@openforis/arena-core 2.16.3 → 2.16.5
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/esm/node/node.js +1 -0
- package/dist/esm/node/node.js.map +1 -1
- package/dist/esm/record/_records/recordGetters.js +17 -13
- package/dist/esm/record/_records/recordGetters.js.map +1 -1
- package/dist/esm/record/recordCloner.js +14 -2
- package/dist/esm/record/recordCloner.js.map +1 -1
- package/dist/esm/record/recordFixer.js +1 -8
- package/dist/esm/record/recordFixer.js.map +1 -1
- package/dist/esm/record/recordNodesUpdater/recordNodesCreator.js +6 -0
- package/dist/esm/record/recordNodesUpdater/recordNodesCreator.js.map +1 -1
- package/dist/esm/record/recordUpdater.js +46 -4
- package/dist/esm/record/recordUpdater.js.map +1 -1
- package/dist/esm/record/recordValidator/attributeKeyValidator.js +2 -1
- package/dist/esm/record/recordValidator/attributeKeyValidator.js.map +1 -1
- package/dist/esm/record/records.js +2 -1
- package/dist/esm/record/records.js.map +1 -1
- package/dist/node/node.d.ts +2 -1
- package/dist/node/node.js +1 -0
- package/dist/node/node.js.map +1 -1
- package/dist/record/_records/recordGetters.d.ts +4 -0
- package/dist/record/_records/recordGetters.js +19 -14
- package/dist/record/_records/recordGetters.js.map +1 -1
- package/dist/record/recordCloner.js +14 -2
- package/dist/record/recordCloner.js.map +1 -1
- package/dist/record/recordFixer.js +1 -8
- package/dist/record/recordFixer.js.map +1 -1
- package/dist/record/recordNodesUpdater/recordNodesCreator.js +6 -0
- package/dist/record/recordNodesUpdater/recordNodesCreator.js.map +1 -1
- package/dist/record/recordUpdater.js +46 -4
- package/dist/record/recordUpdater.js.map +1 -1
- package/dist/record/recordValidator/attributeKeyValidator.js +2 -1
- package/dist/record/recordValidator/attributeKeyValidator.js.map +1 -1
- package/dist/record/records.d.ts +2 -1
- package/dist/record/records.js +1 -0
- package/dist/record/records.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordCloner.js","sourceRoot":"","sources":["../../src/record/recordCloner.ts"],"names":[],"mappings":"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","sourcesContent":["import { ArenaRecordNode, NodeValues, Nodes } from '../node'\nimport { NodeKeys, NodeMetaKeys } from '../node/node'\nimport { NodeDefCode, NodeDefType, NodeDefs } from '../nodeDef'\nimport { Survey, Surveys } from '../survey'\nimport { Dates, Objects, UUIDs } from '../utils'\nimport { Validation } from '../validation'\nimport { ArenaRecord } from './record'\nimport { RecordFixer } from './recordFixer'\nimport { RecordUpdateResult } from './recordNodesUpdater'\nimport { RecordValidations } from './recordValidations'\nimport { Records } from './records'\n\ntype OldUuidToNewUuidMap = {\n [key: string]: string\n}\n\nconst assignNewUuidsToNodes = (params: {\n record: ArenaRecord\n sideEffect: boolean\n}): { newNodeUuidsByOldUuid: OldUuidToNewUuidMap; newFileUuidsByOldUuid: OldUuidToNewUuidMap; record: ArenaRecord } => {\n const { record, sideEffect } = params\n\n // generate a new uuid for each node\n const newNodeUuidsByOldUuid: OldUuidToNewUuidMap = {}\n const newFileUuidsByOldUuid: OldUuidToNewUuidMap = {}\n\n // sort nodes before removing the id, to preserve their hierarchy (faster than comparing each meta.h property)\n const nodesArray = Records.getNodesArray(record).sort(\n (nodeA: ArenaRecordNode, nodeB: ArenaRecordNode): number =>\n Nodes.getHierarchy(nodeA).length - Nodes.getHierarchy(nodeB).length\n )\n\n const recordUpdated = sideEffect ? record : { ...record }\n\n const nodes = recordUpdated.nodes ?? {}\n const nodesUpdated = sideEffect ? nodes : { ...nodes }\n\n // update nodes recordUuid and properties (it does side effect on nodes)\n nodesArray.forEach((node) => {\n let nodeUpdated = sideEffect ? node : { ...node }\n nodeUpdated.recordUuid = record.uuid\n nodeUpdated.dateCreated = nodeUpdated.dateModified = Dates.nowFormattedForStorage()\n\n const oldUuid = node.uuid\n const newUuid = UUIDs.v4()\n newNodeUuidsByOldUuid[oldUuid] = newUuid\n\n nodeUpdated.uuid = newUuid\n // consider every node as just created node\n delete nodeUpdated.id\n nodeUpdated.created = true // this flag will be used by the RDB generator)\n\n // update internal node uuids, meta hierarchy, file uuid (if any)\n const parentUuid = node.parentUuid\n if (parentUuid) {\n nodeUpdated.parentUuid = newNodeUuidsByOldUuid[parentUuid]\n }\n const hierarchy = node.meta?.h ?? []\n if (hierarchy.length > 0) {\n const hierarchyUpdated = hierarchy.map((ancestorUuid) => newNodeUuidsByOldUuid[ancestorUuid])\n nodeUpdated = Objects.assocPath({\n obj: nodeUpdated,\n path: [NodeKeys.meta, NodeMetaKeys.h],\n value: hierarchyUpdated,\n sideEffect,\n })\n }\n // assign new file uuid (file should be cloned elsewhere)\n const fileUuid = NodeValues.getFileUuid(node)\n if (fileUuid) {\n const newFileUuid = UUIDs.v4()\n nodeUpdated = Objects.assocPath({\n obj: nodeUpdated,\n path: [NodeKeys.value, NodeValues.ValuePropsFile.fileUuid],\n value: newFileUuid,\n })\n newFileUuidsByOldUuid[fileUuid] = newFileUuid\n }\n\n delete nodesUpdated[oldUuid]\n nodesUpdated[newUuid] = nodeUpdated\n })\n\n recordUpdated.nodes = nodesUpdated\n\n return { newNodeUuidsByOldUuid, newFileUuidsByOldUuid, record: recordUpdated }\n}\n\nconst assignNewUuidsToValidation = (params: {\n validation: Validation\n newNodeUuidsByOldUuid: OldUuidToNewUuidMap\n sideEffect: boolean\n}): Validation => {\n const { validation, newNodeUuidsByOldUuid, sideEffect } = params\n\n const validationFields = validation?.fields\n if (!validationFields) return validation\n\n const validationFieldsUpdated = sideEffect ? validationFields : { ...validationFields }\n\n Object.entries(validationFields).forEach(([oldFieldKey, validationField]) => {\n let newFieldKey\n if (oldFieldKey.startsWith(RecordValidations.prefixValidationFieldChildrenCount)) {\n const oldParentUuid = oldFieldKey.substring(\n RecordValidations.prefixValidationFieldChildrenCount.length,\n oldFieldKey.lastIndexOf('_')\n )\n const newParentUuid = newNodeUuidsByOldUuid[oldParentUuid]\n newFieldKey = oldFieldKey.replace(oldParentUuid, newParentUuid)\n } else {\n newFieldKey = newNodeUuidsByOldUuid[oldFieldKey]\n }\n if (newFieldKey) {\n validationFieldsUpdated[newFieldKey] = validationField\n }\n delete validationFieldsUpdated[oldFieldKey]\n })\n return Objects.assoc({\n obj: validation,\n prop: 'fields',\n value: validationFieldsUpdated,\n sideEffect,\n })\n}\n\nconst assignNewUuids = (params: {\n record: ArenaRecord\n sideEffect: boolean\n}): { newNodeUuidsByOldUuid: OldUuidToNewUuidMap; newFileUuidsByOldUuid: OldUuidToNewUuidMap; record: ArenaRecord } => {\n const { record, sideEffect } = params\n let recordUpdated = sideEffect ? record : { ...record }\n recordUpdated.uuid = UUIDs.v4()\n\n const {\n newNodeUuidsByOldUuid,\n newFileUuidsByOldUuid,\n record: recordUpdatedUuids,\n } = assignNewUuidsToNodes({ record: recordUpdated, sideEffect })\n\n recordUpdated = recordUpdatedUuids\n\n const { validation } = recordUpdated\n if (validation) {\n const validationUpdated = assignNewUuidsToValidation({\n validation,\n newNodeUuidsByOldUuid,\n sideEffect,\n })\n recordUpdated = Objects.assoc({ obj: recordUpdated, prop: 'validation', value: validationUpdated, sideEffect })\n }\n // re-build nodes index\n const nodes = recordUpdated.nodes!\n delete recordUpdated._nodesIndex\n delete recordUpdated.nodes\n recordUpdated = Records.addNodes(nodes, { sideEffect, sortNodes: true })(recordUpdated)\n\n return { newNodeUuidsByOldUuid, newFileUuidsByOldUuid, record: recordUpdated }\n}\n\nconst removeExcludedNodes = (params: {\n survey: Survey\n record: ArenaRecord\n sideEffect: boolean\n}): RecordUpdateResult => {\n const { survey, record, sideEffect } = params\n const cycle = record.cycle!\n const result = new RecordUpdateResult({ record })\n Surveys.visitDescendantsAndSelfNodeDef({\n survey,\n cycle,\n nodeDef: Surveys.getNodeDefRoot({ survey }),\n visitor: (nodeDef) => {\n const hasAncestorCodeDefExcludedInClone =\n nodeDef.type === NodeDefType.code &&\n Surveys.getNodeDefAncestorCodes({ survey, nodeDef: nodeDef as NodeDefCode }).some(NodeDefs.isExcludedInClone)\n\n if (\n !NodeDefs.isInCycle(cycle)(nodeDef) ||\n NodeDefs.isExcludedInClone(nodeDef) ||\n hasAncestorCodeDefExcludedInClone\n ) {\n const nodesToDelete = Records.getNodesByDefUuid(nodeDef.uuid)(result.record)\n if (nodesToDelete.length > 0) {\n const partialUpdateResult = Records.removeNodes(\n nodesToDelete.map((node) => node.uuid),\n { sideEffect }\n )(result.record)\n result.merge(partialUpdateResult)\n }\n }\n },\n })\n return result\n}\n\nconst cloneRecord = (params: { survey: Survey; record: ArenaRecord; cycleTo: string; sideEffect?: boolean }) => {\n const { survey, record, cycleTo, sideEffect = false } = params\n\n const recordUpdated = sideEffect ? record : { ...record }\n recordUpdated.cycle = cycleTo\n recordUpdated.dateCreated = recordUpdated.dateModified = Dates.nowFormattedForStorage()\n delete recordUpdated.id\n\n // delete nodes not included in clone\n const updateResult = new RecordUpdateResult({ record: recordUpdated })\n updateResult.merge(removeExcludedNodes({ survey, record: updateResult.record, sideEffect }))\n updateResult.merge(RecordFixer.insertMissingSingleNodes({ survey, record: updateResult.record, sideEffect }))\n\n // assign new UUIDs with side effect on record and nodes, faster when record is big\n const {\n newNodeUuidsByOldUuid,\n newFileUuidsByOldUuid,\n record: recordUpdatedUuids,\n } = assignNewUuids({ record: updateResult.record, sideEffect })\n\n updateResult.merge(new RecordUpdateResult({ record: recordUpdatedUuids }))\n\n return { record: updateResult.record, newNodeUuidsByOldUuid, newFileUuidsByOldUuid }\n}\n\nexport const RecordCloner = {\n cloneRecord,\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recordCloner.js","sourceRoot":"","sources":["../../src/record/recordCloner.ts"],"names":[],"mappings":"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","sourcesContent":["import { ArenaRecordNode, NodeValues, Nodes } from '../node'\nimport { NodeKeys, NodeMetaKeys } from '../node/node'\nimport { NodeDefCode, NodeDefType, NodeDefs } from '../nodeDef'\nimport { Survey, Surveys } from '../survey'\nimport { Dates, Objects, UUIDs } from '../utils'\nimport { Validation } from '../validation'\nimport { ArenaRecord } from './record'\nimport { RecordFixer } from './recordFixer'\nimport { RecordUpdateResult } from './recordNodesUpdater'\nimport { RecordValidations } from './recordValidations'\nimport { Records } from './records'\n\ntype OldUuidToNewUuidMap = {\n [key: string]: string\n}\n\nconst assignNewUuidsToNodes = (params: {\n record: ArenaRecord\n sideEffect: boolean\n}): { newNodeUuidsByOldUuid: OldUuidToNewUuidMap; newFileUuidsByOldUuid: OldUuidToNewUuidMap; record: ArenaRecord } => {\n const { record, sideEffect } = params\n\n // generate a new uuid for each node\n const newNodeUuidsByOldUuid: OldUuidToNewUuidMap = {}\n const newFileUuidsByOldUuid: OldUuidToNewUuidMap = {}\n\n // sort nodes before removing the id, to preserve their hierarchy (faster than comparing each meta.h property)\n const nodesArray = Records.getNodesArray(record).sort(\n (nodeA: ArenaRecordNode, nodeB: ArenaRecordNode): number =>\n Nodes.getHierarchy(nodeA).length - Nodes.getHierarchy(nodeB).length\n )\n\n const recordUpdated = sideEffect ? record : { ...record }\n\n const nodes = recordUpdated.nodes ?? {}\n const nodesUpdated = sideEffect ? nodes : { ...nodes }\n\n // new uuids generated in advance: meta.hCode can reference nodes cloned later (e.g. sibling code attributes)\n for (const node of nodesArray) {\n newNodeUuidsByOldUuid[node.uuid] = UUIDs.v4()\n }\n\n // update nodes recordUuid and properties (it does side effect on nodes)\n nodesArray.forEach((node) => {\n let nodeUpdated = sideEffect ? node : { ...node }\n nodeUpdated.recordUuid = record.uuid\n nodeUpdated.dateCreated = nodeUpdated.dateModified = Dates.nowFormattedForStorage()\n\n const oldUuid = node.uuid\n const newUuid = newNodeUuidsByOldUuid[oldUuid]\n nodeUpdated.uuid = newUuid\n // consider every node as just created node\n delete nodeUpdated.id\n nodeUpdated.created = true // this flag will be used by the RDB generator)\n\n // update internal node uuids, meta hierarchy, file uuid (if any)\n const parentUuid = node.parentUuid\n if (parentUuid) {\n nodeUpdated.parentUuid = newNodeUuidsByOldUuid[parentUuid]\n }\n const hierarchy = node.meta?.h ?? []\n if (hierarchy.length > 0) {\n const hierarchyUpdated = hierarchy.map((ancestorUuid) => newNodeUuidsByOldUuid[ancestorUuid])\n nodeUpdated = Objects.assocPath({\n obj: nodeUpdated,\n path: [NodeKeys.meta, NodeMetaKeys.h],\n value: hierarchyUpdated,\n sideEffect,\n })\n }\n const hierarchyCode = Nodes.getHierarchyCode(node)\n if (hierarchyCode.length > 0) {\n nodeUpdated = Objects.assocPath({\n obj: nodeUpdated,\n path: [NodeKeys.meta, NodeMetaKeys.hCode],\n value: hierarchyCode.map((ancestorCodeUuid) => newNodeUuidsByOldUuid[ancestorCodeUuid]),\n sideEffect,\n })\n }\n // assign new file uuid (file should be cloned elsewhere)\n const fileUuid = NodeValues.getFileUuid(node)\n if (fileUuid) {\n const newFileUuid = UUIDs.v4()\n nodeUpdated = Objects.assocPath({\n obj: nodeUpdated,\n path: [NodeKeys.value, NodeValues.ValuePropsFile.fileUuid],\n value: newFileUuid,\n })\n newFileUuidsByOldUuid[fileUuid] = newFileUuid\n }\n\n delete nodesUpdated[oldUuid]\n nodesUpdated[newUuid] = nodeUpdated\n })\n\n recordUpdated.nodes = nodesUpdated\n\n return { newNodeUuidsByOldUuid, newFileUuidsByOldUuid, record: recordUpdated }\n}\n\nconst assignNewUuidsToValidation = (params: {\n validation: Validation\n newNodeUuidsByOldUuid: OldUuidToNewUuidMap\n sideEffect: boolean\n}): Validation => {\n const { validation, newNodeUuidsByOldUuid, sideEffect } = params\n\n const validationFields = validation?.fields\n if (!validationFields) return validation\n\n const validationFieldsUpdated = sideEffect ? validationFields : { ...validationFields }\n\n Object.entries(validationFields).forEach(([oldFieldKey, validationField]) => {\n let newFieldKey\n if (oldFieldKey.startsWith(RecordValidations.prefixValidationFieldChildrenCount)) {\n const oldParentUuid = oldFieldKey.substring(\n RecordValidations.prefixValidationFieldChildrenCount.length,\n oldFieldKey.lastIndexOf('_')\n )\n const newParentUuid = newNodeUuidsByOldUuid[oldParentUuid]\n newFieldKey = oldFieldKey.replace(oldParentUuid, newParentUuid)\n } else {\n newFieldKey = newNodeUuidsByOldUuid[oldFieldKey]\n }\n if (newFieldKey) {\n validationFieldsUpdated[newFieldKey] = validationField\n }\n delete validationFieldsUpdated[oldFieldKey]\n })\n return Objects.assoc({\n obj: validation,\n prop: 'fields',\n value: validationFieldsUpdated,\n sideEffect,\n })\n}\n\nconst assignNewUuids = (params: {\n record: ArenaRecord\n sideEffect: boolean\n}): { newNodeUuidsByOldUuid: OldUuidToNewUuidMap; newFileUuidsByOldUuid: OldUuidToNewUuidMap; record: ArenaRecord } => {\n const { record, sideEffect } = params\n let recordUpdated = sideEffect ? record : { ...record }\n recordUpdated.uuid = UUIDs.v4()\n\n const {\n newNodeUuidsByOldUuid,\n newFileUuidsByOldUuid,\n record: recordUpdatedUuids,\n } = assignNewUuidsToNodes({ record: recordUpdated, sideEffect })\n\n recordUpdated = recordUpdatedUuids\n\n const { validation } = recordUpdated\n if (validation) {\n const validationUpdated = assignNewUuidsToValidation({\n validation,\n newNodeUuidsByOldUuid,\n sideEffect,\n })\n recordUpdated = Objects.assoc({ obj: recordUpdated, prop: 'validation', value: validationUpdated, sideEffect })\n }\n // re-build nodes index\n const nodes = recordUpdated.nodes!\n delete recordUpdated._nodesIndex\n delete recordUpdated.nodes\n recordUpdated = Records.addNodes(nodes, { sideEffect, sortNodes: true })(recordUpdated)\n\n return { newNodeUuidsByOldUuid, newFileUuidsByOldUuid, record: recordUpdated }\n}\n\nconst removeExcludedNodes = (params: {\n survey: Survey\n record: ArenaRecord\n sideEffect: boolean\n}): RecordUpdateResult => {\n const { survey, record, sideEffect } = params\n const cycle = record.cycle!\n const result = new RecordUpdateResult({ record })\n Surveys.visitDescendantsAndSelfNodeDef({\n survey,\n cycle,\n nodeDef: Surveys.getNodeDefRoot({ survey }),\n visitor: (nodeDef) => {\n const hasAncestorCodeDefExcludedInClone =\n nodeDef.type === NodeDefType.code &&\n Surveys.getNodeDefAncestorCodes({ survey, nodeDef: nodeDef as NodeDefCode }).some(NodeDefs.isExcludedInClone)\n\n if (\n !NodeDefs.isInCycle(cycle)(nodeDef) ||\n NodeDefs.isExcludedInClone(nodeDef) ||\n hasAncestorCodeDefExcludedInClone\n ) {\n const nodesToDelete = Records.getNodesByDefUuid(nodeDef.uuid)(result.record)\n if (nodesToDelete.length > 0) {\n const partialUpdateResult = Records.removeNodes(\n nodesToDelete.map((node) => node.uuid),\n { sideEffect }\n )(result.record)\n result.merge(partialUpdateResult)\n }\n }\n },\n })\n return result\n}\n\nconst cloneRecord = (params: { survey: Survey; record: ArenaRecord; cycleTo: string; sideEffect?: boolean }) => {\n const { survey, record, cycleTo, sideEffect = false } = params\n\n const recordUpdated = sideEffect ? record : { ...record }\n recordUpdated.cycle = cycleTo\n recordUpdated.dateCreated = recordUpdated.dateModified = Dates.nowFormattedForStorage()\n delete recordUpdated.id\n\n // delete nodes not included in clone\n const updateResult = new RecordUpdateResult({ record: recordUpdated })\n updateResult.merge(removeExcludedNodes({ survey, record: updateResult.record, sideEffect }))\n updateResult.merge(RecordFixer.insertMissingSingleNodes({ survey, record: updateResult.record, sideEffect }))\n\n // assign new UUIDs with side effect on record and nodes, faster when record is big\n const {\n newNodeUuidsByOldUuid,\n newFileUuidsByOldUuid,\n record: recordUpdatedUuids,\n } = assignNewUuids({ record: updateResult.record, sideEffect })\n\n updateResult.merge(new RecordUpdateResult({ record: recordUpdatedUuids }))\n\n return { record: updateResult.record, newNodeUuidsByOldUuid, newFileUuidsByOldUuid }\n}\n\nexport const RecordCloner = {\n cloneRecord,\n}\n"]}
|
|
@@ -19,14 +19,7 @@ const fixCodeAttribute = (params) => {
|
|
|
19
19
|
return node;
|
|
20
20
|
}
|
|
21
21
|
// populate meta.hCode with ancestor code attribute node uuids
|
|
22
|
-
const hCode =
|
|
23
|
-
let currentCodeDef = nodeDef;
|
|
24
|
-
let currentParentCodeAttribute = records_1.Records.getParentCodeAttribute(parentNode, currentCodeDef)(record);
|
|
25
|
-
while (currentParentCodeAttribute) {
|
|
26
|
-
hCode.unshift(currentParentCodeAttribute.uuid);
|
|
27
|
-
currentCodeDef = survey_1.Surveys.getNodeDefByUuid({ survey, uuid: currentParentCodeAttribute.nodeDefUuid });
|
|
28
|
-
currentParentCodeAttribute = records_1.Records.getParentCodeAttribute(parentNode, currentCodeDef)(record);
|
|
29
|
-
}
|
|
22
|
+
const hCode = records_1.Records.getAncestorCodeAttributes(survey, parentNode, nodeDef)(record).map((codeAttribute) => codeAttribute.uuid);
|
|
30
23
|
const nodeUpdated = sideEffect ? node : Object.assign({}, node);
|
|
31
24
|
nodeUpdated.meta = Object.assign(Object.assign({}, nodeUpdated.meta), { hCode });
|
|
32
25
|
return nodeUpdated;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordFixer.js","sourceRoot":"","sources":["../../src/record/recordFixer.ts"],"names":[],"mappings":"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","sourcesContent":["import { ArenaRecordNode, NodeFactory, Nodes } from '../node'\nimport { NodeDef, NodeDefCode, NodeDefs, NodeDefType } from '../nodeDef'\nimport { Survey, Surveys } from '../survey'\nimport { Objects } from '../utils'\nimport type { ArenaRecord } from './record'\nimport { RecordUpdateResult } from './recordNodesUpdater'\nimport { Records } from './records'\n\nconst fixCodeAttribute = (params: {\n survey: Survey\n nodeDef: NodeDefCode\n record: ArenaRecord\n node: ArenaRecordNode\n sideEffect: boolean\n}): ArenaRecordNode => {\n const { survey, nodeDef, record, node, sideEffect } = params\n if (!NodeDefs.getParentCodeDefUuid(nodeDef) || Objects.isNotEmpty(Nodes.getHierarchyCode(node))) {\n // nodeDef is not a code attribute or meta.hCode already populated: do nothing\n return node\n }\n const parentNode = Records.getParent(node)(record)\n if (!parentNode) {\n // missing parent node; node parentUuid could be invalid\n return node\n }\n // populate meta.hCode with ancestor code attribute node uuids\n const hCode: string[] = []\n let currentCodeDef: NodeDefCode = nodeDef\n let currentParentCodeAttribute = Records.getParentCodeAttribute(parentNode, currentCodeDef)(record)\n while (currentParentCodeAttribute) {\n hCode.unshift(currentParentCodeAttribute.uuid)\n currentCodeDef = Surveys.getNodeDefByUuid({ survey, uuid: currentParentCodeAttribute.nodeDefUuid }) as NodeDefCode\n currentParentCodeAttribute = Records.getParentCodeAttribute(parentNode, currentCodeDef)(record)\n }\n const nodeUpdated = sideEffect ? node : { ...node }\n nodeUpdated.meta = { ...nodeUpdated.meta, hCode }\n return nodeUpdated\n}\n\nconst insertMissingSingleNode = (params: {\n survey: Survey\n nodeDef: NodeDef<any>\n record: ArenaRecord\n parentNode: ArenaRecordNode\n sideEffect: boolean\n}): RecordUpdateResult | null => {\n const { survey, nodeDef, record, parentNode, sideEffect } = params\n if (!NodeDefs.isSingle(nodeDef)) {\n // multiple node: don't insert it\n return null\n }\n const nodeDefUuid = nodeDef.uuid\n const children = Records.getChildren(parentNode, nodeDef.uuid)(record)\n if (!Objects.isEmpty(children)) {\n // single node already inserted\n return null\n }\n // insert missing single node\n const recordUuid = record.uuid\n let node = NodeFactory.createInstance({ nodeDefUuid, recordUuid, parentNode })\n\n if (nodeDef.type === NodeDefType.code) {\n node = fixCodeAttribute({ survey, nodeDef: nodeDef as NodeDefCode, record, node, sideEffect })\n }\n\n const recordUpdated = Records.addNode(node, { sideEffect })(record)\n return new RecordUpdateResult({ record: recordUpdated, nodes: { [node.uuid]: node } })\n}\n\nconst insertMissingSingleNodes = (params: {\n survey: Survey\n record: ArenaRecord\n sideEffect: boolean\n}): RecordUpdateResult => {\n const { survey, record, sideEffect } = params\n const updateResult = new RecordUpdateResult({ record })\n Surveys.visitNodeDefs({\n survey,\n visitor: (nodeDef) => {\n const parentDefUuid = nodeDef.parentUuid\n if (parentDefUuid) {\n const parentNodes = Records.getNodesByDefUuid(parentDefUuid)(updateResult.record)\n for (const parentNode of parentNodes) {\n const partialUpdateResult = insertMissingSingleNode({\n survey,\n nodeDef,\n record: updateResult.record,\n parentNode,\n sideEffect,\n })\n if (partialUpdateResult) {\n updateResult.merge(partialUpdateResult)\n }\n }\n }\n },\n })\n return updateResult\n}\n\nconst deleteNodesByDefUuid = (params: { record: ArenaRecord; nodeDefUuid: string; sideEffect: boolean }) => {\n const { record, nodeDefUuid, sideEffect } = params\n const updateResult = new RecordUpdateResult({ record })\n\n const recordUpdateOptions = { sideEffect }\n\n const nodesToDelete = Records.getNodesByDefUuid(nodeDefUuid)(updateResult.record)\n for (const nodeToDelete of nodesToDelete) {\n // cleanup child applicability\n const parentNode = Records.getParent(nodeToDelete)(updateResult.record)\n if (parentNode && !Nodes.isChildApplicable(parentNode, nodeDefUuid)) {\n const parentNodeUpdated = Nodes.dissocChildApplicability(parentNode, nodeDefUuid)\n const recordWithParentNodeUpdated = Records.addNode(parentNodeUpdated, recordUpdateOptions)(updateResult.record)\n updateResult.merge(new RecordUpdateResult({ record: recordWithParentNodeUpdated }))\n }\n }\n const nodeUuidsToDelete = nodesToDelete.map((node) => node.uuid)\n const nodesDeleteUpdateResult = Records.removeNodes(nodeUuidsToDelete, recordUpdateOptions)(updateResult.record)\n updateResult.merge(nodesDeleteUpdateResult)\n\n return updateResult\n}\n\n/**\n * Fix a record by:\n * - inserting missing single nodes\n * - deleting nodes with non existing node defs\n * - removing status flags (created, deleted, updated) from all nodes\n */\nconst fixRecord = (params: { survey: Survey; record: ArenaRecord; sideEffect?: boolean }): RecordUpdateResult => {\n const { survey, record, sideEffect = false } = params\n const result = new RecordUpdateResult({ record })\n\n // 1. delete nodes with non existing node defs (and their descendants), once per missing node def\n const missingNodeDefUuids = new Set<string>()\n for (const { nodeDefUuid } of Records.getNodesArray(record)) {\n if (!Surveys.findNodeDefByUuid({ survey, uuid: nodeDefUuid })) {\n missingNodeDefUuids.add(nodeDefUuid)\n }\n }\n for (const nodeDefUuid of missingNodeDefUuids) {\n result.merge(deleteNodesByDefUuid({ record: result.record, nodeDefUuid, sideEffect }))\n }\n\n // 2. fix the remaining nodes (read from the updated record, without the deleted nodes); add them all at once\n const nodesUpdated: { [key: string]: ArenaRecordNode } = {}\n for (const node of Records.getNodesArray(result.record)) {\n const nodeDef = Surveys.getNodeDefByUuid({ survey, uuid: node.nodeDefUuid })\n // remove status flags\n let nodeUpdated = Nodes.removeStatusFlags({ node, sideEffect })\n\n if (nodeDef.type === NodeDefType.code) {\n nodeUpdated = fixCodeAttribute({\n survey,\n nodeDef: nodeDef as NodeDefCode,\n record: result.record,\n node: nodeUpdated,\n sideEffect,\n })\n }\n nodesUpdated[nodeUpdated.uuid] = nodeUpdated\n }\n const recordWithNodesUpdated = Records.addNodes(nodesUpdated, { sideEffect })(result.record)\n result.merge(new RecordUpdateResult({ record: recordWithNodesUpdated, nodes: nodesUpdated }))\n\n const missingNodesUpdateResult = insertMissingSingleNodes({ survey, record: result.record, sideEffect })\n result.merge(missingNodesUpdateResult)\n return result\n}\n\nexport const RecordFixer = {\n fixRecord,\n insertMissingSingleNodes,\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recordFixer.js","sourceRoot":"","sources":["../../src/record/recordFixer.ts"],"names":[],"mappings":";;;AAAA,kCAA6D;AAC7D,wCAAwE;AACxE,sCAA2C;AAC3C,oCAAkC;AAElC,6DAAyD;AACzD,uCAAmC;AAEnC,MAAM,gBAAgB,GAAG,CAAC,MAMzB,EAAmB,EAAE;IACpB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,MAAM,CAAA;IAC5D,IAAI,CAAC,kBAAQ,CAAC,oBAAoB,CAAC,OAAO,CAAC,IAAI,eAAO,CAAC,UAAU,CAAC,YAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAChG,8EAA8E;QAC9E,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,UAAU,GAAG,iBAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAA;IAClD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,wDAAwD;QACxD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,8DAA8D;IAC9D,MAAM,KAAK,GAAG,iBAAO,CAAC,yBAAyB,CAC7C,MAAM,EACN,UAAU,EACV,OAAO,CACR,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;IACpD,MAAM,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,mBAAM,IAAI,CAAE,CAAA;IACnD,WAAW,CAAC,IAAI,mCAAQ,WAAW,CAAC,IAAI,KAAE,KAAK,GAAE,CAAA;IACjD,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA;AAED,MAAM,uBAAuB,GAAG,CAAC,MAMhC,EAA6B,EAAE;IAC9B,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAAA;IAClE,IAAI,CAAC,kBAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,iCAAiC;QACjC,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAA;IAChC,MAAM,QAAQ,GAAG,iBAAO,CAAC,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAA;IACtE,IAAI,CAAC,eAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,+BAA+B;QAC/B,OAAO,IAAI,CAAA;IACb,CAAC;IACD,6BAA6B;IAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAA;IAC9B,IAAI,IAAI,GAAG,kBAAW,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAA;IAE9E,IAAI,OAAO,CAAC,IAAI,KAAK,qBAAW,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,GAAG,gBAAgB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAsB,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAA;IAChG,CAAC;IAED,MAAM,aAAa,GAAG,iBAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;IACnE,OAAO,IAAI,uCAAkB,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAA;AACxF,CAAC,CAAA;AAED,MAAM,wBAAwB,GAAG,CAAC,MAIjC,EAAsB,EAAE;IACvB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAAA;IAC7C,MAAM,YAAY,GAAG,IAAI,uCAAkB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;IACvD,gBAAO,CAAC,aAAa,CAAC;QACpB,MAAM;QACN,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE;YACnB,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAA;YACxC,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,WAAW,GAAG,iBAAO,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;gBACjF,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;oBACrC,MAAM,mBAAmB,GAAG,uBAAuB,CAAC;wBAClD,MAAM;wBACN,OAAO;wBACP,MAAM,EAAE,YAAY,CAAC,MAAM;wBAC3B,UAAU;wBACV,UAAU;qBACX,CAAC,CAAA;oBACF,IAAI,mBAAmB,EAAE,CAAC;wBACxB,YAAY,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;oBACzC,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC,CAAA;IACF,OAAO,YAAY,CAAA;AACrB,CAAC,CAAA;AAED,MAAM,oBAAoB,GAAG,CAAC,MAAyE,EAAE,EAAE;IACzG,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,CAAA;IAClD,MAAM,YAAY,GAAG,IAAI,uCAAkB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;IAEvD,MAAM,mBAAmB,GAAG,EAAE,UAAU,EAAE,CAAA;IAE1C,MAAM,aAAa,GAAG,iBAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;IACjF,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;QACzC,8BAA8B;QAC9B,MAAM,UAAU,GAAG,iBAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;QACvE,IAAI,UAAU,IAAI,CAAC,YAAK,CAAC,iBAAiB,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;YACpE,MAAM,iBAAiB,GAAG,YAAK,CAAC,wBAAwB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;YACjF,MAAM,2BAA2B,GAAG,iBAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;YAChH,YAAY,CAAC,KAAK,CAAC,IAAI,uCAAkB,CAAC,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC,CAAC,CAAA;QACrF,CAAC;IACH,CAAC;IACD,MAAM,iBAAiB,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChE,MAAM,uBAAuB,GAAG,iBAAO,CAAC,WAAW,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;IAChH,YAAY,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;IAE3C,OAAO,YAAY,CAAA;AACrB,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,SAAS,GAAG,CAAC,MAAqE,EAAsB,EAAE;IAC9G,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,KAAK,EAAE,GAAG,MAAM,CAAA;IACrD,MAAM,MAAM,GAAG,IAAI,uCAAkB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;IAEjD,iGAAiG;IACjG,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAA;IAC7C,KAAK,MAAM,EAAE,WAAW,EAAE,IAAI,iBAAO,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,IAAI,CAAC,gBAAO,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;YAC9D,mBAAmB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACtC,CAAC;IACH,CAAC;IACD,KAAK,MAAM,WAAW,IAAI,mBAAmB,EAAE,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,CAAA;IACxF,CAAC;IAED,6GAA6G;IAC7G,MAAM,YAAY,GAAuC,EAAE,CAAA;IAC3D,KAAK,MAAM,IAAI,IAAI,iBAAO,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACxD,MAAM,OAAO,GAAG,gBAAO,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;QAC5E,sBAAsB;QACtB,IAAI,WAAW,GAAG,YAAK,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAA;QAE/D,IAAI,OAAO,CAAC,IAAI,KAAK,qBAAW,CAAC,IAAI,EAAE,CAAC;YACtC,WAAW,GAAG,gBAAgB,CAAC;gBAC7B,MAAM;gBACN,OAAO,EAAE,OAAsB;gBAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,IAAI,EAAE,WAAW;gBACjB,UAAU;aACX,CAAC,CAAA;QACJ,CAAC;QACD,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,WAAW,CAAA;IAC9C,CAAC;IACD,MAAM,sBAAsB,GAAG,iBAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC5F,MAAM,CAAC,KAAK,CAAC,IAAI,uCAAkB,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,CAAA;IAE7F,MAAM,wBAAwB,GAAG,wBAAwB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAA;IACxG,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;IACtC,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAEY,QAAA,WAAW,GAAG;IACzB,SAAS;IACT,wBAAwB;CACzB,CAAA","sourcesContent":["import { ArenaRecordNode, NodeFactory, Nodes } from '../node'\nimport { NodeDef, NodeDefCode, NodeDefs, NodeDefType } from '../nodeDef'\nimport { Survey, Surveys } from '../survey'\nimport { Objects } from '../utils'\nimport type { ArenaRecord } from './record'\nimport { RecordUpdateResult } from './recordNodesUpdater'\nimport { Records } from './records'\n\nconst fixCodeAttribute = (params: {\n survey: Survey\n nodeDef: NodeDefCode\n record: ArenaRecord\n node: ArenaRecordNode\n sideEffect: boolean\n}): ArenaRecordNode => {\n const { survey, nodeDef, record, node, sideEffect } = params\n if (!NodeDefs.getParentCodeDefUuid(nodeDef) || Objects.isNotEmpty(Nodes.getHierarchyCode(node))) {\n // nodeDef is not a code attribute or meta.hCode already populated: do nothing\n return node\n }\n const parentNode = Records.getParent(node)(record)\n if (!parentNode) {\n // missing parent node; node parentUuid could be invalid\n return node\n }\n // populate meta.hCode with ancestor code attribute node uuids\n const hCode = Records.getAncestorCodeAttributes(\n survey,\n parentNode,\n nodeDef\n )(record).map((codeAttribute) => codeAttribute.uuid)\n const nodeUpdated = sideEffect ? node : { ...node }\n nodeUpdated.meta = { ...nodeUpdated.meta, hCode }\n return nodeUpdated\n}\n\nconst insertMissingSingleNode = (params: {\n survey: Survey\n nodeDef: NodeDef<any>\n record: ArenaRecord\n parentNode: ArenaRecordNode\n sideEffect: boolean\n}): RecordUpdateResult | null => {\n const { survey, nodeDef, record, parentNode, sideEffect } = params\n if (!NodeDefs.isSingle(nodeDef)) {\n // multiple node: don't insert it\n return null\n }\n const nodeDefUuid = nodeDef.uuid\n const children = Records.getChildren(parentNode, nodeDef.uuid)(record)\n if (!Objects.isEmpty(children)) {\n // single node already inserted\n return null\n }\n // insert missing single node\n const recordUuid = record.uuid\n let node = NodeFactory.createInstance({ nodeDefUuid, recordUuid, parentNode })\n\n if (nodeDef.type === NodeDefType.code) {\n node = fixCodeAttribute({ survey, nodeDef: nodeDef as NodeDefCode, record, node, sideEffect })\n }\n\n const recordUpdated = Records.addNode(node, { sideEffect })(record)\n return new RecordUpdateResult({ record: recordUpdated, nodes: { [node.uuid]: node } })\n}\n\nconst insertMissingSingleNodes = (params: {\n survey: Survey\n record: ArenaRecord\n sideEffect: boolean\n}): RecordUpdateResult => {\n const { survey, record, sideEffect } = params\n const updateResult = new RecordUpdateResult({ record })\n Surveys.visitNodeDefs({\n survey,\n visitor: (nodeDef) => {\n const parentDefUuid = nodeDef.parentUuid\n if (parentDefUuid) {\n const parentNodes = Records.getNodesByDefUuid(parentDefUuid)(updateResult.record)\n for (const parentNode of parentNodes) {\n const partialUpdateResult = insertMissingSingleNode({\n survey,\n nodeDef,\n record: updateResult.record,\n parentNode,\n sideEffect,\n })\n if (partialUpdateResult) {\n updateResult.merge(partialUpdateResult)\n }\n }\n }\n },\n })\n return updateResult\n}\n\nconst deleteNodesByDefUuid = (params: { record: ArenaRecord; nodeDefUuid: string; sideEffect: boolean }) => {\n const { record, nodeDefUuid, sideEffect } = params\n const updateResult = new RecordUpdateResult({ record })\n\n const recordUpdateOptions = { sideEffect }\n\n const nodesToDelete = Records.getNodesByDefUuid(nodeDefUuid)(updateResult.record)\n for (const nodeToDelete of nodesToDelete) {\n // cleanup child applicability\n const parentNode = Records.getParent(nodeToDelete)(updateResult.record)\n if (parentNode && !Nodes.isChildApplicable(parentNode, nodeDefUuid)) {\n const parentNodeUpdated = Nodes.dissocChildApplicability(parentNode, nodeDefUuid)\n const recordWithParentNodeUpdated = Records.addNode(parentNodeUpdated, recordUpdateOptions)(updateResult.record)\n updateResult.merge(new RecordUpdateResult({ record: recordWithParentNodeUpdated }))\n }\n }\n const nodeUuidsToDelete = nodesToDelete.map((node) => node.uuid)\n const nodesDeleteUpdateResult = Records.removeNodes(nodeUuidsToDelete, recordUpdateOptions)(updateResult.record)\n updateResult.merge(nodesDeleteUpdateResult)\n\n return updateResult\n}\n\n/**\n * Fix a record by:\n * - inserting missing single nodes\n * - deleting nodes with non existing node defs\n * - removing status flags (created, deleted, updated) from all nodes\n */\nconst fixRecord = (params: { survey: Survey; record: ArenaRecord; sideEffect?: boolean }): RecordUpdateResult => {\n const { survey, record, sideEffect = false } = params\n const result = new RecordUpdateResult({ record })\n\n // 1. delete nodes with non existing node defs (and their descendants), once per missing node def\n const missingNodeDefUuids = new Set<string>()\n for (const { nodeDefUuid } of Records.getNodesArray(record)) {\n if (!Surveys.findNodeDefByUuid({ survey, uuid: nodeDefUuid })) {\n missingNodeDefUuids.add(nodeDefUuid)\n }\n }\n for (const nodeDefUuid of missingNodeDefUuids) {\n result.merge(deleteNodesByDefUuid({ record: result.record, nodeDefUuid, sideEffect }))\n }\n\n // 2. fix the remaining nodes (read from the updated record, without the deleted nodes); add them all at once\n const nodesUpdated: { [key: string]: ArenaRecordNode } = {}\n for (const node of Records.getNodesArray(result.record)) {\n const nodeDef = Surveys.getNodeDefByUuid({ survey, uuid: node.nodeDefUuid })\n // remove status flags\n let nodeUpdated = Nodes.removeStatusFlags({ node, sideEffect })\n\n if (nodeDef.type === NodeDefType.code) {\n nodeUpdated = fixCodeAttribute({\n survey,\n nodeDef: nodeDef as NodeDefCode,\n record: result.record,\n node: nodeUpdated,\n sideEffect,\n })\n }\n nodesUpdated[nodeUpdated.uuid] = nodeUpdated\n }\n const recordWithNodesUpdated = Records.addNodes(nodesUpdated, { sideEffect })(result.record)\n result.merge(new RecordUpdateResult({ record: recordWithNodesUpdated, nodes: nodesUpdated }))\n\n const missingNodesUpdateResult = insertMissingSingleNodes({ survey, record: result.record, sideEffect })\n result.merge(missingNodesUpdateResult)\n return result\n}\n\nexport const RecordFixer = {\n fixRecord,\n insertMissingSingleNodes,\n}\n"]}
|
|
@@ -15,6 +15,7 @@ const node_1 = require("../../node");
|
|
|
15
15
|
const nodeValues_1 = require("../../node/nodeValues");
|
|
16
16
|
const nodeDef_1 = require("../../nodeDef");
|
|
17
17
|
const nodeDefs_1 = require("../../survey/surveys/nodeDefs");
|
|
18
|
+
const recordGetters_1 = require("../_records/recordGetters");
|
|
18
19
|
const recordUtils_1 = require("../_records/recordUtils");
|
|
19
20
|
const recordEnumeratingItemsExpressionEvaluator_1 = require("./recordEnumeratingItemsExpressionEvaluator");
|
|
20
21
|
const recordUpdateResult_1 = require("./recordUpdateResult");
|
|
@@ -125,6 +126,11 @@ const addNodeAndDescendants = (params) => __awaiter(void 0, void 0, void 0, func
|
|
|
125
126
|
parentNode,
|
|
126
127
|
surveyUuid: survey.uuid,
|
|
127
128
|
});
|
|
129
|
+
if (parentNode && nodeDef.type === nodeDef_1.NodeDefType.code && nodeDef_1.NodeDefs.getParentCodeDefUuid(nodeDef)) {
|
|
130
|
+
// meta.hCode indexes the node as dependent of its ancestor code attributes (cleared when they change)
|
|
131
|
+
const ancestorCodeAttributes = (0, recordGetters_1.getAncestorCodeAttributes)(survey, parentNode, nodeDef)(record);
|
|
132
|
+
node.meta = Object.assign(Object.assign({}, node.meta), { hCode: ancestorCodeAttributes.map((codeAttribute) => codeAttribute.uuid) });
|
|
133
|
+
}
|
|
128
134
|
const updateResult = new recordUpdateResult_1.RecordUpdateResult({ record });
|
|
129
135
|
updateResult.addNode(node, { sideEffect });
|
|
130
136
|
// Add children if entity
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordNodesCreator.js","sourceRoot":"","sources":["../../../src/record/recordNodesUpdater/recordNodesCreator.ts"],"names":[],"mappings":"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","sourcesContent":["import { User } from '../../auth'\nimport { SystemError, SystemErrorKeys } from '../../error'\nimport { CategoryItem } from '../../category'\nimport { ArenaRecordNode, NodeFactory, Nodes } from '../../node'\nimport { NodeValues } from '../../node/nodeValues'\nimport { NodeDef, NodeDefCode, NodeDefEntity, NodeDefType, NodeDefs } from '../../nodeDef'\nimport { CategoryItemProvider } from '../../nodeDefExpressionEvaluator/categoryItemProvider'\nimport { Survey } from '../../survey'\nimport { getNodeDefChildren, getNodeDefEnumerator } from '../../survey/surveys/nodeDefs'\nimport { getEnumeratingCategoryItems } from '../_records/recordUtils'\nimport { getEnumeratingItemsAllowedCodes } from './recordEnumeratingItemsExpressionEvaluator'\nimport { RecordExpressionEvaluationContext } from './recordExpressionEvaluationContext'\nimport { RecordUpdateResult } from './recordUpdateResult'\n\nexport type NodesUpdateParams = RecordExpressionEvaluationContext & {\n dateModified?: string\n clearNonApplicableValues?: boolean\n}\n\nexport type NodeCreateParams = NodesUpdateParams & {\n parentNode?: ArenaRecordNode\n nodeDef: NodeDef<any>\n createMultipleEntities?: boolean\n}\n\nconst getNodesToInsertCount = (params: { parentNode: ArenaRecordNode | undefined; nodeDef: NodeDef<any> }): number => {\n const { nodeDef, parentNode } = params\n if (!parentNode || NodeDefs.isSingle(nodeDef)) return 1\n if (nodeDef.type === NodeDefType.code) return 0 // never create nodes for multiple code attributes\n\n if (NodeDefs.isMultipleEntity(nodeDef) && !NodeDefs.isAutoCreateMinCountItems(nodeDef)) return 0\n\n const minCount = Nodes.getChildrenMinCount({ parentNode, nodeDef })\n if (Number.isNaN(minCount) || minCount <= 0) return 0\n return minCount\n}\n\nexport const createEnumeratedEntityNode = async (params: {\n user: User\n survey: Survey\n parentNode: ArenaRecordNode\n nodeDef: NodeDefEntity\n enumeratorDef: NodeDefCode\n categoryItem: CategoryItem\n updateResult: RecordUpdateResult\n sideEffect?: boolean\n}): Promise<void> => {\n const { user, survey, parentNode, nodeDef, enumeratorDef, categoryItem, updateResult, sideEffect } = params\n\n const { record } = updateResult\n\n const childUpdateResult = await addNodeAndDescendants({\n user,\n survey,\n record: updateResult.record,\n parentNode,\n nodeDef,\n sideEffect,\n })\n const enumeratorNode = Object.values(childUpdateResult.nodes).find((node) => node.nodeDefUuid === enumeratorDef.uuid)\n if (!enumeratorNode) {\n throw new SystemError(SystemErrorKeys.record.enumeratorNodeNotFound, {\n recordUuid: record.uuid,\n entityDef: NodeDefs.getName(nodeDef),\n enumerator: NodeDefs.getName(enumeratorDef),\n })\n }\n enumeratorNode.value = NodeValues.newCodeValue({ itemUuid: categoryItem.uuid })\n enumeratorNode.meta = { ...enumeratorNode.meta, defaultValueApplied: true }\n enumeratorNode.refData = { categoryItem }\n\n updateResult.merge(childUpdateResult)\n}\n\nexport const createEnumeratedEntityNodes = async (params: {\n user: User\n survey: Survey\n parentNode: ArenaRecordNode\n nodeDef: NodeDefEntity\n updateResult: RecordUpdateResult\n categoryItemProvider?: CategoryItemProvider\n sideEffect?: boolean\n}): Promise<boolean> => {\n const { user, survey, parentNode, nodeDef, updateResult, categoryItemProvider } = params\n\n const enumeratorDef = getNodeDefEnumerator({ survey, entityDef: nodeDef })\n if (!enumeratorDef) return false\n\n const allowedCodes = await getEnumeratingItemsAllowedCodes({\n survey,\n user,\n record: updateResult.record,\n entityDef: nodeDef,\n parentNode,\n })\n\n const categoryItems = await getEnumeratingCategoryItems({\n survey,\n enumeratorDef,\n parentNode,\n categoryItemProvider,\n allowedCodes,\n })(updateResult.record)\n if (categoryItems.length === 0) return false\n\n for (const categoryItem of categoryItems) {\n // sequential: each iteration updates the record\n await createEnumeratedEntityNode({ ...params, enumeratorDef, categoryItem }) // NOSONAR\n }\n return true\n}\n\nconst createChildNodesBasedOnMinCount = async (\n params: NodeCreateParams & { updateResult: RecordUpdateResult }\n): Promise<void> => {\n const { parentNode, nodeDef, updateResult, createMultipleEntities = true } = params\n\n if (NodeDefs.isMultipleEntity(nodeDef) && NodeDefs.isEnumerate(nodeDef)) {\n if (await createEnumeratedEntityNodes({ ...params, parentNode: parentNode! })) {\n return\n }\n }\n\n const nodesToInsertCount = getNodesToInsertCount({ parentNode, nodeDef })\n if (\n nodesToInsertCount === 0 ||\n (NodeDefs.isMultipleEntity(nodeDef) &&\n (!createMultipleEntities || (parentNode && !Nodes.isChildApplicable(parentNode, nodeDef.uuid))))\n ) {\n return // do nothing\n }\n for (let index = 0; index < nodesToInsertCount; index++) {\n // sequential: each iteration updates the record\n const childUpdateResult = await addNodeAndDescendants({ ...params, record: updateResult.record }) // NOSONAR\n updateResult.merge(childUpdateResult)\n }\n}\n\nexport const addDescendants = async (params: NodeCreateParams): Promise<RecordUpdateResult> => {\n const { survey, record, nodeDef } = params\n\n const updateResult = new RecordUpdateResult({ record })\n\n if (NodeDefs.isEntity(nodeDef)) {\n const childDefs = getNodeDefChildren({ survey, nodeDef })\n\n // Add only child single nodes (it allows to apply default values)\n for (const childDef of childDefs) {\n // sequential: each iteration updates the record\n await createChildNodesBasedOnMinCount({ ...params, updateResult, nodeDef: childDef }) // NOSONAR\n }\n }\n return updateResult\n}\n\nexport const addNodeAndDescendants = async (params: NodeCreateParams): Promise<RecordUpdateResult> => {\n const { survey, record, parentNode, nodeDef, sideEffect = false } = params\n\n const node = NodeFactory.createInstance({\n nodeDefUuid: nodeDef.uuid,\n recordUuid: record.uuid,\n parentNode,\n surveyUuid: survey.uuid,\n })\n\n const updateResult = new RecordUpdateResult({ record })\n updateResult.addNode(node, { sideEffect })\n\n // Add children if entity\n if (NodeDefs.isEntity(nodeDef)) {\n const descendantsUpdateResult = await addDescendants({\n ...params,\n record: updateResult.record,\n parentNode: node,\n })\n updateResult.merge(descendantsUpdateResult)\n }\n return updateResult\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recordNodesCreator.js","sourceRoot":"","sources":["../../../src/record/recordNodesUpdater/recordNodesCreator.ts"],"names":[],"mappings":"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","sourcesContent":["import { User } from '../../auth'\nimport { SystemError, SystemErrorKeys } from '../../error'\nimport { CategoryItem } from '../../category'\nimport { ArenaRecordNode, NodeFactory, Nodes } from '../../node'\nimport { NodeValues } from '../../node/nodeValues'\nimport { NodeDef, NodeDefCode, NodeDefEntity, NodeDefType, NodeDefs } from '../../nodeDef'\nimport { CategoryItemProvider } from '../../nodeDefExpressionEvaluator/categoryItemProvider'\nimport { Survey } from '../../survey'\nimport { getNodeDefChildren, getNodeDefEnumerator } from '../../survey/surveys/nodeDefs'\nimport { getAncestorCodeAttributes } from '../_records/recordGetters'\nimport { getEnumeratingCategoryItems } from '../_records/recordUtils'\nimport { getEnumeratingItemsAllowedCodes } from './recordEnumeratingItemsExpressionEvaluator'\nimport { RecordExpressionEvaluationContext } from './recordExpressionEvaluationContext'\nimport { RecordUpdateResult } from './recordUpdateResult'\n\nexport type NodesUpdateParams = RecordExpressionEvaluationContext & {\n dateModified?: string\n clearNonApplicableValues?: boolean\n}\n\nexport type NodeCreateParams = NodesUpdateParams & {\n parentNode?: ArenaRecordNode\n nodeDef: NodeDef<any>\n createMultipleEntities?: boolean\n}\n\nconst getNodesToInsertCount = (params: { parentNode: ArenaRecordNode | undefined; nodeDef: NodeDef<any> }): number => {\n const { nodeDef, parentNode } = params\n if (!parentNode || NodeDefs.isSingle(nodeDef)) return 1\n if (nodeDef.type === NodeDefType.code) return 0 // never create nodes for multiple code attributes\n\n if (NodeDefs.isMultipleEntity(nodeDef) && !NodeDefs.isAutoCreateMinCountItems(nodeDef)) return 0\n\n const minCount = Nodes.getChildrenMinCount({ parentNode, nodeDef })\n if (Number.isNaN(minCount) || minCount <= 0) return 0\n return minCount\n}\n\nexport const createEnumeratedEntityNode = async (params: {\n user: User\n survey: Survey\n parentNode: ArenaRecordNode\n nodeDef: NodeDefEntity\n enumeratorDef: NodeDefCode\n categoryItem: CategoryItem\n updateResult: RecordUpdateResult\n sideEffect?: boolean\n}): Promise<void> => {\n const { user, survey, parentNode, nodeDef, enumeratorDef, categoryItem, updateResult, sideEffect } = params\n\n const { record } = updateResult\n\n const childUpdateResult = await addNodeAndDescendants({\n user,\n survey,\n record: updateResult.record,\n parentNode,\n nodeDef,\n sideEffect,\n })\n const enumeratorNode = Object.values(childUpdateResult.nodes).find((node) => node.nodeDefUuid === enumeratorDef.uuid)\n if (!enumeratorNode) {\n throw new SystemError(SystemErrorKeys.record.enumeratorNodeNotFound, {\n recordUuid: record.uuid,\n entityDef: NodeDefs.getName(nodeDef),\n enumerator: NodeDefs.getName(enumeratorDef),\n })\n }\n enumeratorNode.value = NodeValues.newCodeValue({ itemUuid: categoryItem.uuid })\n enumeratorNode.meta = { ...enumeratorNode.meta, defaultValueApplied: true }\n enumeratorNode.refData = { categoryItem }\n\n updateResult.merge(childUpdateResult)\n}\n\nexport const createEnumeratedEntityNodes = async (params: {\n user: User\n survey: Survey\n parentNode: ArenaRecordNode\n nodeDef: NodeDefEntity\n updateResult: RecordUpdateResult\n categoryItemProvider?: CategoryItemProvider\n sideEffect?: boolean\n}): Promise<boolean> => {\n const { user, survey, parentNode, nodeDef, updateResult, categoryItemProvider } = params\n\n const enumeratorDef = getNodeDefEnumerator({ survey, entityDef: nodeDef })\n if (!enumeratorDef) return false\n\n const allowedCodes = await getEnumeratingItemsAllowedCodes({\n survey,\n user,\n record: updateResult.record,\n entityDef: nodeDef,\n parentNode,\n })\n\n const categoryItems = await getEnumeratingCategoryItems({\n survey,\n enumeratorDef,\n parentNode,\n categoryItemProvider,\n allowedCodes,\n })(updateResult.record)\n if (categoryItems.length === 0) return false\n\n for (const categoryItem of categoryItems) {\n // sequential: each iteration updates the record\n await createEnumeratedEntityNode({ ...params, enumeratorDef, categoryItem }) // NOSONAR\n }\n return true\n}\n\nconst createChildNodesBasedOnMinCount = async (\n params: NodeCreateParams & { updateResult: RecordUpdateResult }\n): Promise<void> => {\n const { parentNode, nodeDef, updateResult, createMultipleEntities = true } = params\n\n if (NodeDefs.isMultipleEntity(nodeDef) && NodeDefs.isEnumerate(nodeDef)) {\n if (await createEnumeratedEntityNodes({ ...params, parentNode: parentNode! })) {\n return\n }\n }\n\n const nodesToInsertCount = getNodesToInsertCount({ parentNode, nodeDef })\n if (\n nodesToInsertCount === 0 ||\n (NodeDefs.isMultipleEntity(nodeDef) &&\n (!createMultipleEntities || (parentNode && !Nodes.isChildApplicable(parentNode, nodeDef.uuid))))\n ) {\n return // do nothing\n }\n for (let index = 0; index < nodesToInsertCount; index++) {\n // sequential: each iteration updates the record\n const childUpdateResult = await addNodeAndDescendants({ ...params, record: updateResult.record }) // NOSONAR\n updateResult.merge(childUpdateResult)\n }\n}\n\nexport const addDescendants = async (params: NodeCreateParams): Promise<RecordUpdateResult> => {\n const { survey, record, nodeDef } = params\n\n const updateResult = new RecordUpdateResult({ record })\n\n if (NodeDefs.isEntity(nodeDef)) {\n const childDefs = getNodeDefChildren({ survey, nodeDef })\n\n // Add only child single nodes (it allows to apply default values)\n for (const childDef of childDefs) {\n // sequential: each iteration updates the record\n await createChildNodesBasedOnMinCount({ ...params, updateResult, nodeDef: childDef }) // NOSONAR\n }\n }\n return updateResult\n}\n\nexport const addNodeAndDescendants = async (params: NodeCreateParams): Promise<RecordUpdateResult> => {\n const { survey, record, parentNode, nodeDef, sideEffect = false } = params\n\n const node = NodeFactory.createInstance({\n nodeDefUuid: nodeDef.uuid,\n recordUuid: record.uuid,\n parentNode,\n surveyUuid: survey.uuid,\n })\n if (parentNode && nodeDef.type === NodeDefType.code && NodeDefs.getParentCodeDefUuid(nodeDef as NodeDefCode)) {\n // meta.hCode indexes the node as dependent of its ancestor code attributes (cleared when they change)\n const ancestorCodeAttributes = getAncestorCodeAttributes(survey, parentNode, nodeDef as NodeDefCode)(record)\n node.meta = { ...node.meta, hCode: ancestorCodeAttributes.map((codeAttribute) => codeAttribute.uuid) }\n }\n\n const updateResult = new RecordUpdateResult({ record })\n updateResult.addNode(node, { sideEffect })\n\n // Add children if entity\n if (NodeDefs.isEntity(nodeDef)) {\n const descendantsUpdateResult = await addDescendants({\n ...params,\n record: updateResult.record,\n parentNode: node,\n })\n updateResult.merge(descendantsUpdateResult)\n }\n return updateResult\n}\n"]}
|
|
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.RecordUpdater = void 0;
|
|
13
13
|
const error_1 = require("../error");
|
|
14
|
+
const nodeDef_1 = require("../nodeDef");
|
|
14
15
|
const survey_1 = require("../survey");
|
|
15
16
|
const utils_1 = require("../utils");
|
|
16
17
|
const validations_1 = require("../validation/validations");
|
|
@@ -43,7 +44,7 @@ const getDependentValidationNodePointers = (params) => {
|
|
|
43
44
|
return Array.from(uniquePointersByKey.values());
|
|
44
45
|
};
|
|
45
46
|
const _onRecordNodesCreateOrUpdate = (params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
46
|
-
const { user, survey, dateModified = utils_1.Dates.nowFormattedForStorage() } = params;
|
|
47
|
+
const { user, survey, categoryItemProvider, taxonProvider, areaOfInterestProvider, additionalNodesToValidate, dateModified = utils_1.Dates.nowFormattedForStorage(), } = params;
|
|
47
48
|
const updateResult = yield recordNodesUpdater_1.RecordNodesUpdater.updateNodesDependents(params);
|
|
48
49
|
const { nodes: updatedNodes, record: updatedRecord } = updateResult;
|
|
49
50
|
const dependentValidationNodePointers = getDependentValidationNodePointers({
|
|
@@ -55,10 +56,13 @@ const _onRecordNodesCreateOrUpdate = (params) => __awaiter(void 0, void 0, void
|
|
|
55
56
|
record: updatedRecord,
|
|
56
57
|
nodePointers: dependentValidationNodePointers,
|
|
57
58
|
});
|
|
58
|
-
const nodesToValidate = Object.assign(Object.assign({}, updatedNodes), dependentValidationNodes);
|
|
59
|
+
const nodesToValidate = Object.assign(Object.assign(Object.assign({}, updatedNodes), dependentValidationNodes), additionalNodesToValidate);
|
|
59
60
|
const validationUpdatedNodes = yield recordValidator_1.RecordValidator.validateNodes({
|
|
60
61
|
user,
|
|
61
62
|
survey,
|
|
63
|
+
categoryItemProvider,
|
|
64
|
+
taxonProvider,
|
|
65
|
+
areaOfInterestProvider,
|
|
62
66
|
record: updatedRecord,
|
|
63
67
|
nodes: nodesToValidate,
|
|
64
68
|
});
|
|
@@ -94,11 +98,49 @@ const updateAttributeValue = (params) => __awaiter(void 0, void 0, void 0, funct
|
|
|
94
98
|
const _record = records_1.Records.addNode(attributeUpdated, { sideEffect })(record);
|
|
95
99
|
return _onRecordNodesCreateOrUpdate(Object.assign(Object.assign({}, params), { record: _record, nodes: nodesUpdated }));
|
|
96
100
|
});
|
|
101
|
+
/**
|
|
102
|
+
* Returns the key and unique attributes of the siblings of the specified entities:
|
|
103
|
+
* they could have been duplicates of the ones being deleted, so they must be validated again.
|
|
104
|
+
*/
|
|
105
|
+
const getEntityKeyOrUniqueAttributes = (params) => {
|
|
106
|
+
const { survey, record, entity, uniqueAttributeDefs } = params;
|
|
107
|
+
return [
|
|
108
|
+
...records_1.Records.getEntityKeyNodes(survey, entity)(record),
|
|
109
|
+
...uniqueAttributeDefs.flatMap((uniqueDef) => records_1.Records.getChildren(entity, uniqueDef.uuid)(record)),
|
|
110
|
+
].filter(Boolean);
|
|
111
|
+
};
|
|
112
|
+
const getSiblingKeyOrUniqueAttributes = (params) => {
|
|
113
|
+
const { survey, record, nodeUuids } = params;
|
|
114
|
+
const nodeUuidsSet = new Set(nodeUuids);
|
|
115
|
+
const result = {};
|
|
116
|
+
for (const nodeUuid of nodeUuids) {
|
|
117
|
+
const node = records_1.Records.getNodeByUuid(nodeUuid)(record);
|
|
118
|
+
const parentNode = node ? records_1.Records.getParent(node)(record) : undefined;
|
|
119
|
+
const nodeDef = node ? survey_1.Surveys.getNodeDefByUuid({ survey, uuid: node.nodeDefUuid }) : undefined;
|
|
120
|
+
if (!parentNode || !nodeDef || !nodeDef_1.NodeDefs.isEntity(nodeDef))
|
|
121
|
+
continue;
|
|
122
|
+
const uniqueAttributeDefs = survey_1.Surveys.getNodeDefChildren({ survey, nodeDef }).filter((childDef) => { var _a; return (_a = nodeDef_1.NodeDefs.getValidations(childDef)) === null || _a === void 0 ? void 0 : _a.unique; });
|
|
123
|
+
const siblings = records_1.Records.getChildren(parentNode, nodeDef.uuid)(record).filter((s) => !nodeUuidsSet.has(s.uuid));
|
|
124
|
+
for (const sibling of siblings) {
|
|
125
|
+
for (const attribute of getEntityKeyOrUniqueAttributes({
|
|
126
|
+
survey,
|
|
127
|
+
record,
|
|
128
|
+
entity: sibling,
|
|
129
|
+
uniqueAttributeDefs,
|
|
130
|
+
})) {
|
|
131
|
+
result[attribute.uuid] = attribute;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
};
|
|
97
137
|
const deleteNodes = (params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
98
|
-
const { nodeUuids, record: _record, sideEffect = false } = params;
|
|
138
|
+
const { survey, nodeUuids, record: _record, sideEffect = false } = params;
|
|
139
|
+
// found before removing the nodes: the deleted nodes are no longer reachable from their siblings afterwards
|
|
140
|
+
const siblingKeyOrUniqueAttributes = getSiblingKeyOrUniqueAttributes({ survey, record: _record, nodeUuids });
|
|
99
141
|
const updateResult = records_1.Records.removeNodes(nodeUuids, { sideEffect })(_record);
|
|
100
142
|
const { record, nodesDeleted } = updateResult;
|
|
101
|
-
const result = yield _onRecordNodesCreateOrUpdate(Object.assign(Object.assign({}, params), { record, nodes: nodesDeleted }));
|
|
143
|
+
const result = yield _onRecordNodesCreateOrUpdate(Object.assign(Object.assign({}, params), { record, nodes: nodesDeleted, additionalNodesToValidate: siblingKeyOrUniqueAttributes }));
|
|
102
144
|
result.nodesDeleted = nodesDeleted;
|
|
103
145
|
return result;
|
|
104
146
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordUpdater.js","sourceRoot":"","sources":["../../src/record/recordUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { Dictionary } from '../common'\nimport { SystemError, SystemErrorKeys } from '../error'\nimport { ArenaRecordNode, NodePointer, NodesMap } from '../node'\nimport { Survey, SurveyDependencyType, Surveys } from '../survey'\nimport { Dates, Objects } from '../utils'\nimport { Validations } from '../validation/validations'\nimport { NodePointers } from './nodePointers'\nimport { ArenaRecord } from './record'\nimport { RecordNodesUpdater, RecordUpdateResult } from './recordNodesUpdater'\nimport { NodeCreateParams, NodesUpdateParams } from './recordNodesUpdater/recordNodesCreator'\nimport { Records } from './records'\nimport { RecordValidator } from './recordValidator'\n\nconst validationDependencyTypes = [\n SurveyDependencyType.validations,\n SurveyDependencyType.required,\n SurveyDependencyType.minCount,\n SurveyDependencyType.maxCount,\n]\n\nconst getDependentValidationNodePointers = (params: {\n survey: Survey\n record: ArenaRecord\n nodes: NodesMap\n}): NodePointer[] => {\n const { survey, record, nodes } = params\n const uniquePointersByKey = new Map<string, NodePointer>()\n for (const node of Object.values(nodes)) {\n for (const dependencyType of validationDependencyTypes) {\n const nodePointers = Records.getDependentNodePointers(survey, node, dependencyType)(record)\n for (const pointer of nodePointers) {\n const nodeCtxUuid = pointer.nodeCtx.uuid\n const nodeDefUuid = pointer.nodeDef.uuid\n const key = `${nodeCtxUuid ?? ''}:${nodeDefUuid ?? ''}`\n if (!uniquePointersByKey.has(key)) {\n uniquePointersByKey.set(key, pointer)\n }\n }\n }\n }\n return Array.from(uniquePointersByKey.values())\n}\n\nconst _onRecordNodesCreateOrUpdate = async (\n params: NodesUpdateParams & { nodes: Dictionary<ArenaRecordNode> }\n): Promise<RecordUpdateResult> => {\n const { user, survey, dateModified = Dates.nowFormattedForStorage() } = params\n\n const updateResult = await RecordNodesUpdater.updateNodesDependents(params)\n const { nodes: updatedNodes, record: updatedRecord } = updateResult\n\n const dependentValidationNodePointers = getDependentValidationNodePointers({\n survey,\n record: updatedRecord,\n nodes: updatedNodes,\n })\n\n const dependentValidationNodes = NodePointers.getNodesMapFromNodePointers({\n record: updatedRecord,\n nodePointers: dependentValidationNodePointers,\n })\n\n const nodesToValidate = { ...updatedNodes, ...dependentValidationNodes }\n\n const validationUpdatedNodes = await RecordValidator.validateNodes({\n user,\n survey,\n record: updatedRecord,\n nodes: nodesToValidate,\n })\n\n const validation = Validations.mergeValidations(validationUpdatedNodes)(Validations.getValidation(updatedRecord))\n updatedRecord.validation = validation\n updatedRecord.dateModified = dateModified\n\n updateResult.validation = validation\n\n return updateResult\n}\n\nconst createDescendants = async (params: NodeCreateParams): Promise<RecordUpdateResult> => {\n const { record: updatedRecord, nodes: createdNodes } = await RecordNodesUpdater.addDescendants(params)\n\n return _onRecordNodesCreateOrUpdate({ ...params, record: updatedRecord, nodes: createdNodes })\n}\n\nconst createNodeAndDescendants = async (params: NodeCreateParams): Promise<RecordUpdateResult> => {\n const { record: updatedRecord, nodes: createdNodes } = await RecordNodesUpdater.addNodeAndDescendants(params)\n\n return _onRecordNodesCreateOrUpdate({ ...params, record: updatedRecord, nodes: createdNodes })\n}\n\nconst createRootEntity = async (\n params: NodesUpdateParams & {\n createMultipleEntities?: boolean\n }\n): Promise<RecordUpdateResult> => {\n const { survey, createMultipleEntities = true } = params\n\n return createNodeAndDescendants({ ...params, nodeDef: Surveys.getNodeDefRoot({ survey }), createMultipleEntities })\n}\n\nconst updateAttributeValue = async (\n params: NodesUpdateParams & {\n attributeUuid: string\n value: any\n }\n): Promise<RecordUpdateResult> => {\n const { attributeUuid, record, value, dateModified = Dates.nowFormattedForStorage(), sideEffect = false } = params\n const attribute = Records.getNodeByUuid(attributeUuid)(record)\n if (!attribute) throw new SystemError(SystemErrorKeys.record.nodeNotFound, { uuid: attributeUuid })\n\n let attributeUpdated = sideEffect ? attribute : { ...attribute }\n attributeUpdated.value = value\n attributeUpdated.dateModified = dateModified\n // reset defaultValueApplied flag\n attributeUpdated = Objects.dissocPath({ obj: attributeUpdated, path: ['meta', 'defaultValueApplied'], sideEffect })\n\n const nodesUpdated = { [attributeUuid]: attributeUpdated }\n\n const _record = Records.addNode(attributeUpdated, { sideEffect })(record)\n\n return _onRecordNodesCreateOrUpdate({ ...params, record: _record, nodes: nodesUpdated })\n}\n\nconst deleteNodes = async (\n params: NodesUpdateParams & {\n nodeUuids: string[]\n }\n): Promise<RecordUpdateResult> => {\n const { nodeUuids, record: _record, sideEffect = false } = params\n\n const updateResult = Records.removeNodes(nodeUuids, { sideEffect })(_record)\n const { record, nodesDeleted } = updateResult\n\n const result = await _onRecordNodesCreateOrUpdate({ ...params, record, nodes: nodesDeleted })\n result.nodesDeleted = nodesDeleted\n return result\n}\n\nconst deleteNode = async (params: NodesUpdateParams & { nodeUuid: string }): Promise<RecordUpdateResult> => {\n const { nodeUuid } = params\n return deleteNodes({ ...params, nodeUuids: [nodeUuid] })\n}\n\nexport const RecordUpdater = {\n /** Creates the descendants of a node and updates dependents (applicability, default values, calculations...) and validation */\n createDescendants,\n /** Creates a node and its descendants and updates dependents (applicability, default values, calculations...) and validation */\n createNodeAndDescendants,\n createRootEntity,\n updateAttributeValue,\n /** Deletes the node and its descendants and updates dependents (applicability, default values, calculations...) and validation */\n deleteNode,\n /** Deletes the nodes and their descendants and updates dependents (applicability, default values, calculations...) and validation */\n deleteNodes,\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recordUpdater.js","sourceRoot":"","sources":["../../src/record/recordUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { Dictionary } from '../common'\nimport { SystemError, SystemErrorKeys } from '../error'\nimport { ArenaRecordNode, NodePointer, NodesMap } from '../node'\nimport { NodeDef, NodeDefs } from '../nodeDef'\nimport { Survey, SurveyDependencyType, Surveys } from '../survey'\nimport { Dates, Objects } from '../utils'\nimport { Validations } from '../validation/validations'\nimport { NodePointers } from './nodePointers'\nimport { ArenaRecord } from './record'\nimport { RecordNodesUpdater, RecordUpdateResult } from './recordNodesUpdater'\nimport { NodeCreateParams, NodesUpdateParams } from './recordNodesUpdater/recordNodesCreator'\nimport { Records } from './records'\nimport { RecordValidator } from './recordValidator'\n\nconst validationDependencyTypes = [\n SurveyDependencyType.validations,\n SurveyDependencyType.required,\n SurveyDependencyType.minCount,\n SurveyDependencyType.maxCount,\n]\n\nconst getDependentValidationNodePointers = (params: {\n survey: Survey\n record: ArenaRecord\n nodes: NodesMap\n}): NodePointer[] => {\n const { survey, record, nodes } = params\n const uniquePointersByKey = new Map<string, NodePointer>()\n for (const node of Object.values(nodes)) {\n for (const dependencyType of validationDependencyTypes) {\n const nodePointers = Records.getDependentNodePointers(survey, node, dependencyType)(record)\n for (const pointer of nodePointers) {\n const nodeCtxUuid = pointer.nodeCtx.uuid\n const nodeDefUuid = pointer.nodeDef.uuid\n const key = `${nodeCtxUuid ?? ''}:${nodeDefUuid ?? ''}`\n if (!uniquePointersByKey.has(key)) {\n uniquePointersByKey.set(key, pointer)\n }\n }\n }\n }\n return Array.from(uniquePointersByKey.values())\n}\n\nconst _onRecordNodesCreateOrUpdate = async (\n params: NodesUpdateParams & { nodes: Dictionary<ArenaRecordNode>; additionalNodesToValidate?: NodesMap }\n): Promise<RecordUpdateResult> => {\n const {\n user,\n survey,\n categoryItemProvider,\n taxonProvider,\n areaOfInterestProvider,\n additionalNodesToValidate,\n dateModified = Dates.nowFormattedForStorage(),\n } = params\n\n const updateResult = await RecordNodesUpdater.updateNodesDependents(params)\n const { nodes: updatedNodes, record: updatedRecord } = updateResult\n\n const dependentValidationNodePointers = getDependentValidationNodePointers({\n survey,\n record: updatedRecord,\n nodes: updatedNodes,\n })\n\n const dependentValidationNodes = NodePointers.getNodesMapFromNodePointers({\n record: updatedRecord,\n nodePointers: dependentValidationNodePointers,\n })\n\n const nodesToValidate = { ...updatedNodes, ...dependentValidationNodes, ...additionalNodesToValidate }\n\n const validationUpdatedNodes = await RecordValidator.validateNodes({\n user,\n survey,\n categoryItemProvider,\n taxonProvider,\n areaOfInterestProvider,\n record: updatedRecord,\n nodes: nodesToValidate,\n })\n\n const validation = Validations.mergeValidations(validationUpdatedNodes)(Validations.getValidation(updatedRecord))\n updatedRecord.validation = validation\n updatedRecord.dateModified = dateModified\n\n updateResult.validation = validation\n\n return updateResult\n}\n\nconst createDescendants = async (params: NodeCreateParams): Promise<RecordUpdateResult> => {\n const { record: updatedRecord, nodes: createdNodes } = await RecordNodesUpdater.addDescendants(params)\n\n return _onRecordNodesCreateOrUpdate({ ...params, record: updatedRecord, nodes: createdNodes })\n}\n\nconst createNodeAndDescendants = async (params: NodeCreateParams): Promise<RecordUpdateResult> => {\n const { record: updatedRecord, nodes: createdNodes } = await RecordNodesUpdater.addNodeAndDescendants(params)\n\n return _onRecordNodesCreateOrUpdate({ ...params, record: updatedRecord, nodes: createdNodes })\n}\n\nconst createRootEntity = async (\n params: NodesUpdateParams & {\n createMultipleEntities?: boolean\n }\n): Promise<RecordUpdateResult> => {\n const { survey, createMultipleEntities = true } = params\n\n return createNodeAndDescendants({ ...params, nodeDef: Surveys.getNodeDefRoot({ survey }), createMultipleEntities })\n}\n\nconst updateAttributeValue = async (\n params: NodesUpdateParams & {\n attributeUuid: string\n value: any\n }\n): Promise<RecordUpdateResult> => {\n const { attributeUuid, record, value, dateModified = Dates.nowFormattedForStorage(), sideEffect = false } = params\n const attribute = Records.getNodeByUuid(attributeUuid)(record)\n if (!attribute) throw new SystemError(SystemErrorKeys.record.nodeNotFound, { uuid: attributeUuid })\n\n let attributeUpdated = sideEffect ? attribute : { ...attribute }\n attributeUpdated.value = value\n attributeUpdated.dateModified = dateModified\n // reset defaultValueApplied flag\n attributeUpdated = Objects.dissocPath({ obj: attributeUpdated, path: ['meta', 'defaultValueApplied'], sideEffect })\n\n const nodesUpdated = { [attributeUuid]: attributeUpdated }\n\n const _record = Records.addNode(attributeUpdated, { sideEffect })(record)\n\n return _onRecordNodesCreateOrUpdate({ ...params, record: _record, nodes: nodesUpdated })\n}\n\n/**\n * Returns the key and unique attributes of the siblings of the specified entities:\n * they could have been duplicates of the ones being deleted, so they must be validated again.\n */\nconst getEntityKeyOrUniqueAttributes = (params: {\n survey: Survey\n record: ArenaRecord\n entity: ArenaRecordNode\n uniqueAttributeDefs: NodeDef<any>[]\n}): ArenaRecordNode[] => {\n const { survey, record, entity, uniqueAttributeDefs } = params\n return [\n ...Records.getEntityKeyNodes(survey, entity)(record),\n ...uniqueAttributeDefs.flatMap((uniqueDef) => Records.getChildren(entity, uniqueDef.uuid)(record)),\n ].filter(Boolean)\n}\n\nconst getSiblingKeyOrUniqueAttributes = (params: {\n survey: Survey\n record: ArenaRecord\n nodeUuids: string[]\n}): NodesMap => {\n const { survey, record, nodeUuids } = params\n const nodeUuidsSet = new Set(nodeUuids)\n const result: NodesMap = {}\n for (const nodeUuid of nodeUuids) {\n const node = Records.getNodeByUuid(nodeUuid)(record)\n const parentNode = node ? Records.getParent(node)(record) : undefined\n const nodeDef = node ? Surveys.getNodeDefByUuid({ survey, uuid: node.nodeDefUuid }) : undefined\n if (!parentNode || !nodeDef || !NodeDefs.isEntity(nodeDef)) continue\n\n const uniqueAttributeDefs = Surveys.getNodeDefChildren({ survey, nodeDef }).filter(\n (childDef) => NodeDefs.getValidations(childDef)?.unique\n )\n const siblings = Records.getChildren(parentNode, nodeDef.uuid)(record).filter((s) => !nodeUuidsSet.has(s.uuid))\n for (const sibling of siblings) {\n for (const attribute of getEntityKeyOrUniqueAttributes({\n survey,\n record,\n entity: sibling,\n uniqueAttributeDefs,\n })) {\n result[attribute.uuid] = attribute\n }\n }\n }\n return result\n}\n\nconst deleteNodes = async (\n params: NodesUpdateParams & {\n nodeUuids: string[]\n }\n): Promise<RecordUpdateResult> => {\n const { survey, nodeUuids, record: _record, sideEffect = false } = params\n\n // found before removing the nodes: the deleted nodes are no longer reachable from their siblings afterwards\n const siblingKeyOrUniqueAttributes = getSiblingKeyOrUniqueAttributes({ survey, record: _record, nodeUuids })\n\n const updateResult = Records.removeNodes(nodeUuids, { sideEffect })(_record)\n const { record, nodesDeleted } = updateResult\n\n const result = await _onRecordNodesCreateOrUpdate({\n ...params,\n record,\n nodes: nodesDeleted,\n additionalNodesToValidate: siblingKeyOrUniqueAttributes,\n })\n result.nodesDeleted = nodesDeleted\n return result\n}\n\nconst deleteNode = async (params: NodesUpdateParams & { nodeUuid: string }): Promise<RecordUpdateResult> => {\n const { nodeUuid } = params\n return deleteNodes({ ...params, nodeUuids: [nodeUuid] })\n}\n\nexport const RecordUpdater = {\n /** Creates the descendants of a node and updates dependents (applicability, default values, calculations...) and validation */\n createDescendants,\n /** Creates a node and its descendants and updates dependents (applicability, default values, calculations...) and validation */\n createNodeAndDescendants,\n createRootEntity,\n updateAttributeValue,\n /** Deletes the node and its descendants and updates dependents (applicability, default values, calculations...) and validation */\n deleteNode,\n /** Deletes the nodes and their descendants and updates dependents (applicability, default values, calculations...) and validation */\n deleteNodes,\n}\n"]}
|
|
@@ -44,7 +44,8 @@ const _isEntityDuplicate = (params) => {
|
|
|
44
44
|
return false;
|
|
45
45
|
}
|
|
46
46
|
const keyValuesByDefUuid = _getKeyValuesByDefUuid({ survey, record, entity, keyDefs, cache });
|
|
47
|
-
|
|
47
|
+
// entities with all key values empty are never duplicates (they are reported as missing values)
|
|
48
|
+
return (!Object.values(keyValuesByDefUuid).every(utils_1.Objects.isEmpty) &&
|
|
48
49
|
siblingEntities.some((sibilingEntity) => {
|
|
49
50
|
const siblingKeyValuesByDefUuid = _getKeyValuesByDefUuid({
|
|
50
51
|
survey,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attributeKeyValidator.js","sourceRoot":"","sources":["../../../src/record/recordValidator/attributeKeyValidator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"attributeKeyValidator.js","sourceRoot":"","sources":["../../../src/record/recordValidator/attributeKeyValidator.ts"],"names":[],"mappings":"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","sourcesContent":["import { ArenaRecord } from '../record'\nimport { Records } from '../records'\nimport { NodeDef, NodeDefs, NodeDefProps, NodeDefType } from '../../nodeDef'\nimport { ArenaRecordNode, Nodes, NodeValues } from '../../node'\nimport { ValidationResult, ValidationResultFactory, ValidationSeverity } from '../../validation'\nimport { Survey, Surveys } from '../../survey'\n\nimport { Dictionary } from '../../common'\nimport { Objects } from '../../utils'\n\n/**\n * Cache of entity key values (and key defs by entity def) used during a single validation run (the record doesn't change):\n * without it, validating the keys of S sibling entities would compute the key values of every sibling S times.\n */\nexport type EntityKeysCache = {\n keyDefsByEntityDefUuid: Map<string, NodeDef<NodeDefType, NodeDefProps>[]>\n keyValuesByEntityUuid: Map<string, Dictionary<any>>\n}\n\nexport const createEntityKeysCache = (): EntityKeysCache => ({\n keyDefsByEntityDefUuid: new Map(),\n keyValuesByEntityUuid: new Map(),\n})\n\nconst _getKeyDefs = (params: {\n survey: Survey\n entityDef: NodeDef<NodeDefType, NodeDefProps>\n cache?: EntityKeysCache\n}): NodeDef<NodeDefType, NodeDefProps>[] => {\n const { survey, entityDef, cache } = params\n let keyDefs = cache?.keyDefsByEntityDefUuid.get(entityDef.uuid)\n if (!keyDefs) {\n keyDefs = Surveys.getNodeDefKeys({ survey, nodeDef: entityDef })\n cache?.keyDefsByEntityDefUuid.set(entityDef.uuid, keyDefs)\n }\n return keyDefs\n}\n\nconst _getKeyValuesByDefUuid = (params: {\n survey: Survey\n record: ArenaRecord\n entity: ArenaRecordNode\n keyDefs: NodeDef<NodeDefType, NodeDefProps>[]\n cache?: EntityKeysCache\n}): Dictionary<any> => {\n const { survey, record, entity, keyDefs, cache } = params\n let keyValues = cache?.keyValuesByEntityUuid.get(entity.uuid)\n if (!keyValues) {\n keyValues = Records.getEntityKeyValuesByDefUuid(survey, entity, undefined, keyDefs)(record)\n cache?.keyValuesByEntityUuid.set(entity.uuid, keyValues)\n }\n return keyValues\n}\n\nconst _isEntityDuplicate = (params: {\n survey: Survey\n record: ArenaRecord\n entity: ArenaRecordNode\n entityKeysCache?: EntityKeysCache\n}): boolean => {\n const { survey, entity, record, entityKeysCache: cache } = params\n // 1. get sibling entities\n const nodeParent = Records.getParent(entity)(record)\n if (!nodeParent) return false\n\n const siblingEntities = Records.getChildren(\n nodeParent,\n entity.nodeDefUuid\n )(record).filter((node) => !Nodes.areEqual(entity, node))\n\n // 2. get key values\n const entityDef = Surveys.getNodeDefByUuid({ survey, uuid: entity.nodeDefUuid })\n const keyDefs = _getKeyDefs({ survey, entityDef, cache })\n\n if (Objects.isEmpty(siblingEntities) || Objects.isEmpty(keyDefs)) {\n return false\n }\n const keyValuesByDefUuid = _getKeyValuesByDefUuid({ survey, record, entity, keyDefs, cache })\n // entities with all key values empty are never duplicates (they are reported as missing values)\n return (\n !Object.values(keyValuesByDefUuid).every(Objects.isEmpty) &&\n siblingEntities.some((sibilingEntity) => {\n const siblingKeyValuesByDefUuid = _getKeyValuesByDefUuid({\n survey,\n record,\n entity: sibilingEntity,\n keyDefs,\n cache,\n })\n return keyDefs.every((keyDef) => {\n const keyValue = keyValuesByDefUuid[keyDef.uuid]\n const siblingKeyValue = siblingKeyValuesByDefUuid[keyDef.uuid]\n return NodeValues.isValueEqual({\n survey,\n nodeDef: keyDef,\n value: keyValue,\n valueSearch: siblingKeyValue,\n })\n })\n })\n )\n}\n\nconst isNodeDefToBeValidated = (params: { survey: Survey; nodeDef: NodeDef<NodeDefType, NodeDefProps> }): boolean => {\n const { survey, nodeDef } = params\n if (!NodeDefs.isKey(nodeDef)) return false\n\n const nodeDefParent = Surveys.getNodeDefParent({ survey, nodeDef })\n // root entity key attributes will be validated by another validator\n return !!nodeDefParent && !NodeDefs.isRoot(nodeDefParent)\n}\n\nconst validateAttributeKey =\n (params: {\n survey: Survey\n record: ArenaRecord\n nodeDef: NodeDef<NodeDefType, NodeDefProps>\n entityKeysCache?: EntityKeysCache\n }) =>\n (_propName: string, node: ArenaRecordNode): Promise<ValidationResult> => {\n const { survey, nodeDef, record, entityKeysCache } = params\n\n if (isNodeDefToBeValidated({ survey, nodeDef })) {\n const entity = Records.getParent(node)(record)\n if (entity && _isEntityDuplicate({ survey, record, entity, entityKeysCache })) {\n return Promise.resolve(\n ValidationResultFactory.createInstance({\n valid: false,\n severity: ValidationSeverity.error,\n key: 'record.entity.keyDuplicate',\n })\n )\n }\n }\n\n return Promise.resolve(ValidationResultFactory.createInstance())\n }\n\nexport const AttributeKeyValidator = {\n validateAttributeKey,\n}\n"]}
|
package/dist/record/records.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getCycle, getRoot, getNodes, getNodesArray, getNodeByUuid, getNodesByUuids, getNodesByDefUuid, getChild, getChildren, getParent, getParentCodeAttribute, getAncestorCodePath, getDependentCodeAttributes, getAncestor, getEntityKeyNodes, getEntityKeyNodesByDefUuid, getEntityKeyValues, getEntityKeyValuesByDefUuid, getEntitySiblings, getAttributeSiblings, getNodeIndex, isNodeRequired, visitAncestorsAndSelf, getAncestorsAndSelf, getDescendant, getDescendantsOrSelf, isDescendantOf, visitDescendantsAndSelf, getDependentNodePointers, findEntityByKeyValues, findEntityWithSameKeysInAnotherRecord, getCategoryItemUuid, isNodeEmpty, isNodeFilledByUser, isEmpty, getStep, isInAnalysisStep } from './_records/recordGetters';
|
|
1
|
+
import { getCycle, getRoot, getNodes, getNodesArray, getNodeByUuid, getNodesByUuids, getNodesByDefUuid, getChild, getChildren, getParent, getParentCodeAttribute, getAncestorCodeAttributes, getAncestorCodePath, getDependentCodeAttributes, getAncestor, getEntityKeyNodes, getEntityKeyNodesByDefUuid, getEntityKeyValues, getEntityKeyValuesByDefUuid, getEntitySiblings, getAttributeSiblings, getNodeIndex, isNodeRequired, visitAncestorsAndSelf, getAncestorsAndSelf, getDescendant, getDescendantsOrSelf, isDescendantOf, visitDescendantsAndSelf, getDependentNodePointers, findEntityByKeyValues, findEntityWithSameKeysInAnotherRecord, getCategoryItemUuid, isNodeEmpty, isNodeFilledByUser, isEmpty, getStep, isInAnalysisStep } from './_records/recordGetters';
|
|
2
2
|
import { addNode, addNodes } from './_records/recordUpdater';
|
|
3
3
|
import { getEnumeratingCategoryItems, findDependentEnumeratedEntityDefsNotEmpty } from './_records/recordUtils';
|
|
4
4
|
import { getEntityCompletionPercent, getEntityCompletionStats, getEntityOwnCompletionPercent, getRecordCompletionPercent } from './_records/recordCompletion';
|
|
@@ -16,6 +16,7 @@ export declare const Records: {
|
|
|
16
16
|
getChildren: typeof getChildren;
|
|
17
17
|
getParent: typeof getParent;
|
|
18
18
|
getParentCodeAttribute: typeof getParentCodeAttribute;
|
|
19
|
+
getAncestorCodeAttributes: typeof getAncestorCodeAttributes;
|
|
19
20
|
getAncestorCodePath: typeof getAncestorCodePath;
|
|
20
21
|
getDependentCodeAttributes: typeof getDependentCodeAttributes;
|
|
21
22
|
getAncestor: typeof getAncestor;
|
package/dist/record/records.js
CHANGED
|
@@ -20,6 +20,7 @@ exports.Records = {
|
|
|
20
20
|
getChildren: recordGetters_1.getChildren,
|
|
21
21
|
getParent: recordGetters_1.getParent,
|
|
22
22
|
getParentCodeAttribute: recordGetters_1.getParentCodeAttribute,
|
|
23
|
+
getAncestorCodeAttributes: recordGetters_1.getAncestorCodeAttributes,
|
|
23
24
|
getAncestorCodePath: recordGetters_1.getAncestorCodePath,
|
|
24
25
|
getDependentCodeAttributes: recordGetters_1.getDependentCodeAttributes,
|
|
25
26
|
getAncestor: recordGetters_1.getAncestor,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/record/records.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/record/records.ts"],"names":[],"mappings":";;;AAAA,4DA0CiC;AACjC,4DAA4D;AAC5D,wDAA+G;AAC/G,kEAKoC;AACpC,4EAWyC;AACzC,gFAAiF;AAEpE,QAAA,OAAO,GAAG;IACrB,OAAO;IACP,QAAQ,EAAR,wBAAQ;IACR,OAAO,EAAP,uBAAO;IACP,QAAQ,EAAR,wBAAQ;IACR,aAAa,EAAb,6BAAa;IACb,aAAa,EAAb,6BAAa;IACb,eAAe,EAAf,+BAAe;IACf,iBAAiB,EAAjB,iCAAiB;IACjB,QAAQ,EAAR,wBAAQ;IACR,WAAW,EAAX,2BAAW;IACX,SAAS,EAAT,yBAAS;IACT,sBAAsB,EAAtB,sCAAsB;IACtB,yBAAyB,EAAzB,yCAAyB;IACzB,mBAAmB,EAAnB,mCAAmB;IACnB,0BAA0B,EAA1B,0CAA0B;IAC1B,WAAW,EAAX,2BAAW;IACX,iBAAiB,EAAjB,iCAAiB;IACjB,0BAA0B,EAA1B,0CAA0B;IAC1B,kBAAkB,EAAlB,kCAAkB;IAClB,2BAA2B,EAA3B,2CAA2B;IAC3B,iBAAiB,EAAjB,iCAAiB;IACjB,oBAAoB,EAApB,oCAAoB;IACpB,YAAY,EAAZ,4BAAY;IACZ,gBAAgB,EAAhB,gCAAgB;IAChB,cAAc,EAAd,8BAAc;IACd,aAAa,EAAb,6BAAa;IACb,cAAc,EAAd,8BAAc;IACd,qBAAqB,EAArB,qCAAqB;IACrB,mBAAmB,EAAnB,mCAAmB;IACnB,aAAa,EAAb,6BAAa;IACb,oBAAoB,EAApB,oCAAoB;IACpB,cAAc,EAAd,8BAAc;IACd,uBAAuB,EAAvB,uCAAuB;IACvB,wBAAwB,EAAxB,wCAAwB;IACxB,qBAAqB,EAArB,qCAAqB;IACrB,qCAAqC,EAArC,qDAAqC;IACrC,mBAAmB,EAAnB,mCAAmB;IACnB,WAAW,EAAX,2BAAW;IACX,kBAAkB,EAAlB,kCAAkB;IAClB,OAAO,EAAP,uBAAO;IACP,OAAO,EAAP,uBAAO;IACP,gBAAgB,EAAhB,gCAAgB;IAChB,0BAA0B,EAA1B,6CAA0B;IAC1B,wBAAwB,EAAxB,2CAAwB;IACxB,6BAA6B,EAA7B,gDAA6B;IAC7B,0BAA0B,EAA1B,6CAA0B;IAC1B,2BAA2B,EAA3B,mDAA2B;IAC3B,eAAe,EAAf,uCAAe;IACf,6BAA6B,EAA7B,qDAA6B;IAC7B,iBAAiB,EAAjB,yCAAiB;IACjB,oBAAoB,EAApB,4CAAoB;IACpB,uBAAuB,EAAvB,+CAAuB;IACvB,gBAAgB,EAAhB,wCAAgB;IAChB,gCAAgC,EAAhC,wDAAgC;IAChC,sBAAsB,EAAtB,8CAAsB;IACtB,6BAA6B,EAA7B,qDAA6B;IAC7B,SAAS;IACT,OAAO,EAAP,uBAAO;IACP,QAAQ,EAAR,wBAAQ;IACR,gIAAgI;IAChI,UAAU,EAAV,+BAAU;IACV,oIAAoI;IACpI,WAAW,EAAX,gCAAW;IACX,uGAAuG;IACvG,UAAU,EAAE,+BAAU;IACtB,yGAAyG;IACzG,WAAW,EAAE,gCAAW;IACxB,QAAQ;IACR,2BAA2B,EAA3B,yCAA2B;IAC3B,yCAAyC,EAAzC,uDAAyC;CAC1C,CAAA","sourcesContent":["import {\n getCycle,\n getRoot,\n getNodes,\n getNodesArray,\n getNodeByUuid,\n getNodesByUuids,\n getNodesByDefUuid,\n getChild,\n getChildren,\n getParent,\n getParentCodeAttribute,\n getAncestorCodeAttributes,\n getAncestorCodePath,\n getDependentCodeAttributes,\n getAncestor,\n getEntityKeyNodes,\n getEntityKeyNodesByDefUuid,\n getEntityKeyValues,\n getEntityKeyValuesByDefUuid,\n getEntitySiblings,\n getAttributeSiblings,\n getNodeIndex,\n isNodeApplicable,\n isNodeEditable,\n isNodeVisible,\n isNodeRequired,\n visitAncestorsAndSelf,\n getAncestorsAndSelf,\n getDescendant,\n getDescendantsOrSelf,\n isDescendantOf,\n visitDescendantsAndSelf,\n getDependentNodePointers,\n findEntityByKeyValues,\n findEntityWithSameKeysInAnotherRecord,\n getCategoryItemUuid,\n isNodeEmpty,\n isNodeFilledByUser,\n isEmpty,\n getStep,\n isInAnalysisStep,\n} from './_records/recordGetters'\nimport { addNode, addNodes } from './_records/recordUpdater'\nimport { getEnumeratingCategoryItems, findDependentEnumeratedEntityDefsNotEmpty } from './_records/recordUtils'\nimport {\n getEntityCompletionPercent,\n getEntityCompletionStats,\n getEntityOwnCompletionPercent,\n getRecordCompletionPercent,\n} from './_records/recordCompletion'\nimport {\n getDescendantPageNodeDefUuids,\n getEntitySubtreeStatus,\n getMultiplePageEntitiesStatus,\n getNodeDefChildrenInOwnPage,\n getPageNodeDefs,\n getPageValidationStatus,\n getRecordPagesValidationProgress,\n nodeBelongsToOwnPage,\n nodeBelongsToPage,\n pageHasOwnErrors,\n} from './_records/recordPagesValidation'\nimport { removeNode, removeNodes } from './recordNodesUpdater/recordNodesDeleter'\n\nexport const Records = {\n // READ\n getCycle,\n getRoot,\n getNodes,\n getNodesArray,\n getNodeByUuid,\n getNodesByUuids,\n getNodesByDefUuid,\n getChild,\n getChildren,\n getParent,\n getParentCodeAttribute,\n getAncestorCodeAttributes,\n getAncestorCodePath,\n getDependentCodeAttributes,\n getAncestor,\n getEntityKeyNodes,\n getEntityKeyNodesByDefUuid,\n getEntityKeyValues,\n getEntityKeyValuesByDefUuid,\n getEntitySiblings,\n getAttributeSiblings,\n getNodeIndex,\n isNodeApplicable,\n isNodeEditable,\n isNodeVisible,\n isNodeRequired,\n visitAncestorsAndSelf,\n getAncestorsAndSelf,\n getDescendant,\n getDescendantsOrSelf,\n isDescendantOf,\n visitDescendantsAndSelf,\n getDependentNodePointers,\n findEntityByKeyValues,\n findEntityWithSameKeysInAnotherRecord,\n getCategoryItemUuid,\n isNodeEmpty,\n isNodeFilledByUser,\n isEmpty,\n getStep,\n isInAnalysisStep,\n getEntityCompletionPercent,\n getEntityCompletionStats,\n getEntityOwnCompletionPercent,\n getRecordCompletionPercent,\n getNodeDefChildrenInOwnPage,\n getPageNodeDefs,\n getDescendantPageNodeDefUuids,\n nodeBelongsToPage,\n nodeBelongsToOwnPage,\n getPageValidationStatus,\n pageHasOwnErrors,\n getRecordPagesValidationProgress,\n getEntitySubtreeStatus,\n getMultiplePageEntitiesStatus,\n // UPDATE\n addNode,\n addNodes,\n /** Low-level: removes the node and its descendants without updating dependents and validation (see RecordUpdater.deleteNode) */\n removeNode,\n /** Low-level: removes the nodes and their descendants without updating dependents and validation (see RecordUpdater.deleteNodes) */\n removeNodes,\n /** @deprecated Use removeNode (or RecordUpdater.deleteNode to update dependents and validation too) */\n deleteNode: removeNode,\n /** @deprecated Use removeNodes (or RecordUpdater.deleteNodes to update dependents and validation too) */\n deleteNodes: removeNodes,\n // Utils\n getEnumeratingCategoryItems,\n findDependentEnumeratedEntityDefsNotEmpty,\n}\n\nexport type { RecordUpdateOptions } from './_records/recordUpdateOptions'\nexport type {\n EntitySubtreeStatus,\n PageValidationStatus,\n PagesValidationProgress,\n} from './_records/recordPagesValidation'\n"]}
|