@nocobase/flow-engine 2.0.22 → 2.1.0-alpha.10

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.
@@ -41,11 +41,12 @@ __export(MobilePopup_exports, {
41
41
  });
42
42
  module.exports = __toCommonJS(MobilePopup_exports);
43
43
  var import_antd = require("antd");
44
- var import_antd_mobile = require("antd-mobile");
45
44
  var import_react = __toESM(require("react"));
46
- var import_antd_mobile_icons = require("antd-mobile-icons");
47
45
  var import_MobilePopup = require("./MobilePopup.style");
48
46
  var import_react_i18next = require("react-i18next");
47
+ var import_lazy_helper = require("../lazy-helper");
48
+ const { Popup } = (0, import_lazy_helper.lazy)(() => import("antd-mobile"), "Popup");
49
+ const { CloseOutline } = (0, import_lazy_helper.lazy)(() => import("antd-mobile-icons"), "CloseOutline");
49
50
  const MobilePopup = /* @__PURE__ */ __name((props) => {
50
51
  const { title, visible, onClose: closePopup, children, minHeight, className, footer } = props;
51
52
  const { t } = (0, import_react_i18next.useTranslation)();
@@ -67,7 +68,7 @@ const MobilePopup = /* @__PURE__ */ __name((props) => {
67
68
  };
68
69
  }, []);
69
70
  return /* @__PURE__ */ import_react.default.createElement(import_antd.ConfigProvider, { theme }, /* @__PURE__ */ import_react.default.createElement(
70
- import_antd_mobile.Popup,
71
+ Popup,
71
72
  {
72
73
  className: `${componentCls} ${hashId} ${className || ""}`,
73
74
  visible,
@@ -81,7 +82,7 @@ const MobilePopup = /* @__PURE__ */ __name((props) => {
81
82
  style,
82
83
  destroyOnClose: true
83
84
  },
84
- /* @__PURE__ */ import_react.default.createElement("div", { className: "nb-mobile-action-drawer-header" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "nb-mobile-action-drawer-placeholder" }, /* @__PURE__ */ import_react.default.createElement(import_antd_mobile_icons.CloseOutline, null)), /* @__PURE__ */ import_react.default.createElement("span", null, title), /* @__PURE__ */ import_react.default.createElement(
85
+ /* @__PURE__ */ import_react.default.createElement("div", { className: "nb-mobile-action-drawer-header" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "nb-mobile-action-drawer-placeholder" }, /* @__PURE__ */ import_react.default.createElement(CloseOutline, null)), /* @__PURE__ */ import_react.default.createElement("span", null, title), /* @__PURE__ */ import_react.default.createElement(
85
86
  "span",
86
87
  {
87
88
  className: "nb-mobile-action-drawer-close-icon",
@@ -90,7 +91,7 @@ const MobilePopup = /* @__PURE__ */ __name((props) => {
90
91
  tabIndex: 0,
91
92
  "aria-label": t("Close")
92
93
  },
93
- /* @__PURE__ */ import_react.default.createElement(import_antd_mobile_icons.CloseOutline, null)
94
+ /* @__PURE__ */ import_react.default.createElement(CloseOutline, null)
94
95
  )),
95
96
  children,
96
97
  footer && /* @__PURE__ */ import_react.default.createElement("div", { className: "nb-mobile-action-drawer-footer" }, footer)
@@ -430,7 +430,7 @@ const AddSubModelButtonCore = /* @__PURE__ */ __name(function AddSubModelButton(
430
430
  }
431
431
  let addedModel;
432
432
  try {
433
- addedModel = model.flowEngine.createModel({
433
+ addedModel = await model.flowEngine.createModelAsync({
434
434
  ...import_lodash.default.cloneDeep(createOpts),
435
435
  parentId: model.uid,
436
436
  subKey: subModelKey,
@@ -44,7 +44,7 @@ __export(utils_exports, {
44
44
  buildWrapperFieldChildren: () => buildWrapperFieldChildren
45
45
  });
46
46
  module.exports = __toCommonJS(utils_exports);
47
- var _ = __toESM(require("lodash"));
47
+ var import_lodash = __toESM(require("lodash"));
48
48
  var import_utils = require("../../utils");
49
49
  async function callHideFunction(hide, ctx) {
50
50
  if (typeof hide === "function") {
@@ -107,7 +107,7 @@ function buildSubModelChildren(M, ctx) {
107
107
  const extraArg = args && args.length > 0 ? args[args.length - 1] : void 0;
108
108
  const defaultOpts = await (0, import_utils.resolveCreateModelOptions)(meta == null ? void 0 : meta.createModelOptions, ctx, extraArg);
109
109
  const childOpts = await (0, import_utils.resolveCreateModelOptions)(src, ctx, extraArg);
110
- return _.merge({}, _.cloneDeep(defaultOpts), childOpts);
110
+ return import_lodash.default.merge({}, import_lodash.default.cloneDeep(defaultOpts), childOpts);
111
111
  };
112
112
  }
113
113
  return node;
@@ -8,7 +8,7 @@ import { FlowResource } from './resources';
8
8
  import { Emitter } from './emitter';
9
9
  import ModelOperationScheduler from './scheduler/ModelOperationScheduler';
10
10
  import type { ScheduleOptions, ScheduledCancel } from './scheduler/ModelOperationScheduler';
11
- import type { ActionDefinition, ApplyFlowCacheEntry, CreateModelOptions, EventDefinition, FlowModelOptions, IFlowModelRepository, ModelConstructor, PersistOptions, ResourceType } from './types';
11
+ import type { ActionDefinition, ApplyFlowCacheEntry, CreateModelOptions, EnsureBatchResult, EventDefinition, FlowModelLoaderMap, FlowModelOptions, IFlowModelRepository, ModelConstructor, PersistOptions, ResourceType } from './types';
12
12
  /**
13
13
  * FlowEngine is the core class of the flow engine, responsible for managing flow models, actions, model repository, and more.
14
14
  * It provides capabilities for registering, creating, finding, persisting, replacing, and moving models.
@@ -47,6 +47,28 @@ export declare class FlowEngine {
47
47
  * @private
48
48
  */
49
49
  private _modelClasses;
50
+ /**
51
+ * Registered model entries.
52
+ * Key is the model class name, value is the model loader entry.
53
+ * @private
54
+ */
55
+ private _modelLoaders;
56
+ /**
57
+ * In-flight model loading promises.
58
+ * Key is the model class name, value is the loading promise.
59
+ * @private
60
+ */
61
+ private _loadingModelPromises;
62
+ /**
63
+ * Whether model-loader preload has completed in this session.
64
+ * @private
65
+ */
66
+ private _modelLoadersPreloaded;
67
+ /**
68
+ * In-flight model-loader preload promise.
69
+ * @private
70
+ */
71
+ private _modelLoadersPreloadPromise?;
50
72
  /**
51
73
  * Created model instances.
52
74
  * Key is the model instance UID, value is the model instance object.
@@ -226,6 +248,10 @@ export declare class FlowEngine {
226
248
  * Get all registered global events.
227
249
  */
228
250
  getEvents<TModel extends FlowModel = FlowModel>(): Map<string, EventDefinition<TModel>>;
251
+ /**
252
+ * for proxy instance, the #registerModel can't be called.
253
+ */
254
+ private _registerModel;
229
255
  /**
230
256
  * Register multiple model classes.
231
257
  * @param {Record<string, ModelConstructor>} models Model class map, key is model name, value is model constructor
@@ -234,6 +260,99 @@ export declare class FlowEngine {
234
260
  * flowEngine.registerModels({ UserModel, OrderModel });
235
261
  */
236
262
  registerModels(models: Record<string, ModelConstructor | typeof FlowModel<any>>): void;
263
+ /**
264
+ * Register multiple model loader entries.
265
+ * @param {FlowModelLoaderMap} loaders Model loader entry map, key is model name, value is the model loader entry
266
+ * @returns {void}
267
+ * @example
268
+ * flowEngine.registerModelLoaders({
269
+ * DemoModel: {
270
+ * loader: () => import('./models/DemoModel'),
271
+ * },
272
+ * });
273
+ */
274
+ registerModelLoaders(loaders: FlowModelLoaderMap): void;
275
+ /**
276
+ * Get a registered model class (constructor) asynchronously.
277
+ * This will first ensure the model loader entry is resolved.
278
+ * @param {string} name Model class name
279
+ * @returns {Promise<ModelConstructor | undefined>} Model constructor, or undefined if not found
280
+ */
281
+ getModelClassAsync(name: string): Promise<ModelConstructor | undefined>;
282
+ /**
283
+ * Get all registered model classes asynchronously.
284
+ * This will first ensure all registered model loader entries are resolved.
285
+ * @returns {Promise<Map<string, ModelConstructor>>} Model class map
286
+ */
287
+ getModelClassesAsync(): Promise<Map<string, ModelConstructor>>;
288
+ /**
289
+ * Create and register a model instance asynchronously.
290
+ * This will first ensure all string-based model references in the model tree are resolved.
291
+ * @template T FlowModel subclass type, defaults to FlowModel.
292
+ * @param {CreateModelOptions} options Model creation options
293
+ * @returns {Promise<T>} Created model instance
294
+ */
295
+ createModelAsync<T extends FlowModel = FlowModel>(options: CreateModelOptions, extra?: {
296
+ delegateToParent?: boolean;
297
+ delegate?: FlowContext;
298
+ }): Promise<T>;
299
+ /**
300
+ * Normalize a loader result into a model constructor.
301
+ * @param {string} name Model class name
302
+ * @param {FlowModelLoaderResult} loaded Loader result
303
+ * @returns {ModelConstructor | null} Normalized model constructor
304
+ * @private
305
+ */
306
+ private normalizeModelLoaderResult;
307
+ /**
308
+ * Collect string-based model names from a model tree.
309
+ * @param {unknown} data Model tree data
310
+ * @param {Set<string>} names Model name set
311
+ * @private
312
+ */
313
+ private collectModelNamesFromTree;
314
+ /**
315
+ * Collect additional model names from object-form meta.createModelOptions defaults.
316
+ * @param {ModelConstructor} modelClass Model class constructor
317
+ * @param {Set<string>} names Model name set
318
+ * @private
319
+ */
320
+ private collectModelNamesFromMetaDefaults;
321
+ /**
322
+ * Ensure a single model class is available.
323
+ * @param {string} name Model class name
324
+ * @returns {Promise<ModelConstructor | null>} Model constructor or null when resolution fails
325
+ * @private
326
+ */
327
+ private ensureModel;
328
+ /**
329
+ * Ensure multiple model classes are available.
330
+ * @param {string[]} names Model class names
331
+ * @returns {Promise<EnsureBatchResult>} Batch ensure result
332
+ * @private
333
+ */
334
+ private ensureModels;
335
+ /**
336
+ * Resolve all unresolved string-based model references in a model tree before synchronous creation begins.
337
+ *
338
+ * Use this when you already have a model tree object, such as repository-returned data or resolved
339
+ * `createModelOptions`, and you need to ensure every string `use` in that tree has been loaded and
340
+ * registered into `_modelClasses` before calling `createModel()`.
341
+ *
342
+ * @param {unknown} data Model tree data
343
+ * @returns {Promise<EnsureBatchResult>} Batch ensure result
344
+ */
345
+ resolveModelTree(data: unknown): Promise<EnsureBatchResult>;
346
+ /**
347
+ * Preload all currently registered unresolved model loaders.
348
+ *
349
+ * This method is intended for flow-settings/discovery style entry points that need registered model
350
+ * classes to exist before UI is rendered, without requiring callers to know which specific models
351
+ * will be touched next.
352
+ *
353
+ * @returns {Promise<EnsureBatchResult>} Batch ensure result
354
+ */
355
+ preloadModelLoaders(): Promise<EnsureBatchResult>;
237
356
  registerResources(resources: Record<string, any>): void;
238
357
  createResource<T = FlowResource>(resourceType: ResourceType<T>, options?: {
239
358
  context?: FlowContext;
package/lib/flowEngine.js CHANGED
@@ -83,6 +83,28 @@ const _FlowEngine = class _FlowEngine {
83
83
  * @private
84
84
  */
85
85
  __publicField(this, "_modelClasses", import_reactive.observable.shallow(/* @__PURE__ */ new Map()));
86
+ /**
87
+ * Registered model entries.
88
+ * Key is the model class name, value is the model loader entry.
89
+ * @private
90
+ */
91
+ __publicField(this, "_modelLoaders", /* @__PURE__ */ new Map());
92
+ /**
93
+ * In-flight model loading promises.
94
+ * Key is the model class name, value is the loading promise.
95
+ * @private
96
+ */
97
+ __publicField(this, "_loadingModelPromises", /* @__PURE__ */ new Map());
98
+ /**
99
+ * Whether model-loader preload has completed in this session.
100
+ * @private
101
+ */
102
+ __publicField(this, "_modelLoadersPreloaded", false);
103
+ /**
104
+ * In-flight model-loader preload promise.
105
+ * @private
106
+ */
107
+ __publicField(this, "_modelLoadersPreloadPromise");
86
108
  /**
87
109
  * Created model instances.
88
110
  * Key is the model instance UID, value is the model instance object.
@@ -372,6 +394,16 @@ const _FlowEngine = class _FlowEngine {
372
394
  getEvents() {
373
395
  return this._eventRegistry.getEvents();
374
396
  }
397
+ /**
398
+ * for proxy instance, the #registerModel can't be called.
399
+ */
400
+ _registerModel(name, modelClass) {
401
+ if (this._modelClasses.has(name)) {
402
+ console.warn(`FlowEngine: Model class with name '${name}' is already registered and will be overwritten.`);
403
+ }
404
+ Object.defineProperty(modelClass, "name", { value: name });
405
+ this._modelClasses.set(name, modelClass);
406
+ }
375
407
  /**
376
408
  * Register multiple model classes.
377
409
  * @param {Record<string, ModelConstructor>} models Model class map, key is model name, value is model constructor
@@ -384,6 +416,264 @@ const _FlowEngine = class _FlowEngine {
384
416
  __privateMethod(this, _FlowEngine_instances, registerModel_fn).call(this, name, modelClass);
385
417
  }
386
418
  }
419
+ /**
420
+ * Register multiple model loader entries.
421
+ * @param {FlowModelLoaderMap} loaders Model loader entry map, key is model name, value is the model loader entry
422
+ * @returns {void}
423
+ * @example
424
+ * flowEngine.registerModelLoaders({
425
+ * DemoModel: {
426
+ * loader: () => import('./models/DemoModel'),
427
+ * },
428
+ * });
429
+ */
430
+ registerModelLoaders(loaders) {
431
+ let changed = false;
432
+ for (const [name, entry] of Object.entries(loaders)) {
433
+ if (this._modelLoaders.has(name)) {
434
+ console.warn(`FlowEngine: Model loader with name '${name}' is already registered and will be overwritten.`);
435
+ }
436
+ this._modelLoaders.set(name, entry);
437
+ changed = true;
438
+ }
439
+ if (changed) {
440
+ this._modelLoadersPreloaded = false;
441
+ this._modelLoadersPreloadPromise = void 0;
442
+ }
443
+ }
444
+ /**
445
+ * Get a registered model class (constructor) asynchronously.
446
+ * This will first ensure the model loader entry is resolved.
447
+ * @param {string} name Model class name
448
+ * @returns {Promise<ModelConstructor | undefined>} Model constructor, or undefined if not found
449
+ */
450
+ async getModelClassAsync(name) {
451
+ await this.ensureModel(name);
452
+ return this.getModelClass(name);
453
+ }
454
+ /**
455
+ * Get all registered model classes asynchronously.
456
+ * This will first ensure all registered model loader entries are resolved.
457
+ * @returns {Promise<Map<string, ModelConstructor>>} Model class map
458
+ */
459
+ async getModelClassesAsync() {
460
+ await this.ensureModels(Array.from(this._modelLoaders.keys()));
461
+ return this.getModelClasses();
462
+ }
463
+ /**
464
+ * Create and register a model instance asynchronously.
465
+ * This will first ensure all string-based model references in the model tree are resolved.
466
+ * @template T FlowModel subclass type, defaults to FlowModel.
467
+ * @param {CreateModelOptions} options Model creation options
468
+ * @returns {Promise<T>} Created model instance
469
+ */
470
+ async createModelAsync(options, extra) {
471
+ await this.resolveModelTree(options);
472
+ return this.createModel(options, extra);
473
+ }
474
+ /**
475
+ * Normalize a loader result into a model constructor.
476
+ * @param {string} name Model class name
477
+ * @param {FlowModelLoaderResult} loaded Loader result
478
+ * @returns {ModelConstructor | null} Normalized model constructor
479
+ * @private
480
+ */
481
+ normalizeModelLoaderResult(name, loaded) {
482
+ if (typeof loaded === "function") {
483
+ return loaded;
484
+ }
485
+ if (loaded && typeof loaded === "object") {
486
+ const defaultExport = loaded.default;
487
+ if (typeof defaultExport === "function") {
488
+ return defaultExport;
489
+ }
490
+ const namedExport = loaded[name];
491
+ if (typeof namedExport === "function") {
492
+ return namedExport;
493
+ }
494
+ }
495
+ console.warn(`FlowEngine: model loader for '${name}' did not resolve to a valid model constructor.`);
496
+ return null;
497
+ }
498
+ /**
499
+ * Collect string-based model names from a model tree.
500
+ * @param {unknown} data Model tree data
501
+ * @param {Set<string>} names Model name set
502
+ * @private
503
+ */
504
+ collectModelNamesFromTree(data, names) {
505
+ if (!data || typeof data !== "object") {
506
+ return;
507
+ }
508
+ if (Array.isArray(data)) {
509
+ data.forEach((item) => this.collectModelNamesFromTree(item, names));
510
+ return;
511
+ }
512
+ const tree = data;
513
+ if (typeof tree.use === "string") {
514
+ names.add(tree.use);
515
+ }
516
+ const subModels = tree.subModels;
517
+ if (!subModels || typeof subModels !== "object") {
518
+ return;
519
+ }
520
+ Object.values(subModels).forEach((value) => {
521
+ this.collectModelNamesFromTree(value, names);
522
+ });
523
+ }
524
+ /**
525
+ * Collect additional model names from object-form meta.createModelOptions defaults.
526
+ * @param {ModelConstructor} modelClass Model class constructor
527
+ * @param {Set<string>} names Model name set
528
+ * @private
529
+ */
530
+ collectModelNamesFromMetaDefaults(modelClass, names) {
531
+ var _a;
532
+ const metaCreate = (_a = modelClass.meta) == null ? void 0 : _a.createModelOptions;
533
+ if (metaCreate && typeof metaCreate === "object") {
534
+ this.collectModelNamesFromTree(metaCreate, names);
535
+ }
536
+ }
537
+ /**
538
+ * Ensure a single model class is available.
539
+ * @param {string} name Model class name
540
+ * @returns {Promise<ModelConstructor | null>} Model constructor or null when resolution fails
541
+ * @private
542
+ */
543
+ async ensureModel(name) {
544
+ const existing = this._modelClasses.get(name);
545
+ if (existing) {
546
+ return existing;
547
+ }
548
+ const inflight = this._loadingModelPromises.get(name);
549
+ if (inflight) {
550
+ return inflight;
551
+ }
552
+ const entry = this._modelLoaders.get(name);
553
+ if (!entry) {
554
+ console.warn(`FlowEngine: Model entry '${name}' not found. Falling back to ErrorFlowModel when needed.`);
555
+ return null;
556
+ }
557
+ const promise = (async () => {
558
+ try {
559
+ const loaded = await entry.loader();
560
+ const modelClass = this.normalizeModelLoaderResult(name, loaded);
561
+ if (!modelClass) {
562
+ return null;
563
+ }
564
+ this._registerModel(name, modelClass);
565
+ return modelClass;
566
+ } catch (error) {
567
+ console.warn(`FlowEngine: Failed to load model '${name}'. Falling back to ErrorFlowModel when needed.`, error);
568
+ return null;
569
+ } finally {
570
+ this._loadingModelPromises.delete(name);
571
+ }
572
+ })();
573
+ this._loadingModelPromises.set(name, promise);
574
+ return promise;
575
+ }
576
+ /**
577
+ * Ensure multiple model classes are available.
578
+ * @param {string[]} names Model class names
579
+ * @returns {Promise<EnsureBatchResult>} Batch ensure result
580
+ * @private
581
+ */
582
+ async ensureModels(names) {
583
+ const requested = Array.from(new Set(names.filter((name) => !!name)));
584
+ const loaded = [];
585
+ const failed = [];
586
+ const results = await Promise.all(
587
+ requested.map(async (name) => {
588
+ const modelClass = await this.ensureModel(name);
589
+ return { name, modelClass };
590
+ })
591
+ );
592
+ results.forEach(({ name, modelClass }) => {
593
+ if (modelClass) {
594
+ loaded.push(name);
595
+ } else {
596
+ failed.push({ name });
597
+ }
598
+ });
599
+ return { requested, loaded, failed };
600
+ }
601
+ /**
602
+ * Resolve all unresolved string-based model references in a model tree before synchronous creation begins.
603
+ *
604
+ * Use this when you already have a model tree object, such as repository-returned data or resolved
605
+ * `createModelOptions`, and you need to ensure every string `use` in that tree has been loaded and
606
+ * registered into `_modelClasses` before calling `createModel()`.
607
+ *
608
+ * @param {unknown} data Model tree data
609
+ * @returns {Promise<EnsureBatchResult>} Batch ensure result
610
+ */
611
+ async resolveModelTree(data) {
612
+ const requested = /* @__PURE__ */ new Set();
613
+ const loaded = /* @__PURE__ */ new Set();
614
+ const failed = /* @__PURE__ */ new Map();
615
+ const processed = /* @__PURE__ */ new Set();
616
+ const pending = /* @__PURE__ */ new Set();
617
+ this.collectModelNamesFromTree(data, pending);
618
+ while (pending.size > 0) {
619
+ const batch = Array.from(pending).filter((name) => !processed.has(name));
620
+ pending.clear();
621
+ if (batch.length === 0) {
622
+ break;
623
+ }
624
+ batch.forEach((name) => requested.add(name));
625
+ const result = await this.ensureModels(batch);
626
+ result.loaded.forEach((name) => {
627
+ processed.add(name);
628
+ loaded.add(name);
629
+ const modelClass = this.getModelClass(name);
630
+ if (modelClass) {
631
+ const discovered = /* @__PURE__ */ new Set();
632
+ this.collectModelNamesFromMetaDefaults(modelClass, discovered);
633
+ discovered.forEach((discoveredName) => {
634
+ if (!processed.has(discoveredName)) {
635
+ pending.add(discoveredName);
636
+ }
637
+ });
638
+ }
639
+ });
640
+ result.failed.forEach((item) => {
641
+ processed.add(item.name);
642
+ failed.set(item.name, item);
643
+ });
644
+ }
645
+ return {
646
+ requested: Array.from(requested),
647
+ loaded: Array.from(loaded),
648
+ failed: Array.from(failed.values())
649
+ };
650
+ }
651
+ /**
652
+ * Preload all currently registered unresolved model loaders.
653
+ *
654
+ * This method is intended for flow-settings/discovery style entry points that need registered model
655
+ * classes to exist before UI is rendered, without requiring callers to know which specific models
656
+ * will be touched next.
657
+ *
658
+ * @returns {Promise<EnsureBatchResult>} Batch ensure result
659
+ */
660
+ async preloadModelLoaders() {
661
+ const unresolved = Array.from(this._modelLoaders.keys()).filter((name) => !this._modelClasses.has(name));
662
+ if (unresolved.length === 0) {
663
+ this._modelLoadersPreloaded = true;
664
+ return { requested: [], loaded: [], failed: [] };
665
+ }
666
+ if (this._modelLoadersPreloadPromise) {
667
+ return this._modelLoadersPreloadPromise;
668
+ }
669
+ this._modelLoadersPreloadPromise = (async () => {
670
+ const result = await this.ensureModels(unresolved);
671
+ this._modelLoadersPreloaded = result.failed.length === 0;
672
+ this._modelLoadersPreloadPromise = void 0;
673
+ return result;
674
+ })();
675
+ return this._modelLoadersPreloadPromise;
676
+ }
387
677
  registerResources(resources) {
388
678
  for (const [name, resourceClass] of Object.entries(resources)) {
389
679
  this._resources.set(name, resourceClass);
@@ -732,7 +1022,7 @@ const _FlowEngine = class _FlowEngine {
732
1022
  * Hydrate a model into current engine from an already-existing model instance in previous engines.
733
1023
  * - Avoids repository requests when the model tree is already present in memory.
734
1024
  */
735
- hydrateModelFromPreviousEngines(options, extra) {
1025
+ async hydrateModelFromPreviousEngines(options, extra) {
736
1026
  var _a;
737
1027
  const uid = options == null ? void 0 : options.uid;
738
1028
  const parentId = options == null ? void 0 : options.parentId;
@@ -744,7 +1034,7 @@ const _FlowEngine = class _FlowEngine {
744
1034
  }
745
1035
  if (existing) {
746
1036
  const data = existing.serialize();
747
- return this.createModel(data, extra);
1037
+ return this.createModelAsync(data, extra);
748
1038
  }
749
1039
  }
750
1040
  if (parentId && subKey) {
@@ -755,10 +1045,10 @@ const _FlowEngine = class _FlowEngine {
755
1045
  if (!localParent) {
756
1046
  const parentData = parentFromPrev.serialize();
757
1047
  delete parentData.subModels;
758
- localParent = this.createModel(parentData, extra);
1048
+ localParent = await this.createModelAsync(parentData, extra);
759
1049
  }
760
1050
  const modelData = modelFromPrev.serialize();
761
- const localModel = this.createModel(modelData, extra);
1051
+ const localModel = await this.createModelAsync(modelData, extra);
762
1052
  const mounted = (_a = localParent.subModels) == null ? void 0 : _a[subKey];
763
1053
  if (Array.isArray(mounted)) {
764
1054
  const exists = mounted.some((m) => (m == null ? void 0 : m.uid) === (localModel == null ? void 0 : localModel.uid));
@@ -794,20 +1084,21 @@ const _FlowEngine = class _FlowEngine {
794
1084
  if (model) {
795
1085
  return model;
796
1086
  }
797
- const hydrated = this.hydrateModelFromPreviousEngines(options);
1087
+ const hydrated = await this.hydrateModelFromPreviousEngines(options);
798
1088
  if (hydrated) {
799
1089
  return hydrated;
800
1090
  }
801
1091
  }
802
1092
  const data = await this._modelRepository.findOne(options);
803
1093
  if (!(data == null ? void 0 : data.uid)) return null;
1094
+ await this.resolveModelTree(data);
804
1095
  if (refresh) {
805
1096
  const existing = this.getModel(data.uid);
806
1097
  if (existing) {
807
1098
  this.removeModelWithSubModels(existing.uid);
808
1099
  }
809
1100
  }
810
- return this.createModel(data);
1101
+ return this.createModelAsync(data);
811
1102
  }
812
1103
  /**
813
1104
  * Find a sub-model by parent model ID and subKey.
@@ -845,16 +1136,16 @@ const _FlowEngine = class _FlowEngine {
845
1136
  if (m) {
846
1137
  return m;
847
1138
  }
848
- const hydrated = this.hydrateModelFromPreviousEngines(options, extra);
1139
+ const hydrated = await this.hydrateModelFromPreviousEngines(options, extra);
849
1140
  if (hydrated) {
850
1141
  return hydrated;
851
1142
  }
852
1143
  const data = await this._modelRepository.findOne(options);
853
1144
  let model = null;
854
1145
  if (data == null ? void 0 : data.uid) {
855
- model = this.createModel(data, extra);
1146
+ model = await this.createModelAsync(data, extra);
856
1147
  } else {
857
- model = this.createModel(options, extra);
1148
+ model = await this.createModelAsync(options, extra);
858
1149
  if (!(extra == null ? void 0 : extra.skipSave)) {
859
1150
  await model.save();
860
1151
  }
@@ -1098,11 +1389,7 @@ _FlowEngine_instances = new WeakSet();
1098
1389
  * @private
1099
1390
  */
1100
1391
  registerModel_fn = /* @__PURE__ */ __name(function(name, modelClass) {
1101
- if (this._modelClasses.has(name)) {
1102
- console.warn(`FlowEngine: Model class with name '${name}' is already registered and will be overwritten.`);
1103
- }
1104
- Object.defineProperty(modelClass, "name", { value: name });
1105
- this._modelClasses.set(name, modelClass);
1392
+ return this._registerModel(name, modelClass);
1106
1393
  }, "#registerModel");
1107
1394
  __name(_FlowEngine, "FlowEngine");
1108
1395
  let FlowEngine = _FlowEngine;
@@ -79,12 +79,19 @@ export interface FlowSettingsOpenOptions {
79
79
  /** 配置保存成功后触发的回调 */
80
80
  onSaved?: () => void | Promise<void>;
81
81
  }
82
+ export type FlowSettingsComponent = React.ComponentType<any>;
83
+ export type FlowSettingsComponentModule = {
84
+ default?: FlowSettingsComponent;
85
+ } | Record<string, FlowSettingsComponent>;
86
+ export type FlowSettingsComponentLoader = () => Promise<FlowSettingsComponentModule | FlowSettingsComponent>;
87
+ export type FlowSettingsComponentLoaderMap = Record<string, FlowSettingsComponentLoader>;
82
88
  export declare class FlowSettings {
83
89
  #private;
84
90
  components: Record<string, any>;
85
91
  scopes: Record<string, any>;
86
92
  private antdComponentsLoaded;
87
93
  enabled: boolean;
94
+ private engine;
88
95
  toolbarItems: ToolbarItemConfig[];
89
96
  constructor(engine: FlowEngine);
90
97
  on(event: 'beforeOpen', callback: (...args: any[]) => void): void;
@@ -110,6 +117,7 @@ export declare class FlowSettings {
110
117
  * flowSettings.registerComponents({ MyComponent, AnotherComponent });
111
118
  */
112
119
  registerComponents(components: Record<string, any>): void;
120
+ registerComponentLoaders(loaders: FlowSettingsComponentLoaderMap): void;
113
121
  /**
114
122
  * 添加作用域到 FlowSettings 的作用域注册表中。
115
123
  * 这些作用域可以在 flow step 的 uiSchema 中使用。
@@ -122,17 +130,17 @@ export declare class FlowSettings {
122
130
  /**
123
131
  * 启用流程设置组件的显示
124
132
  * @example
125
- * flowSettings.enable();
133
+ * await flowSettings.enable();
126
134
  */
127
- enable(): void;
128
- forceEnable(): void;
135
+ enable(): Promise<void>;
136
+ forceEnable(): Promise<void>;
129
137
  /**
130
138
  * 禁用流程设置组件的显示
131
139
  * @example
132
- * flowSettings.disable();
140
+ * await flowSettings.disable();
133
141
  */
134
- disable(): void;
135
- forceDisable(): void;
142
+ disable(): Promise<void>;
143
+ forceDisable(): Promise<void>;
136
144
  /**
137
145
  * 添加扩展工具栏项目
138
146
  * @param {ToolbarItemConfig} config 项目配置