@nocobase/flow-engine 2.1.19 → 2.1.21

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/lib/flowEngine.js CHANGED
@@ -1141,6 +1141,9 @@ const _FlowEngine = class _FlowEngine {
1141
1141
  if (!this.ensureModelRepository()) return;
1142
1142
  const refresh = !!(options == null ? void 0 : options.refresh);
1143
1143
  const bypassLoadedPageCache = this._loadedPageCache.shouldBypass(options, () => this.context.flowSettingsEnabled);
1144
+ if (this.context.flowSettingsEnabled) {
1145
+ this._loadedPageCache.markDirtyForOptions(options);
1146
+ }
1144
1147
  if (!refresh && !bypassLoadedPageCache) {
1145
1148
  const model2 = this.findModelByParentId(options.parentId, options.subKey);
1146
1149
  if (model2) {
@@ -1201,6 +1204,9 @@ const _FlowEngine = class _FlowEngine {
1201
1204
  if (!this.ensureModelRepository()) return;
1202
1205
  const { uid, parentId, subKey } = options;
1203
1206
  const bypassLoadedPageCache = this._loadedPageCache.shouldBypass(options, () => this.context.flowSettingsEnabled);
1207
+ if (this.context.flowSettingsEnabled) {
1208
+ this._loadedPageCache.markDirtyForOptions(options);
1209
+ }
1204
1210
  if (uid && !bypassLoadedPageCache && this._modelInstances.has(uid)) {
1205
1211
  return this._modelInstances.get(uid);
1206
1212
  }
@@ -17,6 +17,7 @@ type DirtyKeyOptions = {
17
17
  export declare const createLoadedPageCache: () => {
18
18
  getDirtyKeyForModel(model?: FlowModel | null, options?: DirtyKeyOptions): string | undefined;
19
19
  markDirty(key?: string): void;
20
+ markDirtyForOptions(options?: LoadedPageOptions): void;
20
21
  shouldBypass(options?: LoadedPageOptions, isFlowSettingsEnabled?: () => boolean): boolean;
21
22
  clear(options?: LoadedPageOptions): void;
22
23
  mountModelToParent: <T extends FlowModel<import("..").DefaultStructure> = FlowModel<import("..").DefaultStructure>>(model: T, forceReplace?: boolean) => T;
@@ -113,6 +113,12 @@ const createLoadedPageCache = /* @__PURE__ */ __name(() => {
113
113
  dirtyKeys.add(key);
114
114
  }
115
115
  },
116
+ markDirtyForOptions(options) {
117
+ const key = getLoadedPageKey(options);
118
+ if (key) {
119
+ dirtyKeys.add(key);
120
+ }
121
+ },
116
122
  shouldBypass(options, isFlowSettingsEnabled) {
117
123
  const key = getLoadedPageKey(options);
118
124
  if (!key || !dirtyKeys.has(key)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/flow-engine",
3
- "version": "2.1.19",
3
+ "version": "2.1.21",
4
4
  "private": false,
5
5
  "description": "A standalone flow engine for NocoBase, managing workflows, models, and actions.",
6
6
  "main": "lib/index.js",
@@ -8,8 +8,8 @@
8
8
  "dependencies": {
9
9
  "@formily/antd-v5": "1.x",
10
10
  "@formily/reactive": "2.x",
11
- "@nocobase/sdk": "2.1.19",
12
- "@nocobase/shared": "2.1.19",
11
+ "@nocobase/sdk": "2.1.21",
12
+ "@nocobase/shared": "2.1.21",
13
13
  "ahooks": "^3.7.2",
14
14
  "axios": "^1.7.0",
15
15
  "dayjs": "^1.11.9",
@@ -37,5 +37,5 @@
37
37
  ],
38
38
  "author": "NocoBase Team",
39
39
  "license": "Apache-2.0",
40
- "gitHead": "c316683666cfb478cb355b971c8f067a4f925fcb"
40
+ "gitHead": "491141417d8338022651c9e99afbd2d84c1e2b0b"
41
41
  }
@@ -340,9 +340,9 @@ describe('ViewScopedFlowEngine', () => {
340
340
  const repository = new DirtyPageRepository();
341
341
  root.setModelRepository(repository);
342
342
 
343
- class ParentModel extends FlowModel {}
344
- class PageModel extends FlowModel {}
345
343
  class BlockModel extends FlowModel {}
344
+ class PageModel extends FlowModel<{ parent?: FlowModel; subModels: { items: BlockModel[] } }> {}
345
+ class ParentModel extends FlowModel<{ parent?: FlowModel; subModels: { page?: PageModel } }> {}
346
346
  root.registerModels({ ParentModel, PageModel, BlockModel });
347
347
 
348
348
  const parent = root.createModel<ParentModel>({ use: 'ParentModel', uid: 'popup-action' });
@@ -357,7 +357,10 @@ describe('ViewScopedFlowEngine', () => {
357
357
  items: [{ use: 'BlockModel', uid: 'stale-block' }],
358
358
  },
359
359
  });
360
- const staleBlock = stalePage.findSubModel('items' as any, (item) => item.uid === 'stale-block') as FlowModel;
360
+ const staleBlock = stalePage.findSubModel('items', (item) => item.uid === 'stale-block');
361
+ if (!staleBlock) {
362
+ throw new Error('Expected stale block to be loaded');
363
+ }
361
364
  parent.setSubModel('page', stalePage);
362
365
  oldScoped.unlinkFromStack();
363
366
 
@@ -372,7 +375,7 @@ describe('ViewScopedFlowEngine', () => {
372
375
  },
373
376
  };
374
377
 
375
- root.flowSettings.enable();
378
+ await root.flowSettings.enable();
376
379
  await staleBlock.saveStepParams();
377
380
  root.flowSettings.disable();
378
381
  repository.findOneCalls = 0;
@@ -388,8 +391,8 @@ describe('ViewScopedFlowEngine', () => {
388
391
 
389
392
  expect(repository.findOneCalls).toBe(1);
390
393
  expect(loaded).not.toBe(stalePage);
391
- expect((parent.subModels as any).page).toBe(loaded);
392
- expect(loaded?.mapSubModels('items' as any, (item) => item.uid)).toEqual(['fresh-block']);
394
+ expect(parent.subModels.page).toBe(loaded);
395
+ expect(loaded?.mapSubModels('items', (item) => item.uid)).toEqual(['fresh-block']);
393
396
 
394
397
  repository.findOneCalls = 0;
395
398
  const nextRuntimeScoped = createViewScopedEngine(root);
@@ -405,6 +408,69 @@ describe('ViewScopedFlowEngine', () => {
405
408
  expect(loadedAgain?.uid).toBe('popup-page');
406
409
  });
407
410
 
411
+ it('reloads a page after it was loaded in flow settings mode', async () => {
412
+ const root = new FlowEngine();
413
+ const repository = new DirtyPageRepository();
414
+ root.setModelRepository(repository);
415
+
416
+ class ParentModel extends FlowModel {}
417
+ class PageModel extends FlowModel {}
418
+ class BlockModel extends FlowModel {}
419
+ root.registerModels({ ParentModel, PageModel, BlockModel });
420
+
421
+ const parent = root.createModel<ParentModel>({ use: 'ParentModel', uid: 'settings-popup-action' });
422
+ repository.data = {
423
+ use: 'PageModel',
424
+ uid: 'settings-popup-page',
425
+ parentId: parent.uid,
426
+ subKey: 'page',
427
+ subType: 'object',
428
+ subModels: {
429
+ items: [{ use: 'BlockModel', uid: 'stale-settings-block' }],
430
+ },
431
+ };
432
+
433
+ await root.flowSettings.enable();
434
+ const designScoped = createViewScopedEngine(root);
435
+ const designLoaded = await designScoped.loadOrCreateModel<PageModel>({
436
+ async: true,
437
+ parentId: parent.uid,
438
+ subKey: 'page',
439
+ subType: 'object',
440
+ use: 'PageModel',
441
+ });
442
+ expect(repository.findOneCalls).toBe(1);
443
+ expect(designLoaded?.mapSubModels('items', (item) => item.uid)).toEqual(['stale-settings-block']);
444
+ designScoped.unlinkFromStack();
445
+
446
+ repository.data = {
447
+ use: 'PageModel',
448
+ uid: 'settings-popup-page',
449
+ parentId: parent.uid,
450
+ subKey: 'page',
451
+ subType: 'object',
452
+ subModels: {
453
+ items: [{ use: 'BlockModel', uid: 'fresh-settings-block' }],
454
+ },
455
+ };
456
+ root.flowSettings.disable();
457
+ repository.findOneCalls = 0;
458
+
459
+ const runtimeScoped = createViewScopedEngine(root);
460
+ const runtimeLoaded = await runtimeScoped.loadOrCreateModel<PageModel>({
461
+ async: true,
462
+ parentId: parent.uid,
463
+ subKey: 'page',
464
+ subType: 'object',
465
+ use: 'PageModel',
466
+ });
467
+
468
+ expect(repository.findOneCalls).toBe(1);
469
+ expect(runtimeLoaded).not.toBe(designLoaded);
470
+ expect(parent.subModels.page).toBe(runtimeLoaded);
471
+ expect(runtimeLoaded?.mapSubModels('items', (item) => item.uid)).toEqual(['fresh-settings-block']);
472
+ });
473
+
408
474
  it('does not bypass loaded page cache after a non-config save', async () => {
409
475
  const root = new FlowEngine();
410
476
  const repository = new DirtyPageRepository();
package/src/flowEngine.ts CHANGED
@@ -1343,6 +1343,9 @@ export class FlowEngine {
1343
1343
  if (!this.ensureModelRepository()) return;
1344
1344
  const refresh = !!options?.refresh;
1345
1345
  const bypassLoadedPageCache = this._loadedPageCache.shouldBypass(options, () => this.context.flowSettingsEnabled);
1346
+ if (this.context.flowSettingsEnabled) {
1347
+ this._loadedPageCache.markDirtyForOptions(options);
1348
+ }
1346
1349
  if (!refresh && !bypassLoadedPageCache) {
1347
1350
  const model = this.findModelByParentId(options.parentId, options.subKey);
1348
1351
  if (model) {
@@ -1412,6 +1415,9 @@ export class FlowEngine {
1412
1415
  if (!this.ensureModelRepository()) return;
1413
1416
  const { uid, parentId, subKey } = options;
1414
1417
  const bypassLoadedPageCache = this._loadedPageCache.shouldBypass(options, () => this.context.flowSettingsEnabled);
1418
+ if (this.context.flowSettingsEnabled) {
1419
+ this._loadedPageCache.markDirtyForOptions(options);
1420
+ }
1415
1421
  if (uid && !bypassLoadedPageCache && this._modelInstances.has(uid)) {
1416
1422
  return this._modelInstances.get(uid) as T;
1417
1423
  }
@@ -123,6 +123,13 @@ export const createLoadedPageCache = () => {
123
123
  }
124
124
  },
125
125
 
126
+ markDirtyForOptions(options?: LoadedPageOptions): void {
127
+ const key = getLoadedPageKey(options);
128
+ if (key) {
129
+ dirtyKeys.add(key);
130
+ }
131
+ },
132
+
126
133
  shouldBypass(options?: LoadedPageOptions, isFlowSettingsEnabled?: () => boolean): boolean {
127
134
  const key = getLoadedPageKey(options);
128
135
  if (!key || !dirtyKeys.has(key)) {