@nocobase/flow-engine 2.0.0-alpha.4 → 2.0.0-alpha.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.
@@ -49,6 +49,7 @@ module.exports = __toCommonJS(data_source_exports);
49
49
  var import_reactive = require("@formily/reactive");
50
50
  var import_lodash = __toESM(require("lodash"));
51
51
  var import_jioToJoiSchema = require("./jioToJoiSchema");
52
+ var import_sortCollectionsByInherits = require("./sortCollectionsByInherits");
52
53
  const _DataSourceManager = class _DataSourceManager {
53
54
  dataSources;
54
55
  flowEngine;
@@ -220,7 +221,7 @@ const _CollectionManager = class _CollectionManager {
220
221
  return this.getCollection(options.name);
221
222
  }
222
223
  upsertCollections(collections) {
223
- for (const collection of this.sortCollectionsByInherits(collections)) {
224
+ for (const collection of (0, import_sortCollectionsByInherits.sortCollectionsByInherits)(collections)) {
224
225
  if (this.collections.has(collection.name)) {
225
226
  this.updateCollection(collection);
226
227
  } else {
@@ -368,7 +369,8 @@ const _Collection = class _Collection {
368
369
  for (const inherit of this.options.inherits || []) {
369
370
  const collection = this.collectionManager.getCollection(inherit);
370
371
  if (!collection) {
371
- throw new Error(`Collection ${inherit} not found`);
372
+ console.warn(`Warning: Collection ${inherit} not found for collection ${this.name}`);
373
+ continue;
372
374
  }
373
375
  this.inherits.set(inherit, collection);
374
376
  }
@@ -0,0 +1,10 @@
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
+ import { CollectionOptions } from '.';
10
+ export declare function sortCollectionsByInherits(collections: CollectionOptions[]): CollectionOptions[];
@@ -0,0 +1,71 @@
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 __name = (target, value) => __defProp(target, "name", { value, configurable: true });
15
+ var __export = (target, all) => {
16
+ for (var name in all)
17
+ __defProp(target, name, { get: all[name], enumerable: true });
18
+ };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
24
+ }
25
+ return to;
26
+ };
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var sortCollectionsByInherits_exports = {};
29
+ __export(sortCollectionsByInherits_exports, {
30
+ sortCollectionsByInherits: () => sortCollectionsByInherits
31
+ });
32
+ module.exports = __toCommonJS(sortCollectionsByInherits_exports);
33
+ function sortCollectionsByInherits(collections) {
34
+ const sorted = [];
35
+ const visited = /* @__PURE__ */ new Set();
36
+ const visiting = /* @__PURE__ */ new Set();
37
+ const map = /* @__PURE__ */ new Map();
38
+ collections.forEach((col) => {
39
+ map.set(col.name, col);
40
+ });
41
+ const addToSorted = /* @__PURE__ */ __name((col) => {
42
+ if (visiting.has(col.name)) {
43
+ throw new Error(`Circular dependency detected: ${col.name} inherits from itself through a chain`);
44
+ }
45
+ if (visited.has(col.name)) {
46
+ return;
47
+ }
48
+ visiting.add(col.name);
49
+ const inherits = col.inherits || [];
50
+ for (const inheritName of inherits) {
51
+ const inheritCol = map.get(inheritName);
52
+ if (!inheritCol) {
53
+ console.warn(`Warning: Collection ${inheritName}, inherited by ${col.name}, not found.`);
54
+ continue;
55
+ }
56
+ addToSorted(inheritCol);
57
+ }
58
+ visiting.delete(col.name);
59
+ visited.add(col.name);
60
+ sorted.push(col);
61
+ }, "addToSorted");
62
+ for (const col of collections) {
63
+ addToSorted(col);
64
+ }
65
+ return sorted;
66
+ }
67
+ __name(sortCollectionsByInherits, "sortCollectionsByInherits");
68
+ // Annotate the CommonJS export names for ESM import in node:
69
+ 0 && (module.exports = {
70
+ sortCollectionsByInherits
71
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/flow-engine",
3
- "version": "2.0.0-alpha.4",
3
+ "version": "2.0.0-alpha.5",
4
4
  "private": false,
5
5
  "description": "A standalone flow engine for NocoBase, managing workflows, models, and actions.",
6
6
  "main": "lib/index.js",
@@ -33,5 +33,5 @@
33
33
  ],
34
34
  "author": "NocoBase Team",
35
35
  "license": "AGPL-3.0",
36
- "gitHead": "54f3cab47e7efbdc73377014d05f5fc66a4affbb"
36
+ "gitHead": "943e035bbec27f9ecfe8ce8857955945f20976f3"
37
37
  }
@@ -0,0 +1,125 @@
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
+ import { describe, expect, it } from 'vitest';
11
+ import { sortCollectionsByInherits } from '../sortCollectionsByInherits';
12
+
13
+ describe('sortCollectionsByInherits', () => {
14
+ it('should sort collections by their inherits in correct order', () => {
15
+ const collections = [
16
+ { name: 'posts', inherits: [] },
17
+ { name: 'comments', inherits: ['posts'] },
18
+ { name: 'users', inherits: ['comments'] },
19
+ ];
20
+ const sorted = sortCollectionsByInherits(collections);
21
+ expect(sorted.map((c) => c.name)).toEqual(['posts', 'comments', 'users']);
22
+ });
23
+
24
+ it('should handle collections with no inherits', () => {
25
+ const collections = [
26
+ { name: 'users', inherits: [] },
27
+ { name: 'posts', inherits: [] },
28
+ ];
29
+ const sorted = sortCollectionsByInherits(collections);
30
+ expect(sorted.map((c) => c.name)).toEqual(['users', 'posts']);
31
+ });
32
+
33
+ it('should handle collections with undefined inherits', () => {
34
+ const collections = [{ name: 'users' }, { name: 'posts' }];
35
+ const sorted = sortCollectionsByInherits(collections);
36
+ expect(sorted.map((c) => c.name)).toEqual(['users', 'posts']);
37
+ });
38
+
39
+ it('should handle complex inheritance chains', () => {
40
+ const collections = [
41
+ { name: 'base', inherits: [] },
42
+ { name: 'middle', inherits: ['base'] },
43
+ { name: 'top', inherits: ['middle'] },
44
+ { name: 'independent', inherits: [] },
45
+ ];
46
+ const sorted = sortCollectionsByInherits(collections);
47
+ expect(sorted.map((c) => c.name)).toEqual(['base', 'middle', 'top', 'independent']);
48
+ });
49
+
50
+ it('should handle multiple inheritance', () => {
51
+ const collections = [
52
+ { name: 'user', inherits: [] },
53
+ { name: 'post', inherits: [] },
54
+ { name: 'comment', inherits: ['user', 'post'] },
55
+ ];
56
+ const sorted = sortCollectionsByInherits(collections);
57
+ expect(sorted.map((c) => c.name)).toEqual(['user', 'post', 'comment']);
58
+ });
59
+
60
+ it('should throw error for circular dependencies', () => {
61
+ const collections = [
62
+ { name: 'a', inherits: ['b'] },
63
+ { name: 'b', inherits: ['a'] },
64
+ ];
65
+ expect(() => sortCollectionsByInherits(collections)).toThrow('Circular dependency detected');
66
+ });
67
+
68
+ it('should gracefully handle missing inherit collections', () => {
69
+ const collections = [
70
+ { name: 'posts', inherits: ['nonexistent'] },
71
+ { name: 'users', inherits: [] },
72
+ ];
73
+ const sorted = sortCollectionsByInherits(collections);
74
+ expect(sorted.map((c) => c.name)).toEqual(['posts', 'users']);
75
+ });
76
+
77
+ it('should handle self-inheritance circular dependency', () => {
78
+ const collections = [{ name: 'posts', inherits: ['posts'] }];
79
+ expect(() => sortCollectionsByInherits(collections)).toThrow('Circular dependency detected');
80
+ });
81
+
82
+ it('should maintain order for collections without dependencies', () => {
83
+ const collections = [
84
+ { name: 'z', inherits: [] },
85
+ { name: 'a', inherits: [] },
86
+ { name: 'm', inherits: [] },
87
+ ];
88
+ const sorted = sortCollectionsByInherits(collections);
89
+ expect(sorted.map((c) => c.name)).toEqual(['z', 'a', 'm']);
90
+ });
91
+
92
+ it('should handle empty collections array', () => {
93
+ const sorted = sortCollectionsByInherits([]);
94
+ expect(sorted).toEqual([]);
95
+ });
96
+
97
+ it('should handle collections with multiple missing inherits', () => {
98
+ const collections = [
99
+ { name: 'posts', inherits: ['missing1', 'missing2'] },
100
+ { name: 'users', inherits: ['missing3'] },
101
+ { name: 'comments', inherits: ['posts', 'missing4'] },
102
+ ];
103
+ const sorted = sortCollectionsByInherits(collections);
104
+ expect(sorted.map((c) => c.name)).toEqual(['posts', 'users', 'comments']);
105
+ });
106
+
107
+ it('should handle mixed existing and missing inherits', () => {
108
+ const collections = [
109
+ { name: 'base', inherits: [] },
110
+ { name: 'middle', inherits: ['base', 'missing'] },
111
+ { name: 'top', inherits: ['middle'] },
112
+ ];
113
+ const sorted = sortCollectionsByInherits(collections);
114
+ expect(sorted.map((c) => c.name)).toEqual(['base', 'middle', 'top']);
115
+ });
116
+
117
+ it('should handle all inherits missing', () => {
118
+ const collections = [
119
+ { name: 'posts', inherits: ['missing1', 'missing2'] },
120
+ { name: 'users', inherits: ['missing3'] },
121
+ ];
122
+ const sorted = sortCollectionsByInherits(collections);
123
+ expect(sorted.map((c) => c.name)).toEqual(['posts', 'users']);
124
+ });
125
+ });
@@ -11,6 +11,7 @@ import { observable } from '@formily/reactive';
11
11
  import _ from 'lodash';
12
12
  import { FlowEngine } from '../flowEngine';
13
13
  import { jioToJoiSchema } from './jioToJoiSchema';
14
+ import { sortCollectionsByInherits } from './sortCollectionsByInherits';
14
15
  export interface DataSourceOptions extends Record<string, any> {
15
16
  key: string;
16
17
  displayName?: string;
@@ -227,7 +228,7 @@ export class CollectionManager {
227
228
  }
228
229
 
229
230
  upsertCollections(collections: CollectionOptions[]) {
230
- for (const collection of this.sortCollectionsByInherits(collections)) {
231
+ for (const collection of sortCollectionsByInherits(collections)) {
231
232
  if (this.collections.has(collection.name)) {
232
233
  this.updateCollection(collection);
233
234
  } else {
@@ -400,7 +401,8 @@ export class Collection {
400
401
  for (const inherit of this.options.inherits || []) {
401
402
  const collection = this.collectionManager.getCollection(inherit);
402
403
  if (!collection) {
403
- throw new Error(`Collection ${inherit} not found`);
404
+ console.warn(`Warning: Collection ${inherit} not found for collection ${this.name}`);
405
+ continue;
404
406
  }
405
407
  this.inherits.set(inherit, collection);
406
408
  }
@@ -0,0 +1,61 @@
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
+ import { CollectionOptions } from '.';
11
+
12
+ export function sortCollectionsByInherits(collections: CollectionOptions[]): CollectionOptions[] {
13
+ const sorted: CollectionOptions[] = [];
14
+ const visited = new Set<string>();
15
+ const visiting = new Set<string>();
16
+ const map = new Map<string, CollectionOptions>();
17
+
18
+ // Create a map for O(1) lookup
19
+ collections.forEach((col) => {
20
+ map.set(col.name, col);
21
+ });
22
+
23
+ const addToSorted = (col: CollectionOptions): void => {
24
+ // Check for circular dependency
25
+ if (visiting.has(col.name)) {
26
+ throw new Error(`Circular dependency detected: ${col.name} inherits from itself through a chain`);
27
+ }
28
+
29
+ // Skip if already processed
30
+ if (visited.has(col.name)) {
31
+ return;
32
+ }
33
+
34
+ // Mark as currently being processed
35
+ visiting.add(col.name);
36
+
37
+ // Process inherits first (dependencies)
38
+ const inherits = col.inherits || [];
39
+ for (const inheritName of inherits) {
40
+ const inheritCol = map.get(inheritName);
41
+ if (!inheritCol) {
42
+ console.warn(`Warning: Collection ${inheritName}, inherited by ${col.name}, not found.`);
43
+ continue;
44
+ }
45
+ addToSorted(inheritCol);
46
+ // Silently skip missing inherit collections
47
+ }
48
+
49
+ // Mark as processed and add to sorted array
50
+ visiting.delete(col.name);
51
+ visited.add(col.name);
52
+ sorted.push(col);
53
+ };
54
+
55
+ // Process all collections
56
+ for (const col of collections) {
57
+ addToSorted(col);
58
+ }
59
+
60
+ return sorted;
61
+ }