@nocobase/plugin-collection-tree 2.1.0-alpha.40 → 2.1.0-alpha.45
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/externalVersion.js
CHANGED
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
|
-
"@nocobase/client": "2.1.0-alpha.
|
|
12
|
-
"@nocobase/database": "2.1.0-alpha.
|
|
13
|
-
"@nocobase/utils": "2.1.0-alpha.
|
|
11
|
+
"@nocobase/client": "2.1.0-alpha.45",
|
|
12
|
+
"@nocobase/database": "2.1.0-alpha.45",
|
|
13
|
+
"@nocobase/utils": "2.1.0-alpha.45",
|
|
14
14
|
"lodash": "4.18.1",
|
|
15
|
-
"@nocobase/data-source-manager": "2.1.0-alpha.
|
|
16
|
-
"@nocobase/server": "2.1.0-alpha.
|
|
15
|
+
"@nocobase/data-source-manager": "2.1.0-alpha.45",
|
|
16
|
+
"@nocobase/server": "2.1.0-alpha.45",
|
|
17
17
|
"sequelize": "6.35.2"
|
|
18
18
|
};
|
|
@@ -42,6 +42,7 @@ module.exports = __toCommonJS(adjacency_list_repository_exports);
|
|
|
42
42
|
var import_database = require("@nocobase/database");
|
|
43
43
|
var import_utils = require("@nocobase/utils");
|
|
44
44
|
var import_lodash = __toESM(require("lodash"));
|
|
45
|
+
var import_cycle_detection = require("./cycle-detection");
|
|
45
46
|
class AdjacencyListRepository extends import_database.Repository {
|
|
46
47
|
async update(options) {
|
|
47
48
|
return super.update({
|
|
@@ -118,13 +119,23 @@ class AdjacencyListRepository extends import_database.Repository {
|
|
|
118
119
|
}
|
|
119
120
|
nodeMap[`${node[foreignKey]}`].push(node);
|
|
120
121
|
});
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
const getNodePrimaryKey = (node) => node.get(primaryKey);
|
|
123
|
+
function buildTree(rootId, path, pathIndex) {
|
|
124
|
+
const children = nodeMap[String(rootId)];
|
|
123
125
|
if (!children) {
|
|
124
126
|
return [];
|
|
125
127
|
}
|
|
126
128
|
return children.map((child) => {
|
|
127
|
-
const
|
|
129
|
+
const childPrimaryKey = getNodePrimaryKey(child);
|
|
130
|
+
const cycleStartIndex = pathIndex.get(String(childPrimaryKey));
|
|
131
|
+
if (cycleStartIndex !== void 0) {
|
|
132
|
+
throw new Error((0, import_cycle_detection.formatTreeCycleError)(collection.name, [...path.slice(cycleStartIndex), childPrimaryKey]));
|
|
133
|
+
}
|
|
134
|
+
pathIndex.set(String(childPrimaryKey), path.length);
|
|
135
|
+
path.push(childPrimaryKey);
|
|
136
|
+
const childrenValues = buildTree(childPrimaryKey, path, pathIndex);
|
|
137
|
+
path.pop();
|
|
138
|
+
pathIndex.delete(String(childPrimaryKey));
|
|
128
139
|
if (childrenValues.length > 0) {
|
|
129
140
|
child.setDataValue(childrenKey, childrenValues);
|
|
130
141
|
}
|
|
@@ -132,8 +143,8 @@ class AdjacencyListRepository extends import_database.Repository {
|
|
|
132
143
|
});
|
|
133
144
|
}
|
|
134
145
|
for (const root of rootNodes) {
|
|
135
|
-
const rootId = root
|
|
136
|
-
const children = buildTree(rootId);
|
|
146
|
+
const rootId = getNodePrimaryKey(root);
|
|
147
|
+
const children = buildTree(rootId, [rootId], /* @__PURE__ */ new Map([[String(rootId), 0]]));
|
|
137
148
|
if (children.length > 0) {
|
|
138
149
|
root.setDataValue(childrenKey, children);
|
|
139
150
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
export type TreeNodeKey = string | number;
|
|
10
|
+
export declare function findCyclePath(path: TreeNodeKey[], nodeKey: TreeNodeKey): TreeNodeKey[] | null;
|
|
11
|
+
export declare function formatTreeCycleError(collectionName: string, cyclePath: TreeNodeKey[]): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var cycle_detection_exports = {};
|
|
28
|
+
__export(cycle_detection_exports, {
|
|
29
|
+
findCyclePath: () => findCyclePath,
|
|
30
|
+
formatTreeCycleError: () => formatTreeCycleError
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(cycle_detection_exports);
|
|
33
|
+
function findCyclePath(path, nodeKey) {
|
|
34
|
+
const nodeKeyString = String(nodeKey);
|
|
35
|
+
const cycleStartIndex = path.findIndex((pathNodeKey) => String(pathNodeKey) === nodeKeyString);
|
|
36
|
+
if (cycleStartIndex === -1) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return [...path.slice(cycleStartIndex), nodeKey];
|
|
40
|
+
}
|
|
41
|
+
function formatTreeCycleError(collectionName, cyclePath) {
|
|
42
|
+
return `Cycle detected in ${collectionName}: ${cyclePath.join(" -> ")}`;
|
|
43
|
+
}
|
|
44
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
45
|
+
0 && (module.exports = {
|
|
46
|
+
findCyclePath,
|
|
47
|
+
formatTreeCycleError
|
|
48
|
+
});
|
package/dist/server/plugin.d.ts
CHANGED
package/dist/server/plugin.js
CHANGED
|
@@ -42,6 +42,7 @@ module.exports = __toCommonJS(plugin_exports);
|
|
|
42
42
|
var import_data_source_manager = require("@nocobase/data-source-manager");
|
|
43
43
|
var import_server = require("@nocobase/server");
|
|
44
44
|
var import_lodash = __toESM(require("lodash"));
|
|
45
|
+
var import_cycle_detection = require("./cycle-detection");
|
|
45
46
|
var import_tree_collection = require("./tree-collection");
|
|
46
47
|
class PluginCollectionTreeServer extends import_server.Plugin {
|
|
47
48
|
async beforeLoad() {
|
|
@@ -138,13 +139,28 @@ class PluginCollectionTreeServer extends import_server.Plugin {
|
|
|
138
139
|
transaction: options2.transaction
|
|
139
140
|
});
|
|
140
141
|
});
|
|
141
|
-
this.db.on(`${collection.name}.beforeSave`, async (model) => {
|
|
142
|
-
var _a;
|
|
142
|
+
this.db.on(`${collection.name}.beforeSave`, async (model, options2) => {
|
|
143
|
+
var _a, _b;
|
|
143
144
|
const tk = collection.filterTargetKey;
|
|
144
145
|
const parentForeignKey = ((_a = collection.treeParentField) == null ? void 0 : _a.foreignKey) || "parentId";
|
|
145
|
-
|
|
146
|
+
const nodePrimaryKey = model.get(tk);
|
|
147
|
+
const parentPrimaryKey = model.get(parentForeignKey);
|
|
148
|
+
if (nodePrimaryKey !== null && nodePrimaryKey !== void 0 && parentPrimaryKey !== null && parentPrimaryKey !== void 0 && String(parentPrimaryKey) === String(nodePrimaryKey)) {
|
|
146
149
|
throw new Error("Cannot set itself as the parent node");
|
|
147
150
|
}
|
|
151
|
+
if (nodePrimaryKey === null || nodePrimaryKey === void 0 || parentPrimaryKey === null || parentPrimaryKey === void 0) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const isParentChanged = model.isNewRecord || typeof model.changed === "function" && Boolean(model.changed(parentForeignKey)) || ((_b = model["_changed"]) == null ? void 0 : _b.has(parentForeignKey));
|
|
155
|
+
if (!isParentChanged) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
await this.validateTreeParent({
|
|
159
|
+
collection,
|
|
160
|
+
nodePrimaryKey,
|
|
161
|
+
parentPrimaryKey,
|
|
162
|
+
transaction: options2 == null ? void 0 : options2.transaction
|
|
163
|
+
});
|
|
148
164
|
});
|
|
149
165
|
this.db.on("collections.afterDestroy", async (collection2, { transaction }) => {
|
|
150
166
|
const name2 = `main_${collection2.get("name")}_path`;
|
|
@@ -224,6 +240,35 @@ class PluginCollectionTreeServer extends import_server.Plugin {
|
|
|
224
240
|
}
|
|
225
241
|
return path;
|
|
226
242
|
}
|
|
243
|
+
async validateTreeParent({
|
|
244
|
+
collection,
|
|
245
|
+
nodePrimaryKey,
|
|
246
|
+
parentPrimaryKey,
|
|
247
|
+
transaction
|
|
248
|
+
}) {
|
|
249
|
+
var _a;
|
|
250
|
+
const tk = collection.filterTargetKey;
|
|
251
|
+
const parentForeignKey = ((_a = collection.treeParentField) == null ? void 0 : _a.foreignKey) || "parentId";
|
|
252
|
+
const path = [nodePrimaryKey];
|
|
253
|
+
let currentParentPrimaryKey = parentPrimaryKey;
|
|
254
|
+
while (currentParentPrimaryKey !== null && currentParentPrimaryKey !== void 0) {
|
|
255
|
+
if ((0, import_cycle_detection.findCyclePath)(path, currentParentPrimaryKey)) {
|
|
256
|
+
throw new Error("Cannot set a descendant node as the parent node");
|
|
257
|
+
}
|
|
258
|
+
path.push(currentParentPrimaryKey);
|
|
259
|
+
const parent = await this.app.db.getRepository(collection.name).findOne({
|
|
260
|
+
fields: [tk, parentForeignKey],
|
|
261
|
+
filter: {
|
|
262
|
+
[tk]: currentParentPrimaryKey
|
|
263
|
+
},
|
|
264
|
+
transaction
|
|
265
|
+
});
|
|
266
|
+
if (!parent) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
currentParentPrimaryKey = parent.get(parentForeignKey);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
227
272
|
async updateTreePath(model, collection, pathCollectionName, transaction) {
|
|
228
273
|
const tk = collection.filterTargetKey;
|
|
229
274
|
let path = `/${model.get(tk)}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/plugin-collection-tree",
|
|
3
|
-
"version": "2.1.0-alpha.
|
|
3
|
+
"version": "2.1.0-alpha.45",
|
|
4
4
|
"displayName": "Collection: Tree",
|
|
5
5
|
"displayName.ru-RU": "Древовидная Коллекция",
|
|
6
6
|
"displayName.zh-CN": "数据表:树",
|
|
@@ -17,5 +17,5 @@
|
|
|
17
17
|
"@nocobase/test": "2.x"
|
|
18
18
|
},
|
|
19
19
|
"license": "Apache-2.0",
|
|
20
|
-
"gitHead": "
|
|
20
|
+
"gitHead": "e9e24987e12d0ad10a5db8815b1e1b7b447f1938"
|
|
21
21
|
}
|