@builttocreate/engine-utils 2.10.1 → 2.11.0-1828.beta.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/dist/fieldHelper.js +40 -1
- package/dist/generateReadableId.js +167 -0
- package/dist/index.js +24 -1
- package/dist/joyDocHelper.js +118 -35
- package/dist/tableHelper.js +3 -6
- package/dist/validateReadableId.js +192 -0
- package/package.json +4 -3
package/dist/fieldHelper.js
CHANGED
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.isTargetOptionDeleted = exports.isFieldEmpty = exports.handleMultiSelectOptionToggle = exports.getTemplateWithLookups = exports.getMultiSelectFieldValue = exports.getImportFieldValues = exports.getDefaultOption = exports.getDefaultFieldValuesFromTemplate = exports.getChartFieldValue = exports["default"] = void 0;
|
|
7
|
+
exports.isTargetOptionDeleted = exports.isFieldEmpty = exports.handleMultiSelectOptionToggle = exports.getTemplateWithLookups = exports.getMultiSelectFieldValue = exports.getImportFieldValues = exports.getDefaultOption = exports.getDefaultFieldValuesFromTemplate = exports.getChartFieldValue = exports.flattenSchemaTree = exports["default"] = void 0;
|
|
8
8
|
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
9
9
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
10
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
@@ -298,6 +298,45 @@ var isTargetOptionDeleted = exports.isTargetOptionDeleted = function isTargetOpt
|
|
|
298
298
|
var result = !(undeletedOptions.length > 0);
|
|
299
299
|
return result;
|
|
300
300
|
};
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
*
|
|
304
|
+
* Flattens a nested schema tree into an array of objects and adds a depth property to each object.
|
|
305
|
+
*
|
|
306
|
+
* @param {Object} schemaObj
|
|
307
|
+
* @returns {Array} // An array of objects with the schema's id, depth, and other properties.
|
|
308
|
+
*/
|
|
309
|
+
var flattenSchemaTree = exports.flattenSchemaTree = function flattenSchemaTree(schemaObj) {
|
|
310
|
+
var flattened = [];
|
|
311
|
+
|
|
312
|
+
// Recursive function to traverse the tree.
|
|
313
|
+
function traverse(schemaId, depth, parentId) {
|
|
314
|
+
var node = schemaObj[schemaId];
|
|
315
|
+
if (!node) return;
|
|
316
|
+
|
|
317
|
+
// Create a new object that includes the schema's id and its depth.
|
|
318
|
+
flattened.push(_objectSpread({
|
|
319
|
+
id: schemaId,
|
|
320
|
+
parentId: parentId,
|
|
321
|
+
depth: depth
|
|
322
|
+
}, node));
|
|
323
|
+
|
|
324
|
+
// If the node has children, traverse them with increased depth.
|
|
325
|
+
if (node.children && node.children.length > 0) {
|
|
326
|
+
node.children.forEach(function (childId) {
|
|
327
|
+
return traverse(childId, depth + 1, schemaId);
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Find and traverse each root node.
|
|
333
|
+
Object.keys(schemaObj).forEach(function (schemaId) {
|
|
334
|
+
if (schemaObj[schemaId].root) {
|
|
335
|
+
traverse(schemaId, 0);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
return flattened;
|
|
339
|
+
};
|
|
301
340
|
var _default = exports["default"] = {
|
|
302
341
|
getDefaultOption: getDefaultOption,
|
|
303
342
|
getChartFieldValue: getChartFieldValue,
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.generateReadableId = generateReadableId;
|
|
7
|
+
exports.generateReadableTableColumnId = generateReadableTableColumnId;
|
|
8
|
+
exports.getFieldPositionsCount = getFieldPositionsCount;
|
|
9
|
+
exports.getFieldsCount = getFieldsCount;
|
|
10
|
+
exports.getViewsFieldPositionsCount = getViewsFieldPositionsCount;
|
|
11
|
+
/**
|
|
12
|
+
* Counts fields of a specific type in an array of fields
|
|
13
|
+
*
|
|
14
|
+
* @param {Array} fields - Array of fields that have a .type property
|
|
15
|
+
* @param {String} type - The field type to count
|
|
16
|
+
* @returns {Number} - Count of fields matching the type
|
|
17
|
+
*/
|
|
18
|
+
function countFieldsByType(fields, type) {
|
|
19
|
+
if (!fields || !Array.isArray(fields)) return 0;
|
|
20
|
+
return fields.filter(function (field) {
|
|
21
|
+
return field && field.type === type;
|
|
22
|
+
}).length;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Counts field positions of a specific type in document fields
|
|
27
|
+
*
|
|
28
|
+
* @param {Array} fields - Array of fields
|
|
29
|
+
* @param {String} type - Field type to count
|
|
30
|
+
* @returns {Number} - Count of fields matching the type
|
|
31
|
+
*/
|
|
32
|
+
function getFieldsCount(fields, type) {
|
|
33
|
+
if (!fields || !Array.isArray(fields)) {
|
|
34
|
+
console.warn('getFieldsCount: fields parameter is missing or not an array');
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
return countFieldsByType(fields, type);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Counts field positions of a specific type in an array of pages
|
|
42
|
+
*
|
|
43
|
+
* @param {Array} pages - Array of pages with fieldPositions
|
|
44
|
+
* @param {String} type - Field type to count
|
|
45
|
+
* @returns {Number} - Count of fieldPositions matching the type
|
|
46
|
+
*/
|
|
47
|
+
function getFieldPositionsCount(pages, type) {
|
|
48
|
+
if (!pages || !Array.isArray(pages)) {
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
if (!pages.length) return 0;
|
|
52
|
+
var count = 0;
|
|
53
|
+
pages.forEach(function (page) {
|
|
54
|
+
if (page && page.fieldPositions) {
|
|
55
|
+
count += countFieldsByType(page.fieldPositions, type);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return count;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Counts field positions in views
|
|
63
|
+
*
|
|
64
|
+
* @param {Array} views - Array of views with pages with fieldPositions
|
|
65
|
+
* @param {String} type - Field type to count
|
|
66
|
+
* @returns {Number} - Count of fieldPositions in views matching the type
|
|
67
|
+
*/
|
|
68
|
+
function getViewsFieldPositionsCount(views, type) {
|
|
69
|
+
if (!views || !Array.isArray(views)) {
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
if (!views.length) return 0;
|
|
73
|
+
var count = 0;
|
|
74
|
+
views.forEach(function (view) {
|
|
75
|
+
if (view && view.pages && view.pages.length) {
|
|
76
|
+
count += getFieldPositionsCount(view.pages, type);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
return count;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Gets the next field ID for a specific type by counting existing fields
|
|
84
|
+
* and incrementing. It is built to support any combination of the parameters.
|
|
85
|
+
*
|
|
86
|
+
* But it is recommended to use it with all 3 parts if possible.
|
|
87
|
+
*
|
|
88
|
+
* @param {Object} parts - Object containing fields, pages, and views
|
|
89
|
+
* @param {Array} parts.fields - Array of fields
|
|
90
|
+
* @param {Array} parts.pages - Array of pages with fieldPositions
|
|
91
|
+
* @param {Array} parts.views - Array of views with pages
|
|
92
|
+
* @param {String} type - The field type to count
|
|
93
|
+
* @param {String} prefix - An optional prefix to add to the ID
|
|
94
|
+
* @returns {String} - An ID in the format "prefix{type}{count+1}" (e.g. "text3")
|
|
95
|
+
*/
|
|
96
|
+
function generateReadableId(parts, type) {
|
|
97
|
+
var splitterId = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
|
|
98
|
+
var fields = parts === null || parts === void 0 ? void 0 : parts.fields;
|
|
99
|
+
var pages = parts === null || parts === void 0 ? void 0 : parts.pages;
|
|
100
|
+
var views = parts === null || parts === void 0 ? void 0 : parts.views;
|
|
101
|
+
if (!type) throw new Error('generateReadableId: type is required');
|
|
102
|
+
|
|
103
|
+
// Check if all three parameters are missing
|
|
104
|
+
if (!fields && !pages && !views) {
|
|
105
|
+
throw new Error('generateReadableId: at least one of fields, pages, or views is required');
|
|
106
|
+
}
|
|
107
|
+
if (!fields) console.warn('generateReadableId: fields parameter is missing');
|
|
108
|
+
|
|
109
|
+
// Note: leaving for now until we allow targeting fieldPositions
|
|
110
|
+
// if (pages) count += getFieldPositionsCount(pages, type);
|
|
111
|
+
// if (views && views.length > 1) count += getViewsFieldPositionsCount(views, type);
|
|
112
|
+
|
|
113
|
+
var count = fields.length ? getFieldsCount(fields, type) : 0;
|
|
114
|
+
var readableId = "".concat(type).concat(splitterId).concat(count + 1);
|
|
115
|
+
while (hasDuplicateId(fields, readableId)) {
|
|
116
|
+
count++;
|
|
117
|
+
readableId = "".concat(type).concat(splitterId).concat(count + 1);
|
|
118
|
+
}
|
|
119
|
+
return readableId;
|
|
120
|
+
}
|
|
121
|
+
function hasDuplicateId(items, targetId) {
|
|
122
|
+
return items.some(function (item) {
|
|
123
|
+
return item._id === targetId;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Generates a readable table column ID by counting existing columns
|
|
129
|
+
*
|
|
130
|
+
* @param {String} tableId - The ID of the table (used as prefix)
|
|
131
|
+
* @param {Array} tableColumns - Array of table column objects
|
|
132
|
+
* @returns {String} - An ID in the format "{tableId}Column{count+1}" (e.g. "table1Column1")
|
|
133
|
+
*/
|
|
134
|
+
function generateReadableTableColumnId(tableId, tableColumns, columnId) {
|
|
135
|
+
//Add logic that ensures that created Id is not a duplicate
|
|
136
|
+
if (!tableId) throw new Error('generateReadableTableColumnId: tableId is required');
|
|
137
|
+
if (!columnId) throw new Error('generateReadableTableColumnId: columnId is required');
|
|
138
|
+
if (!tableColumns || !Array.isArray(tableColumns)) {
|
|
139
|
+
console.warn('generateReadableTableColumnId: tableColumns parameter is missing or not an array');
|
|
140
|
+
return "".concat(tableId, "Column1");
|
|
141
|
+
}
|
|
142
|
+
var counts = {};
|
|
143
|
+
var generatedId = null;
|
|
144
|
+
|
|
145
|
+
//Filter out undefined and null values from tableColumns
|
|
146
|
+
var validColumns = tableColumns.filter(function (column) {
|
|
147
|
+
return column !== undefined && column !== null;
|
|
148
|
+
});
|
|
149
|
+
validColumns.forEach(function (col) {
|
|
150
|
+
var type = (col.type || 'unknown').toLowerCase();
|
|
151
|
+
counts[type] = (counts[type] || 0) + 1;
|
|
152
|
+
var readableId = "".concat(type).concat(counts[type]);
|
|
153
|
+
if (col._id === columnId) {
|
|
154
|
+
/**
|
|
155
|
+
* If the generatedReadableId is already present in the tableColumns,
|
|
156
|
+
* we need to increment the count until we find a unique ID.
|
|
157
|
+
* This ensures that the new column ID is unique.
|
|
158
|
+
*/
|
|
159
|
+
while (hasDuplicateId(validColumns, readableId)) {
|
|
160
|
+
counts[type]++;
|
|
161
|
+
readableId = "".concat(type).concat(counts[type]);
|
|
162
|
+
}
|
|
163
|
+
generatedId = readableId;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
return generatedId;
|
|
167
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,18 @@ Object.defineProperty(exports, "generateObjectId", {
|
|
|
31
31
|
return _generateObjectId["default"];
|
|
32
32
|
}
|
|
33
33
|
});
|
|
34
|
+
Object.defineProperty(exports, "generateReadableId", {
|
|
35
|
+
enumerable: true,
|
|
36
|
+
get: function get() {
|
|
37
|
+
return _generateReadableId.generateReadableId;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
Object.defineProperty(exports, "generateReadableTableColumnId", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get: function get() {
|
|
43
|
+
return _generateReadableId.generateReadableTableColumnId;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
34
46
|
exports.paginationHelper = exports.joyDocHelper = void 0;
|
|
35
47
|
Object.defineProperty(exports, "reduxApiMiddleware", {
|
|
36
48
|
enumerable: true,
|
|
@@ -45,6 +57,12 @@ Object.defineProperty(exports, "validateObjectId", {
|
|
|
45
57
|
return _validateObjectId["default"];
|
|
46
58
|
}
|
|
47
59
|
});
|
|
60
|
+
Object.defineProperty(exports, "validateReadableId", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function get() {
|
|
63
|
+
return _validateReadableId["default"];
|
|
64
|
+
}
|
|
65
|
+
});
|
|
48
66
|
var tableHelper = _interopRequireWildcard(require("./tableHelper"));
|
|
49
67
|
exports.tableHelper = tableHelper;
|
|
50
68
|
var chartHelper = _interopRequireWildcard(require("./chartHelper"));
|
|
@@ -66,6 +84,8 @@ var _changedKeys = _interopRequireDefault(require("./changedKeys"));
|
|
|
66
84
|
var _Roles = _interopRequireDefault(require("./constants/Roles"));
|
|
67
85
|
var _generateObjectId = _interopRequireDefault(require("./generateObjectId"));
|
|
68
86
|
var _validateObjectId = _interopRequireDefault(require("./validateObjectId"));
|
|
87
|
+
var _generateReadableId = require("./generateReadableId");
|
|
88
|
+
var _validateReadableId = _interopRequireDefault(require("./validateReadableId"));
|
|
69
89
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
70
90
|
var _default = exports["default"] = {
|
|
71
91
|
fileHelper: fileHelper,
|
|
@@ -81,5 +101,8 @@ var _default = exports["default"] = {
|
|
|
81
101
|
roleHelper: roleHelper,
|
|
82
102
|
Roles: _Roles["default"],
|
|
83
103
|
generateObjectId: _generateObjectId["default"],
|
|
84
|
-
validateObjectId: _validateObjectId["default"]
|
|
104
|
+
validateObjectId: _validateObjectId["default"],
|
|
105
|
+
generateReadableId: _generateReadableId.generateReadableId,
|
|
106
|
+
generateReadableTableColumnId: _generateReadableId.generateReadableTableColumnId,
|
|
107
|
+
validateReadableId: _validateReadableId["default"]
|
|
85
108
|
};
|
package/dist/joyDocHelper.js
CHANGED
|
@@ -9,6 +9,7 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
|
|
|
9
9
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
10
|
var _generateObjectId = _interopRequireDefault(require("./generateObjectId"));
|
|
11
11
|
var _validateObjectId = _interopRequireDefault(require("./validateObjectId"));
|
|
12
|
+
var _generateReadableId = require("./generateReadableId");
|
|
12
13
|
var _PageLayoutModes = _interopRequireDefault(require("./constants/PageLayoutModes"));
|
|
13
14
|
var _FieldPresentationModes = _interopRequireDefault(require("./constants/FieldPresentationModes"));
|
|
14
15
|
var _DocumentTypes = _interopRequireDefault(require("./constants/DocumentTypes"));
|
|
@@ -18,6 +19,7 @@ var _FieldDisplayTypes = _interopRequireDefault(require("./constants/FieldDispla
|
|
|
18
19
|
var _FileViews = _interopRequireDefault(require("./constants/FileViews"));
|
|
19
20
|
var _FormStyleOptions = _interopRequireDefault(require("./constants/FormStyleOptions"));
|
|
20
21
|
var _tableHelper = require("./tableHelper");
|
|
22
|
+
var _validateReadableId = _interopRequireDefault(require("./validateReadableId"));
|
|
21
23
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
22
24
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
23
25
|
/**
|
|
@@ -81,10 +83,48 @@ var getDefaultJoyDoc = exports.getDefaultJoyDoc = function getDefaultJoyDoc() {
|
|
|
81
83
|
identifier: "doc_".concat(id),
|
|
82
84
|
name: 'New Doc',
|
|
83
85
|
files: [getDefaultJoyDocFile(fileDefaults, pageDefaults)],
|
|
84
|
-
fields: []
|
|
86
|
+
fields: [],
|
|
87
|
+
formulas: []
|
|
85
88
|
}, defaults);
|
|
86
89
|
};
|
|
87
90
|
|
|
91
|
+
/**
|
|
92
|
+
* If existing _id is a valid ObjectId, keep it
|
|
93
|
+
* Otherwise, generate a readable ID using the field type
|
|
94
|
+
* with as much data as we are given to determine the proper count.
|
|
95
|
+
*
|
|
96
|
+
* @param {String} existingId - The existing ID to check
|
|
97
|
+
* @param {String} type - The field type for generating readable IDs
|
|
98
|
+
* @param {Object} doc - The document context for readable ID generation
|
|
99
|
+
* @param {Object} generatedIdCounts - Object to track generated ID counts within this operation
|
|
100
|
+
* @returns {String} - Either the existing ObjectId or a new readable ID
|
|
101
|
+
*/
|
|
102
|
+
var getFieldId = function getFieldId(existingId, type, doc) {
|
|
103
|
+
// If existing ID is a valid ObjectId or readableId, maintain it
|
|
104
|
+
//Note: readableId validation is already done when it's being generated
|
|
105
|
+
|
|
106
|
+
if (existingId && (0, _validateObjectId["default"])(existingId)) {
|
|
107
|
+
return existingId;
|
|
108
|
+
}
|
|
109
|
+
if (existingId) return existingId;
|
|
110
|
+
|
|
111
|
+
// Otherwise, generate a readable ID
|
|
112
|
+
if (type) {
|
|
113
|
+
// Get the base count from existing fields
|
|
114
|
+
var baseCount = 0;
|
|
115
|
+
if (doc.fields) baseCount += (0, _generateReadableId.getFieldsCount)(doc.fields, type);
|
|
116
|
+
|
|
117
|
+
// Note: leaving for now until we allow targeting fieldPositions
|
|
118
|
+
// if (doc.pages) baseCount += getFieldPositionsCount(getAllPages(doc), type);
|
|
119
|
+
// if (doc.views && doc.views.length > 1) baseCount += getViewsFieldPositionsCount(getAllViews(doc), type);
|
|
120
|
+
|
|
121
|
+
return "".concat(type).concat(baseCount + 1);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Fallback to ObjectId if we can't generate readable ID
|
|
125
|
+
return (0, _generateObjectId["default"])();
|
|
126
|
+
};
|
|
127
|
+
|
|
88
128
|
/**
|
|
89
129
|
* Get Clean JoyDoc Format
|
|
90
130
|
*
|
|
@@ -105,32 +145,52 @@ var getCleanedJoyDoc = exports.getCleanedJoyDoc = function getCleanedJoyDoc(doc)
|
|
|
105
145
|
nextDoc = _removeOrphanedFields.nextDoc;
|
|
106
146
|
|
|
107
147
|
/**
|
|
108
|
-
* Step 1.1: Replace doc._id if it is not valid
|
|
148
|
+
* Step 1.1: Replace doc._id if it is not valid (always use objectId for documents)
|
|
109
149
|
*/
|
|
110
150
|
if (nextDoc._id && !(0, _validateObjectId["default"])(nextDoc._id)) nextDoc._id = (0, _generateObjectId["default"])();
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Step 1.2: Clean field IDs using simplified approach
|
|
154
|
+
*/
|
|
155
|
+
if (nextDoc.fields && nextDoc.fields.length > 0) {
|
|
156
|
+
nextDoc.fields = nextDoc.fields.map(function (field) {
|
|
157
|
+
var nextField = _objectSpread({}, field);
|
|
158
|
+
|
|
159
|
+
// Clean field _id using simplified approach
|
|
160
|
+
nextField._id = getFieldId(field._id, field.type, nextDoc);
|
|
161
|
+
|
|
162
|
+
// Clean table field rowOrder
|
|
163
|
+
if (field.type === _FieldTypes["default"].table) {
|
|
164
|
+
var cleanedRoworder = (0, _tableHelper.getCleanedRowOrder)(field.rowOrder, field.value);
|
|
165
|
+
nextField.rowOrder = cleanedRoworder;
|
|
166
|
+
}
|
|
167
|
+
return nextField;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
111
170
|
if (nextDoc.files && nextDoc.files.length > 0) {
|
|
112
171
|
nextDoc.files = nextDoc.files.map(function (file) {
|
|
113
172
|
var _nextFile$views;
|
|
114
173
|
var nextFile = _objectSpread({}, file);
|
|
115
174
|
|
|
116
175
|
/**
|
|
117
|
-
* Step 1.
|
|
176
|
+
* Step 1.3: Replace files[x]._id if it is not a valid ObjectId or valid readable ID
|
|
118
177
|
*/
|
|
119
|
-
|
|
178
|
+
|
|
179
|
+
if (nextFile._id && !(0, _validateObjectId["default"])(nextFile._id) && !(0, _validateReadableId["default"])(nextFile._id)) nextFile._id = (0, _generateObjectId["default"])();
|
|
120
180
|
|
|
121
181
|
/**
|
|
122
|
-
* Step 1.
|
|
182
|
+
* Step 1.4: Replace page ids and field ids if they are not valid
|
|
123
183
|
*/
|
|
124
|
-
nextFile.pages = getCleanedJoyDocPages(nextFile.pages);
|
|
184
|
+
nextFile.pages = getCleanedJoyDocPages(nextFile.pages, nextDoc);
|
|
125
185
|
nextFile.pageOrder = cleanPageOrder(getPageOrder(nextFile.pageOrder, nextFile.pages), nextFile.pages);
|
|
126
186
|
|
|
127
187
|
/**
|
|
128
|
-
* Step 1.
|
|
188
|
+
* Step 1.5: Replace view page ids and field ids if they are not valid
|
|
129
189
|
*/
|
|
130
190
|
if ((nextFile === null || nextFile === void 0 || (_nextFile$views = nextFile.views) === null || _nextFile$views === void 0 ? void 0 : _nextFile$views.length) > 0) {
|
|
131
191
|
nextFile.views = nextFile.views.map(function (view) {
|
|
132
192
|
var nextView = _objectSpread({}, view);
|
|
133
|
-
nextView.pages = getCleanedJoyDocPages(nextView.pages);
|
|
193
|
+
nextView.pages = getCleanedJoyDocPages(nextView.pages, nextDoc);
|
|
134
194
|
nextView.pageOrder = cleanPageOrder(getPageOrder(nextView.pageOrder, nextView.pages), nextView.pages);
|
|
135
195
|
return nextView;
|
|
136
196
|
});
|
|
@@ -140,21 +200,6 @@ var getCleanedJoyDoc = exports.getCleanedJoyDoc = function getCleanedJoyDoc(doc)
|
|
|
140
200
|
} else {
|
|
141
201
|
nextDoc.files = [getDefaultJoyDocFile()];
|
|
142
202
|
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Logic below is used to clean the table field rowOrder by removing the
|
|
146
|
-
* deletedRowIds / duplicateRowIds from the rowOrder.
|
|
147
|
-
**/
|
|
148
|
-
if (nextDoc.fields && nextDoc.fields.length > 0) {
|
|
149
|
-
nextDoc.fields = nextDoc.fields.map(function (field) {
|
|
150
|
-
var nextField = _objectSpread({}, field);
|
|
151
|
-
if (field.type === _FieldTypes["default"].table) {
|
|
152
|
-
var cleanedRoworder = (0, _tableHelper.getCleanedRowOrder)(field.rowOrder, field.value);
|
|
153
|
-
nextField.rowOrder = cleanedRoworder;
|
|
154
|
-
}
|
|
155
|
-
return nextField;
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
203
|
return nextDoc;
|
|
159
204
|
};
|
|
160
205
|
|
|
@@ -168,12 +213,27 @@ var removeOrphanedFieldsFromJoydoc = exports.removeOrphanedFieldsFromJoydoc = fu
|
|
|
168
213
|
var nextDoc = _objectSpread({}, doc);
|
|
169
214
|
var associatedFieldIdLookup = {};
|
|
170
215
|
nextDoc === null || nextDoc === void 0 || (_nextDoc$files = nextDoc.files) === null || _nextDoc$files === void 0 || _nextDoc$files.forEach(function (file) {
|
|
171
|
-
var _file$views;
|
|
216
|
+
var _file$header, _file$footer, _file$pages, _file$views;
|
|
217
|
+
/**
|
|
218
|
+
* Header
|
|
219
|
+
*/
|
|
220
|
+
if (file.header) (_file$header = file.header) === null || _file$header === void 0 || (_file$header = _file$header.fieldPositions) === null || _file$header === void 0 || _file$header.forEach(function (fieldPosition) {
|
|
221
|
+
return associatedFieldIdLookup[fieldPosition.field] = true;
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Footer
|
|
226
|
+
*/
|
|
227
|
+
if (file.footer) (_file$footer = file.footer) === null || _file$footer === void 0 || (_file$footer = _file$footer.fieldPositions) === null || _file$footer === void 0 || _file$footer.forEach(function (fieldPosition) {
|
|
228
|
+
return associatedFieldIdLookup[fieldPosition.field] = true;
|
|
229
|
+
});
|
|
230
|
+
|
|
172
231
|
/**
|
|
173
232
|
* Primary view
|
|
174
233
|
*/
|
|
175
|
-
file.pages.forEach(function (page) {
|
|
176
|
-
|
|
234
|
+
(_file$pages = file.pages) === null || _file$pages === void 0 || _file$pages.forEach(function (page) {
|
|
235
|
+
var _page$fieldPositions;
|
|
236
|
+
page === null || page === void 0 || (_page$fieldPositions = page.fieldPositions) === null || _page$fieldPositions === void 0 || _page$fieldPositions.forEach(function (fieldPosition) {
|
|
177
237
|
return associatedFieldIdLookup[fieldPosition.field] = true;
|
|
178
238
|
});
|
|
179
239
|
});
|
|
@@ -184,7 +244,8 @@ var removeOrphanedFieldsFromJoydoc = exports.removeOrphanedFieldsFromJoydoc = fu
|
|
|
184
244
|
(_file$views = file.views) === null || _file$views === void 0 || _file$views.forEach(function (view) {
|
|
185
245
|
var _view$pages;
|
|
186
246
|
view === null || view === void 0 || (_view$pages = view.pages) === null || _view$pages === void 0 || _view$pages.forEach(function (page) {
|
|
187
|
-
|
|
247
|
+
var _page$fieldPositions2;
|
|
248
|
+
page === null || page === void 0 || (_page$fieldPositions2 = page.fieldPositions) === null || _page$fieldPositions2 === void 0 || _page$fieldPositions2.forEach(function (fieldPosition) {
|
|
188
249
|
return associatedFieldIdLookup[fieldPosition.field] = true;
|
|
189
250
|
});
|
|
190
251
|
});
|
|
@@ -215,25 +276,31 @@ var removeOrphanedFieldsFromJoydoc = exports.removeOrphanedFieldsFromJoydoc = fu
|
|
|
215
276
|
* 1. Valid page inside document file.pages array.
|
|
216
277
|
* 2. All id's in pages and fieldPositions are valid format
|
|
217
278
|
*
|
|
218
|
-
* @param {
|
|
279
|
+
* @param {Array} pages
|
|
280
|
+
* @param {Object} doc - The full document (needed for readableId generation)
|
|
219
281
|
* @returns {Object}
|
|
220
282
|
*/
|
|
221
|
-
var getCleanedJoyDocPages = exports.getCleanedJoyDocPages = function getCleanedJoyDocPages(pages) {
|
|
283
|
+
var getCleanedJoyDocPages = exports.getCleanedJoyDocPages = function getCleanedJoyDocPages(pages, doc) {
|
|
222
284
|
if ((pages === null || pages === void 0 ? void 0 : pages.length) > 0) {
|
|
223
285
|
return pages.map(function (page) {
|
|
224
286
|
/**
|
|
225
|
-
* Step 1: Replace pages[x]._id if it is not valid
|
|
287
|
+
* Step 1: Replace pages[x]._id if it is not valid (always use objectId for pages)
|
|
226
288
|
*/
|
|
227
289
|
var nextPage = _objectSpread({}, page);
|
|
228
|
-
if (nextPage._id && !(0, _validateObjectId["default"])(nextPage._id)) nextPage._id = (0, _generateObjectId["default"])();
|
|
290
|
+
if (nextPage._id && !(0, _validateObjectId["default"])(nextPage._id) && !(0, _validateReadableId["default"])(nextPage._id)) nextPage._id = (0, _generateObjectId["default"])();
|
|
229
291
|
if (nextPage.fieldPositions && nextPage.fieldPositions.length > 0) {
|
|
230
292
|
nextPage.fieldPositions = nextPage.fieldPositions.map(function (fieldPosition) {
|
|
231
293
|
/**
|
|
232
294
|
* Step 1.2: Replace fieldPosition _id and field reference if they are not valid
|
|
295
|
+
* Use simplified approach: respect ObjectIds, otherwise generate readable IDs
|
|
233
296
|
*/
|
|
234
297
|
var nextFieldPosition = _objectSpread({}, fieldPosition);
|
|
235
|
-
|
|
236
|
-
|
|
298
|
+
|
|
299
|
+
// Clean fieldPosition _id
|
|
300
|
+
nextFieldPosition._id = nextFieldPosition._id && ((0, _validateObjectId["default"])(nextFieldPosition._id) || (0, _validateReadableId["default"])(nextFieldPosition._id)) ? nextFieldPosition._id : (0, _generateObjectId["default"])();
|
|
301
|
+
|
|
302
|
+
// Clean fieldPosition.field reference
|
|
303
|
+
nextFieldPosition.field = getFieldId(nextFieldPosition.field, fieldPosition.type, doc);
|
|
237
304
|
return nextFieldPosition;
|
|
238
305
|
});
|
|
239
306
|
} else {
|
|
@@ -387,6 +454,7 @@ var getDocumentFromTemplate = exports.getDocumentFromTemplate = function getDocu
|
|
|
387
454
|
var duplicateDocumentPage = exports.duplicateDocumentPage = function duplicateDocumentPage(doc, fileId, pageId) {
|
|
388
455
|
var _nextDoc$fields;
|
|
389
456
|
var pageDefaults = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
457
|
+
var config = arguments.length > 4 ? arguments[4] : undefined;
|
|
390
458
|
var changelogInfo = {
|
|
391
459
|
primaryPages: {
|
|
392
460
|
targetIndex: 0,
|
|
@@ -395,6 +463,7 @@ var duplicateDocumentPage = exports.duplicateDocumentPage = function duplicateDo
|
|
|
395
463
|
viewPages: [],
|
|
396
464
|
fields: []
|
|
397
465
|
};
|
|
466
|
+
var useReadableIds = (config === null || config === void 0 ? void 0 : config.useReadableIds) || false;
|
|
398
467
|
var nextDoc = JSON.parse(JSON.stringify(doc));
|
|
399
468
|
var fileIndex = nextDoc.files.findIndex(function (file) {
|
|
400
469
|
return file._id === fileId;
|
|
@@ -402,7 +471,7 @@ var duplicateDocumentPage = exports.duplicateDocumentPage = function duplicateDo
|
|
|
402
471
|
var newPageId = (0, _generateObjectId["default"])();
|
|
403
472
|
var fieldLookup = {};
|
|
404
473
|
(_nextDoc$fields = nextDoc.fields) === null || _nextDoc$fields === void 0 || _nextDoc$fields.forEach(function (field) {
|
|
405
|
-
|
|
474
|
+
fieldLookup[field._id] = field;
|
|
406
475
|
});
|
|
407
476
|
|
|
408
477
|
/**
|
|
@@ -434,6 +503,7 @@ var duplicateDocumentPage = exports.duplicateDocumentPage = function duplicateDo
|
|
|
434
503
|
var newFieldsLookupByOldId = {};
|
|
435
504
|
var duplicatedFields = [];
|
|
436
505
|
fieldIdsToDuplicate.forEach(function (fieldId) {
|
|
506
|
+
var _nextDoc$files$fileIn, _nextDoc$files$fileIn2;
|
|
437
507
|
/**
|
|
438
508
|
* Why do we check if a new field has already been created?
|
|
439
509
|
*
|
|
@@ -444,9 +514,22 @@ var duplicateDocumentPage = exports.duplicateDocumentPage = function duplicateDo
|
|
|
444
514
|
*/
|
|
445
515
|
if (newFieldsLookupByOldId[fieldId]) return;
|
|
446
516
|
var field = fieldLookup[fieldId];
|
|
517
|
+
|
|
518
|
+
// Skip if field not found in lookup
|
|
519
|
+
if (!field) return;
|
|
520
|
+
|
|
521
|
+
// Generate readable ID using current fields plus already duplicated fields
|
|
522
|
+
var allFields = [].concat((0, _toConsumableArray2["default"])(nextDoc.fields), (0, _toConsumableArray2["default"])(duplicatedFields));
|
|
447
523
|
var duplicateField = _objectSpread(_objectSpread({}, field), {}, {
|
|
448
|
-
_id: (0,
|
|
524
|
+
_id: useReadableIds ? (0, _generateReadableId.generateReadableId)({
|
|
525
|
+
fields: allFields,
|
|
526
|
+
pages: (_nextDoc$files$fileIn = nextDoc.files[fileIndex]) === null || _nextDoc$files$fileIn === void 0 ? void 0 : _nextDoc$files$fileIn.pages,
|
|
527
|
+
views: (_nextDoc$files$fileIn2 = nextDoc.files[fileIndex]) === null || _nextDoc$files$fileIn2 === void 0 ? void 0 : _nextDoc$files$fileIn2.views
|
|
528
|
+
}, field.type) : (0, _generateObjectId["default"])()
|
|
449
529
|
});
|
|
530
|
+
|
|
531
|
+
// Remove formulas property when duplicating
|
|
532
|
+
delete duplicateField.formulas;
|
|
450
533
|
duplicatedFields.push(duplicateField);
|
|
451
534
|
|
|
452
535
|
/**
|
package/dist/tableHelper.js
CHANGED
|
@@ -256,14 +256,10 @@ var handleMoveColumnRight = exports.handleMoveColumnRight = function handleMoveC
|
|
|
256
256
|
* @return {Object}
|
|
257
257
|
*/
|
|
258
258
|
var getDefaultColumnOption = exports.getDefaultColumnOption = function getDefaultColumnOption(value) {
|
|
259
|
-
var color = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
260
259
|
return {
|
|
261
260
|
_id: (0, _generateObjectId["default"])(),
|
|
262
261
|
value: value || 'Option',
|
|
263
|
-
deleted: false
|
|
264
|
-
styles: {
|
|
265
|
-
backgroundColor: color
|
|
266
|
-
}
|
|
262
|
+
deleted: false
|
|
267
263
|
};
|
|
268
264
|
};
|
|
269
265
|
|
|
@@ -422,7 +418,7 @@ var getDefaultDropdownColumn = exports.getDefaultDropdownColumn = function getDe
|
|
|
422
418
|
*/
|
|
423
419
|
var getDefaultMultiSelectColumn = exports.getDefaultMultiSelectColumn = function getDefaultMultiSelectColumn() {
|
|
424
420
|
var defaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
425
|
-
var options = defaults.options || [getDefaultColumnOption('Option 1'
|
|
421
|
+
var options = defaults.options || [getDefaultColumnOption('Option 1'), getDefaultColumnOption('Option 2'), getDefaultColumnOption('Option 3')];
|
|
426
422
|
return _objectSpread({
|
|
427
423
|
_id: (0, _generateObjectId["default"])(),
|
|
428
424
|
type: _FieldTableColumnTypes["default"].multiSelect,
|
|
@@ -761,6 +757,7 @@ var generateTableLookup = exports.generateTableLookup = function generateTableLo
|
|
|
761
757
|
if (!(row !== null && row !== void 0 && row.cells)) console.warn("Missing 'cells' in row: ".concat(row._id));
|
|
762
758
|
tableColumns.forEach(function (column) {
|
|
763
759
|
if (!column.operand) return;
|
|
760
|
+
// eslint-disable-next-line no-console
|
|
764
761
|
if (!row) console.warn("Row via column ".concat(column === null || column === void 0 ? void 0 : column._id, " is undefined."));
|
|
765
762
|
var cellKey = "".concat(column.operand).concat(rowIndex + 1);
|
|
766
763
|
var cellRawValue = row && row !== null && row !== void 0 && row.cells && row.cells[column._id] ? row.cells[column._id] : undefined;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports["default"] = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
10
|
+
var _fieldHelper = require("./fieldHelper");
|
|
11
|
+
var _FieldTypes = _interopRequireDefault(require("./constants/FieldTypes"));
|
|
12
|
+
// Check if value follows a valid readableId pattern for use in JavaScript formulas
|
|
13
|
+
// Note to test this please run npm test src/validateReadableId.test.js
|
|
14
|
+
|
|
15
|
+
// JavaScript reserved words and future reserved words
|
|
16
|
+
var JS_RESERVED_WORDS = new Set([
|
|
17
|
+
// ES6 Keywords
|
|
18
|
+
'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'export', 'extends', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'new', 'return', 'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield',
|
|
19
|
+
// ES6 Future Reserved Words
|
|
20
|
+
'enum', 'implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', 'await', 'async',
|
|
21
|
+
// Literals
|
|
22
|
+
'null', 'true', 'false', 'undefined', 'NaN', 'Infinity']);
|
|
23
|
+
|
|
24
|
+
// Common Excel function names (subset of most commonly used)
|
|
25
|
+
var EXCEL_FUNCTIONS = new Set([
|
|
26
|
+
// Math functions
|
|
27
|
+
'sum', 'average', 'count', 'max', 'min', 'round', 'roundup', 'rounddown', 'ceiling', 'floor', 'abs', 'sign', 'sqrt', 'power', 'exp', 'ln', 'log', 'log10', 'mod', 'quotient', 'product', 'sumif', 'countif', 'averageif', 'sumifs', 'countifs', 'averageifs', 'maxifs', 'minifs', 'subtotal', 'aggregate', 'rand', 'randbetween', 'pi', 'degrees', 'radians', 'fact', 'combin', 'permut', 'gcd', 'lcm', 'mround', 'multinomial', 'seriessum', 'sqrtpi', 'sumproduct', 'sumsq', 'sumx2my2', 'sumx2py2', 'sumxmy2',
|
|
28
|
+
// Text functions
|
|
29
|
+
'concatenate', 'concat', 'left', 'right', 'mid', 'len', 'lower', 'upper', 'proper', 'trim', 'substitute', 'replace', 'find', 'search', 'text', 'value', 'clean', 'code', 'char', 'exact', 'rept', 'fixed', 'dollar', 'textjoin', 'textbefore', 'textafter', 'textsplit', 'unichar', 'unicode',
|
|
30
|
+
// Date functions
|
|
31
|
+
'date', 'today', 'now', 'year', 'month', 'day', 'hour', 'minute', 'second', 'weekday', 'weeknum', 'datedif', 'datevalue', 'timevalue', 'days', 'days360', 'edate', 'eomonth', 'networkdays', 'workday', 'isoweeknum', 'yearfrac',
|
|
32
|
+
// Logical functions
|
|
33
|
+
'if', 'and', 'or', 'not', 'xor', 'iferror', 'ifna', 'ifs', 'switch', 'true', 'false',
|
|
34
|
+
// Lookup functions
|
|
35
|
+
'vlookup', 'hlookup', 'lookup', 'match', 'index', 'choose', 'offset', 'indirect', 'row', 'column', 'rows', 'columns', 'transpose', 'unique', 'filter', 'sort', 'sortby', 'xlookup', 'xmatch',
|
|
36
|
+
// Statistical functions
|
|
37
|
+
'median', 'mode', 'stdev', 'var', 'correl', 'forecast', 'trend', 'growth', 'linest', 'logest', 'slope', 'intercept', 'pearson', 'rsq', 'steyx', 'kurt', 'skew', 'rank', 'percentile', 'quartile', 'percentrank', 'large', 'small', 'standardize', 'ztest', 'ttest', 'ftest', 'chisq', 'norm', 'lognorm', 'expon', 'gamma', 'beta', 'binom', 'poisson', 'weibull', 'hypgeom', 'negbinom', 'geomean', 'harmean', 'devsq', 'avedev', 'confidence',
|
|
38
|
+
// Financial functions
|
|
39
|
+
'pv', 'fv', 'pmt', 'rate', 'nper', 'irr', 'npv', 'mirr', 'xirr', 'xnpv', 'sln', 'syd', 'ddb', 'vdb', 'ipmt', 'ppmt', 'cumipmt', 'cumprinc', 'price', 'yield', 'duration', 'mduration', 'disc', 'intrate', 'received', 'accrint', 'accrintm', 'coupdaybs', 'coupdays', 'coupdaysnc', 'coupncd', 'coupnum', 'couppcd', 'tbilleq', 'tbillprice', 'tbillyield',
|
|
40
|
+
// Information functions
|
|
41
|
+
'isblank', 'iserror', 'isna', 'isnumber', 'istext', 'islogical', 'isref', 'isformula', 'cell', 'info', 'type', 'na', 'error', 'iseven', 'isodd', 'n', 'sheet', 'sheets',
|
|
42
|
+
// Database functions
|
|
43
|
+
'dsum', 'daverage', 'dcount', 'dcounta', 'dmax', 'dmin', 'dproduct', 'dstdev', 'dstdevp', 'dvar', 'dvarp', 'dget',
|
|
44
|
+
// Engineering functions
|
|
45
|
+
'convert', 'bin2dec', 'bin2hex', 'bin2oct', 'dec2bin', 'dec2hex', 'dec2oct', 'hex2bin', 'hex2dec', 'hex2oct', 'oct2bin', 'oct2dec', 'oct2hex', 'complex', 'imabs', 'imaginary', 'imargument', 'imconjugate', 'imcos', 'imdiv', 'imexp', 'imln', 'imlog10', 'imlog2', 'impower', 'improduct', 'imreal', 'imsin', 'imsqrt', 'imsub', 'imsum', 'delta', 'erf', 'erfc', 'gestep', 'besseli', 'besselj', 'besselk', 'bessely',
|
|
46
|
+
// Array functions (newer)
|
|
47
|
+
'sequence', 'randarray', 'tocol', 'torow', 'wrapcols', 'wraprows', 'take', 'drop', 'expand', 'choosecols', 'chooserows', 'vstack', 'hstack']);
|
|
48
|
+
|
|
49
|
+
// JavaScript built-in object methods and properties
|
|
50
|
+
var JS_BUILTIN_NAMES = new Set([
|
|
51
|
+
// Number methods
|
|
52
|
+
'parseFloat', 'parseInt', 'isFinite', 'isInteger', 'isNaN', 'isSafeInteger', 'toExponential', 'toFixed', 'toPrecision', 'toString', 'valueOf',
|
|
53
|
+
// String methods
|
|
54
|
+
'charAt', 'charCodeAt', 'codePointAt', 'concat', 'endsWith', 'includes', 'indexOf', 'lastIndexOf', 'localeCompare', 'match', 'matchAll', 'normalize', 'padEnd', 'padStart', 'repeat', 'replace', 'replaceAll', 'search', 'slice', 'split', 'startsWith', 'substring', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toUpperCase', 'trim', 'trimEnd', 'trimStart', 'length',
|
|
55
|
+
// Array methods
|
|
56
|
+
'from', 'isArray', 'of', 'concat', 'copyWithin', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'flat', 'flatMap', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'unshift', 'values',
|
|
57
|
+
// Object methods
|
|
58
|
+
'assign', 'create', 'defineProperties', 'defineProperty', 'entries', 'freeze', 'fromEntries', 'getOwnPropertyDescriptor', 'getOwnPropertyDescriptors', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'getPrototypeOf', 'hasOwnProperty', 'is', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'preventExtensions', 'propertyIsEnumerable', 'seal', 'setPrototypeOf', 'values',
|
|
59
|
+
// Global properties
|
|
60
|
+
'constructor', 'prototype', '__proto__']);
|
|
61
|
+
|
|
62
|
+
// Custom reserved words from the spec
|
|
63
|
+
var CUSTOM_RESERVED_WORDS = new Set([
|
|
64
|
+
// Booleans
|
|
65
|
+
'checked', 'unchecked', 'enabled', 'disabled', 'on', 'off', 'yes', 'no',
|
|
66
|
+
// Self referencing
|
|
67
|
+
'current', 'self'
|
|
68
|
+
|
|
69
|
+
// Note: 'index' is already in EXCEL_FUNCTIONS, so it's not included here to avoid duplicate warnings
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
// Common JoyDoc properties (based on the codebase analysis)
|
|
73
|
+
var JOYDOC_PROPERTIES = new Set(['_id', 'identifier', 'name', 'type', 'files', 'fields', 'pages', 'pageOrder', 'fieldPositions', 'value', 'file', 'field', 'views', 'source', 'template', 'createdOn', 'updatedOn', 'deleted', 'width', 'height', 'rowHeight', 'cols', 'layout', 'presentation', 'padding', 'styles', 'margin', 'rowOrder', 'columnOrder', 'columns', 'rows', 'options', 'required', 'readOnly', 'disabled', 'hidden', 'validation', 'formula', 'format', 'placeholder', 'defaultValue', 'minValue', 'maxValue', 'minLength', 'maxLength', 'pattern', 'title', 'description', 'displayType', 'x', 'y', 'w', 'h']);
|
|
74
|
+
|
|
75
|
+
// Field types from FieldTypes.js
|
|
76
|
+
// Note: These are removed from validation because generateReadableId uses them as prefixes
|
|
77
|
+
// e.g., "text1", "number1", etc. The bare field type names should be allowed.
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Validates if a string can be used as a JavaScript identifier
|
|
81
|
+
* and doesn't conflict with reserved words
|
|
82
|
+
*
|
|
83
|
+
* @param {*} readableId - The ID to validate
|
|
84
|
+
* @returns {boolean} - True if valid, false otherwise
|
|
85
|
+
*/
|
|
86
|
+
var _default = exports["default"] = function _default(readableId, fields, tableColumns, fieldId) {
|
|
87
|
+
// Must be a non-empty string
|
|
88
|
+
if (typeof readableId !== 'string' || readableId.length === 0) {
|
|
89
|
+
console.warn("validateReadableId: Invalid input - expected non-empty string, got ".concat(typeof readableId === 'string' ? 'empty string' : (0, _typeof2["default"])(readableId)));
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Must not be parseable as a number (but check for Infinity as a special case)
|
|
94
|
+
if (readableId !== 'Infinity' && !isNaN(readableId)) {
|
|
95
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - cannot be a numeric value"));
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Must match the pattern: start with letter or underscore, followed by letters, numbers, or underscores
|
|
100
|
+
var identifierPattern = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
101
|
+
if (!identifierPattern.test(readableId)) {
|
|
102
|
+
if (/^[0-9]/.test(readableId)) {
|
|
103
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - identifiers cannot start with a number"));
|
|
104
|
+
} else if (/[^a-zA-Z0-9_]/.test(readableId)) {
|
|
105
|
+
var invalidChars = readableId.match(/[^a-zA-Z0-9_]/g);
|
|
106
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - contains invalid characters: ").concat((0, _toConsumableArray2["default"])(new Set(invalidChars)).join(', ')));
|
|
107
|
+
} else {
|
|
108
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - must start with a letter or underscore and contain only letters, numbers, and underscores"));
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Convert to lowercase for case-insensitive checking
|
|
114
|
+
var lowercaseId = readableId.toLowerCase();
|
|
115
|
+
|
|
116
|
+
// Check in order of precedence:
|
|
117
|
+
|
|
118
|
+
// 1. JavaScript reserved words (highest priority)
|
|
119
|
+
if (JS_RESERVED_WORDS.has(readableId) || JS_RESERVED_WORDS.has(lowercaseId)) {
|
|
120
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - it's a JavaScript reserved word"));
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 2. JavaScript built-in names
|
|
125
|
+
if (JS_BUILTIN_NAMES.has(readableId)) {
|
|
126
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - it's a JavaScript built-in method or property"));
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// 3. JoyDoc properties
|
|
131
|
+
if (JOYDOC_PROPERTIES.has(readableId)) {
|
|
132
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - it's a JoyDoc property name"));
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 4. Custom reserved words (lower priority than JoyDoc since 'index' can be more specific)
|
|
137
|
+
if (CUSTOM_RESERVED_WORDS.has(lowercaseId)) {
|
|
138
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - it's a reserved word (boolean/self-referencing term)"));
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 5. Excel functions (lowest priority since it has many general terms)
|
|
143
|
+
if (EXCEL_FUNCTIONS.has(lowercaseId)) {
|
|
144
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - it's an Excel function name"));
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
//6. Check for duplicates in readableIds
|
|
149
|
+
|
|
150
|
+
if (Array.isArray(fields)) {
|
|
151
|
+
//DuplicateId check for fieldIds
|
|
152
|
+
var duplicateField = fields.find(function (field) {
|
|
153
|
+
return field._id === readableId;
|
|
154
|
+
});
|
|
155
|
+
if (duplicateField) {
|
|
156
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - it already exists in fields"));
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* DuplicateId check for nested tables of collection fields
|
|
162
|
+
* When readableIds for nestedTables are passed in, we need the fieldId to retrieve the collection fields that houses the nestedTable
|
|
163
|
+
*/
|
|
164
|
+
if (fieldId) {
|
|
165
|
+
var targetField = fields.find(function (field) {
|
|
166
|
+
return field._id === fieldId;
|
|
167
|
+
});
|
|
168
|
+
if ((targetField === null || targetField === void 0 ? void 0 : targetField.type) === _FieldTypes["default"].collection) {
|
|
169
|
+
var flattenedSchema = (0, _fieldHelper.flattenSchemaTree)(targetField.schema);
|
|
170
|
+
var readableIdExists = flattenedSchema.some(function (schema) {
|
|
171
|
+
return schema.id === readableId;
|
|
172
|
+
});
|
|
173
|
+
if (readableIdExists) {
|
|
174
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - it already exists in fields"));
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
//DuplicateId check for columnIds
|
|
182
|
+
if (tableColumns && Array.isArray(tableColumns)) {
|
|
183
|
+
var duplicateColumnId = tableColumns.find(function (column) {
|
|
184
|
+
return column._id === readableId;
|
|
185
|
+
});
|
|
186
|
+
if (duplicateColumnId) {
|
|
187
|
+
console.warn("validateReadableId: \"".concat(readableId, "\" is invalid - it already exists in fields"));
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return true;
|
|
192
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@builttocreate/engine-utils",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Utility library for
|
|
3
|
+
"version": "2.11.0-1828.beta.0",
|
|
4
|
+
"description": "Utility library for common logic shared across web and mobile",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist/**/*",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"homepage": "https://github.com/zionlabs/engine-utils#readme",
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@babel/cli": "^7.
|
|
33
|
+
"@babel/cli": "^7.27.2",
|
|
34
34
|
"@babel/core": "^7.12.10",
|
|
35
35
|
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
|
36
36
|
"@babel/plugin-transform-regenerator": "^7.12.1",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@babel/polyfill": "^7.12.1",
|
|
51
|
+
"@builttocreate/engine-utils": "2.11.0-beta.7",
|
|
51
52
|
"@builttocreate/hot-formula-parser": "^5.0.1",
|
|
52
53
|
"cross-env": "^7.0.3",
|
|
53
54
|
"moment": "^2.29.4"
|