@flowgram.ai/node 0.1.0-alpha.2 → 0.1.0-alpha.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/dist/index.js CHANGED
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
30
  // src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
33
  DataEvent: () => DataEvent,
34
34
  FormModelV2: () => FormModelV2,
35
35
  FormPlugin: () => FormPlugin,
@@ -46,7 +46,7 @@ __export(src_exports, {
46
46
  useWatchFormValues: () => useWatchFormValues,
47
47
  useWatchFormWarnings: () => useWatchFormWarnings
48
48
  });
49
- module.exports = __toCommonJS(src_exports);
49
+ module.exports = __toCommonJS(index_exports);
50
50
 
51
51
  // src/types.ts
52
52
  var DataEvent = /* @__PURE__ */ ((DataEvent2) => {
@@ -65,14 +65,14 @@ function isFormMetaV2(formMeta) {
65
65
  }
66
66
 
67
67
  // src/form-model-v2.ts
68
- var import_lodash2 = require("lodash");
68
+ var import_lodash_es2 = require("lodash-es");
69
69
  var import_utils = require("@flowgram.ai/utils");
70
70
  var import_form_core2 = require("@flowgram.ai/form-core");
71
71
  var import_form2 = require("@flowgram.ai/form");
72
72
  var import_core = require("@flowgram.ai/core");
73
73
 
74
74
  // src/utils.ts
75
- var import_lodash = require("lodash");
75
+ var import_lodash_es = require("lodash-es");
76
76
  var import_form_core = require("@flowgram.ai/form-core");
77
77
  function findMatchedInMap(field, validateMap) {
78
78
  if (!validateMap) {
@@ -81,7 +81,7 @@ function findMatchedInMap(field, validateMap) {
81
81
  if (validateMap[field.name]) {
82
82
  return validateMap[field.name];
83
83
  }
84
- const found = (0, import_lodash.find)(Object.keys(validateMap), (key) => {
84
+ const found = (0, import_lodash_es.find)(Object.keys(validateMap), (key) => {
85
85
  if (key.startsWith("regex:")) {
86
86
  const regex = RegExp(key.split(":")[1]);
87
87
  return regex.test(field.name);
@@ -109,10 +109,25 @@ function convertGlobPath(path) {
109
109
  return path;
110
110
  }
111
111
  function mergeEffectMap(origin, source) {
112
- return (0, import_lodash.mergeWith)(origin, source, function(objValue, srcValue) {
112
+ return (0, import_lodash_es.mergeWith)(origin, source, function(objValue, srcValue) {
113
113
  return (objValue || []).concat(srcValue);
114
114
  });
115
115
  }
116
+ function mergeEffectReturn(origin, source) {
117
+ return () => {
118
+ origin?.();
119
+ source?.();
120
+ };
121
+ }
122
+ function runAndDeleteEffectReturn(effectReturnMap, name, events) {
123
+ events.forEach((event) => {
124
+ const eventMap = effectReturnMap.get(event);
125
+ if (eventMap?.[name]) {
126
+ eventMap[name]();
127
+ delete eventMap[name];
128
+ }
129
+ });
130
+ }
116
131
 
117
132
  // src/form-render.tsx
118
133
  var import_react = __toESM(require("react"));
@@ -124,24 +139,25 @@ function renderForm(formModel) {
124
139
 
125
140
  // src/form-model-v2.ts
126
141
  var DEFAULT = {
127
- EFFECT_MAP: {},
128
- EFFECT_RETURN_MAP: /* @__PURE__ */ new Map([
142
+ // Different formModel should have different reference
143
+ EFFECT_MAP: () => ({}),
144
+ EFFECT_RETURN_MAP: () => /* @__PURE__ */ new Map([
129
145
  ["onValueInitOrChange" /* onValueInitOrChange */, {}],
130
146
  ["onValueChange" /* onValueChange */, {}],
131
147
  ["onValueInit" /* onValueInit */, {}],
132
148
  ["onArrayAppend" /* onArrayAppend */, {}],
133
149
  ["onArrayDelete" /* onArrayDelete */, {}]
134
150
  ]),
135
- FORM_FEEDBACKS: [],
151
+ FORM_FEEDBACKS: () => [],
136
152
  VALID: null
137
153
  };
138
154
  var FormModelV2 = class extends import_form_core2.FormModel {
139
155
  constructor(node) {
140
156
  super();
141
- this.effectMap = DEFAULT.EFFECT_MAP;
142
- this.effectReturnMap = DEFAULT.EFFECT_RETURN_MAP;
157
+ this.effectMap = DEFAULT.EFFECT_MAP();
158
+ this.effectReturnMap = DEFAULT.EFFECT_RETURN_MAP();
143
159
  this.plugins = [];
144
- this.formFeedbacks = DEFAULT.FORM_FEEDBACKS;
160
+ this.formFeedbacks = DEFAULT.FORM_FEEDBACKS();
145
161
  this.onInitializedEmitter = new import_utils.Emitter();
146
162
  this.onValidateEmitter = new import_utils.Emitter();
147
163
  this.onValidate = this.onValidateEmitter.event;
@@ -184,11 +200,20 @@ var FormModelV2 = class extends import_form_core2.FormModel {
184
200
  return this._formControl;
185
201
  }
186
202
  get formMeta() {
187
- return this.node.getNodeRegistry().formMeta;
203
+ return this._formMeta || this.node.getNodeRegistry().formMeta;
204
+ }
205
+ get values() {
206
+ return this.nativeFormModel?.values;
188
207
  }
189
208
  get feedbacks() {
190
209
  return this._feedbacks;
191
210
  }
211
+ updateFormValues(value) {
212
+ if (this.nativeFormModel) {
213
+ const finalValue = this.formMeta.formatOnInit ? this.formMeta.formatOnInit(value, this.nodeContext) : value;
214
+ this.nativeFormModel.values = finalValue;
215
+ }
216
+ }
192
217
  set feedbacks(feedbacks) {
193
218
  this._feedbacks = feedbacks;
194
219
  this.onFeedbacksChangeEmitter.fire(feedbacks);
@@ -202,7 +227,8 @@ var FormModelV2 = class extends import_form_core2.FormModel {
202
227
  get nodeContext() {
203
228
  return {
204
229
  node: this.node,
205
- playgroundContext: this.node.getService(import_core.PlaygroundContext)
230
+ playgroundContext: this.node.getService(import_core.PlaygroundContext),
231
+ clientContext: this.node.getService(import_core.PluginContext)
206
232
  };
207
233
  }
208
234
  get nativeFormModel() {
@@ -218,9 +244,6 @@ var FormModelV2 = class extends import_form_core2.FormModel {
218
244
  this.plugins = plugins;
219
245
  plugins.forEach((plugin) => {
220
246
  plugin.init(this);
221
- if (plugin.config?.effect) {
222
- mergeEffectMap(this.effectMap, plugin.config.effect);
223
- }
224
247
  });
225
248
  }
226
249
  init(formMeta, rawInitialValues) {
@@ -229,11 +252,17 @@ var FormModelV2 = class extends import_form_core2.FormModel {
229
252
  this._valid = null;
230
253
  formData.fireChange();
231
254
  });
255
+ (formMeta.plugins || [])?.forEach((_plugin) => {
256
+ if (_plugin.setupFormMeta) {
257
+ formMeta = _plugin.setupFormMeta(formMeta, this.nodeContext);
258
+ }
259
+ });
260
+ this._formMeta = formMeta;
232
261
  const { validateTrigger, validate, effect } = formMeta;
233
262
  if (effect) {
234
263
  this.effectMap = effect;
235
264
  }
236
- const defaultValues = typeof formMeta.defaultValues === "function" ? formMeta.defaultValues() : formMeta.defaultValues;
265
+ const defaultValues = typeof formMeta.defaultValues === "function" ? formMeta.defaultValues(this.nodeContext) : formMeta.defaultValues;
237
266
  const initialValues = formMeta.formatOnInit ? formMeta.formatOnInit(rawInitialValues, this.nodeContext) : rawInitialValues;
238
267
  const { control } = (0, import_form2.createForm)({
239
268
  initialValues: initialValues || defaultValues,
@@ -251,31 +280,51 @@ var FormModelV2 = class extends import_form_core2.FormModel {
251
280
  if (formMeta.plugins) {
252
281
  this.initPlugins(formMeta.plugins);
253
282
  }
254
- nativeFormModel.onFormValuesChange(({ values, prevValues, name }) => {
255
- const effectKeys = Object.keys(this.effectMap).filter(
256
- (pattern) => import_form2.Glob.isMatchOrParent(pattern, name)
257
- );
258
- effectKeys.forEach((effectKey) => {
259
- const effectOptionsArr = this.effectMap[effectKey];
260
- effectOptionsArr.forEach(({ effect: effect2, event }) => {
261
- if (event === "onValueChange" /* onValueChange */ || event === "onValueInitOrChange" /* onValueInitOrChange */) {
262
- const currentName = import_form2.Glob.getParentPathByPattern(effectKey, name);
263
- const prevEffectReturn = this.effectReturnMap.get(event)?.[currentName];
264
- if (prevEffectReturn) {
265
- prevEffectReturn();
266
- }
267
- const effectReturn = effect2({
268
- name: currentName,
269
- value: (0, import_lodash2.get)(values, currentName),
270
- prevValue: (0, import_lodash2.get)(prevValues, currentName),
271
- formValues: values,
272
- context: this.nodeContext
273
- });
274
- if (effectReturn && typeof effectReturn === "function" && this.effectReturnMap.has(event)) {
275
- const eventMap = this.effectReturnMap.get(event);
276
- eventMap[currentName] = effectReturn;
283
+ nativeFormModel.onFormValuesChange(({ values, prevValues, name, options }) => {
284
+ Object.keys(this.effectMap).forEach((pattern) => {
285
+ const paths = (0, import_lodash_es2.uniq)([
286
+ ...import_form2.Glob.findMatchPaths(values, pattern),
287
+ ...import_form2.Glob.findMatchPaths(prevValues, pattern)
288
+ ]).filter(
289
+ (path) => (
290
+ // trigger effect by compare if value changed
291
+ (0, import_lodash_es2.get)(values, path) !== (0, import_lodash_es2.get)(prevValues, path)
292
+ )
293
+ );
294
+ if (import_form2.Glob.isMatchOrParent(pattern, name)) {
295
+ const currentName = import_form2.Glob.getParentPathByPattern(pattern, name);
296
+ if (!paths.includes(currentName)) {
297
+ paths.push(currentName);
298
+ }
299
+ }
300
+ const effectOptionsArr = this.effectMap[pattern];
301
+ paths.forEach((path) => {
302
+ let eventList = ["onValueChange" /* onValueChange */, "onValueInitOrChange" /* onValueInitOrChange */];
303
+ const isPrevNil = (0, import_lodash_es2.isNil)((0, import_lodash_es2.get)(prevValues, path));
304
+ if (isPrevNil) {
305
+ if (options?.action === "array-append" && import_form2.Glob.isMatch(`${name}.*`, path)) {
306
+ eventList = [];
307
+ } else {
308
+ eventList = ["onValueInit" /* onValueInit */, "onValueInitOrChange" /* onValueInitOrChange */];
277
309
  }
278
310
  }
311
+ runAndDeleteEffectReturn(this.effectReturnMap, path, eventList);
312
+ effectOptionsArr.forEach(({ effect: effect2, event }) => {
313
+ if (eventList.includes(event)) {
314
+ const effectReturn = effect2({
315
+ name: path,
316
+ value: (0, import_lodash_es2.get)(values, path),
317
+ prevValue: (0, import_lodash_es2.get)(prevValues, path),
318
+ formValues: values,
319
+ form: (0, import_form2.toForm)(this.nativeFormModel),
320
+ context: this.nodeContext
321
+ });
322
+ if (effectReturn && typeof effectReturn === "function" && this.effectReturnMap.has(event)) {
323
+ const eventMap = this.effectReturnMap.get(event);
324
+ eventMap[path] = mergeEffectReturn(eventMap[path], effectReturn);
325
+ }
326
+ }
327
+ });
279
328
  });
280
329
  });
281
330
  });
@@ -283,24 +332,25 @@ var FormModelV2 = class extends import_form_core2.FormModel {
283
332
  Object.keys(this.effectMap).forEach((pattern) => {
284
333
  const paths = import_form2.Glob.findMatchPaths(values, pattern);
285
334
  const effectOptionsArr = this.effectMap[pattern];
286
- effectOptionsArr.forEach(({ event, effect: effect2 }) => {
287
- if (event === "onValueInit" /* onValueInit */ || event === "onValueInitOrChange" /* onValueInitOrChange */) {
288
- paths.forEach((path) => {
289
- if (import_form2.Glob.isMatchOrParent(name, path) || name === path) {
290
- const prevEffectReturn = this.effectReturnMap.get(event)?.[path];
291
- if (prevEffectReturn) {
292
- prevEffectReturn();
293
- }
335
+ paths.forEach((path) => {
336
+ if (import_form2.Glob.isMatchOrParent(name, path) || name === path) {
337
+ runAndDeleteEffectReturn(this.effectReturnMap, path, [
338
+ "onValueInit" /* onValueInit */,
339
+ "onValueInitOrChange" /* onValueInitOrChange */
340
+ ]);
341
+ effectOptionsArr.forEach(({ event, effect: effect2 }) => {
342
+ if (event === "onValueInit" /* onValueInit */ || event === "onValueInitOrChange" /* onValueInitOrChange */) {
294
343
  const effectReturn = effect2({
295
344
  name: path,
296
- value: (0, import_lodash2.get)(values, path),
345
+ value: (0, import_lodash_es2.get)(values, path),
297
346
  formValues: values,
298
- prevValue: (0, import_lodash2.get)(prevValues, path),
347
+ prevValue: (0, import_lodash_es2.get)(prevValues, path),
348
+ form: (0, import_form2.toForm)(this.nativeFormModel),
299
349
  context: this.nodeContext
300
350
  });
301
351
  if (effectReturn && typeof effectReturn === "function" && this.effectReturnMap.has(event)) {
302
352
  const eventMap = this.effectReturnMap.get(event);
303
- eventMap[path] = effectReturn;
353
+ eventMap[path] = mergeEffectReturn(eventMap[path], effectReturn);
304
354
  }
305
355
  }
306
356
  });
@@ -311,13 +361,14 @@ var FormModelV2 = class extends import_form_core2.FormModel {
311
361
  nativeFormModel.onFieldModelCreate((field) => {
312
362
  const effectOptionsArr = findMatchedInMap(field, this.effectMap);
313
363
  if (effectOptionsArr?.length) {
314
- const eventMap = (0, import_lodash2.groupBy)(effectOptionsArr, "event");
315
- (0, import_lodash2.mapKeys)(eventMap, (optionsArr, event) => {
364
+ const eventMap = (0, import_lodash_es2.groupBy)(effectOptionsArr, "event");
365
+ (0, import_lodash_es2.mapKeys)(eventMap, (optionsArr, event) => {
316
366
  const combinedEffect = (props) => {
317
367
  optionsArr.forEach(
318
368
  ({ effect: effect2 }) => effect2({
319
369
  ...props,
320
370
  formValues: nativeFormModel.values,
371
+ form: (0, import_form2.toForm)(this.nativeFormModel),
321
372
  context: this.nodeContext
322
373
  })
323
374
  );
@@ -353,13 +404,10 @@ var FormModelV2 = class extends import_form_core2.FormModel {
353
404
  return this.nativeFormModel?.values;
354
405
  }
355
406
  clearValid() {
356
- if (this.valid !== null) {
357
- this.valid = null;
358
- }
359
407
  }
360
408
  async validate() {
361
409
  this.formFeedbacks = await this.nativeFormModel?.validate();
362
- this.valid = (0, import_lodash2.isEmpty)(this.formFeedbacks?.filter((f) => f.level === "error"));
410
+ this.valid = (0, import_lodash_es2.isEmpty)(this.formFeedbacks?.filter((f) => f.level === "error"));
363
411
  this.onValidateEmitter.fire(this);
364
412
  return this.valid;
365
413
  }
@@ -389,16 +437,18 @@ var FormModelV2 = class extends import_form_core2.FormModel {
389
437
  `[NodeEngine] FormModel Error: onFormValueChangeIn can not be called before initialized`
390
438
  );
391
439
  }
392
- this.formControl._formModel.onFormValuesChange(({ name: changedName, values, prevValues }) => {
393
- if (changedName === name) {
394
- callback({
395
- value: (0, import_lodash2.get)(values, name),
396
- prevValue: (0, import_lodash2.get)(prevValues, name),
397
- formValues: values,
398
- prevFormValues: prevValues
399
- });
440
+ return this.formControl._formModel.onFormValuesChange(
441
+ ({ name: changedName, values, prevValues }) => {
442
+ if (changedName === name) {
443
+ callback({
444
+ value: (0, import_lodash_es2.get)(values, name),
445
+ prevValue: (0, import_lodash_es2.get)(prevValues, name),
446
+ formValues: values,
447
+ prevFormValues: prevValues
448
+ });
449
+ }
400
450
  }
401
- });
451
+ );
402
452
  }
403
453
  /**
404
454
  * @deprecated 该方法用于兼容 V1 版本 FormModel接口,如果确定是FormModelV2 请使用 FormModel.getValueIn
@@ -455,13 +505,13 @@ var FormModelV2 = class extends import_form_core2.FormModel {
455
505
  effectReturn();
456
506
  });
457
507
  });
458
- this.effectMap = DEFAULT.EFFECT_MAP;
459
- this.effectReturnMap = DEFAULT.EFFECT_RETURN_MAP;
508
+ this.effectMap = DEFAULT.EFFECT_MAP();
509
+ this.effectReturnMap = DEFAULT.EFFECT_RETURN_MAP();
460
510
  this.plugins.forEach((p) => {
461
511
  p.dispose();
462
512
  });
463
513
  this.plugins = [];
464
- this.formFeedbacks = DEFAULT.FORM_FEEDBACKS;
514
+ this.formFeedbacks = DEFAULT.FORM_FEEDBACKS();
465
515
  this._valid = DEFAULT.VALID;
466
516
  this._formControl = void 0;
467
517
  this._initialized = false;
@@ -537,9 +587,9 @@ function useWatchFormWarnings(node) {
537
587
  // src/form-plugin.ts
538
588
  var import_nanoid = require("nanoid");
539
589
  var FormPlugin = class {
540
- constructor(name, config, opts) {
541
- this.name = name;
542
- this.pluginId = `${name}__${(0, import_nanoid.nanoid)()}`;
590
+ constructor(config, opts) {
591
+ this.name = config?.name || "";
592
+ this.pluginId = `${this.name}__${(0, import_nanoid.nanoid)()}`;
543
593
  this.config = config;
544
594
  this.opts = opts;
545
595
  }
@@ -549,10 +599,46 @@ var FormPlugin = class {
549
599
  get ctx() {
550
600
  return {
551
601
  formModel: this.formModel,
552
- node: this.formModel.nodeContext.node,
553
- playgroundContext: this.formModel.nodeContext.playgroundContext
602
+ ...this.formModel.nodeContext
554
603
  };
555
604
  }
605
+ setupFormMeta(formMeta, nodeContext) {
606
+ const nextFormMeta = {
607
+ ...formMeta
608
+ };
609
+ this.config.onSetupFormMeta?.(
610
+ {
611
+ mergeEffect: (effect) => {
612
+ nextFormMeta.effect = mergeEffectMap(nextFormMeta.effect || {}, effect);
613
+ },
614
+ mergeValidate: (validate) => {
615
+ nextFormMeta.validate = {
616
+ ...nextFormMeta.validate || {},
617
+ ...validate
618
+ };
619
+ },
620
+ addFormatOnInit: (formatOnInit) => {
621
+ if (!nextFormMeta.formatOnInit) {
622
+ nextFormMeta.formatOnInit = formatOnInit;
623
+ return;
624
+ }
625
+ const legacyFormatOnInit = nextFormMeta.formatOnInit;
626
+ nextFormMeta.formatOnInit = (v, c) => formatOnInit?.(legacyFormatOnInit(v, c), c);
627
+ },
628
+ addFormatOnSubmit: (formatOnSubmit) => {
629
+ if (!nextFormMeta.formatOnSubmit) {
630
+ nextFormMeta.formatOnSubmit = formatOnSubmit;
631
+ return;
632
+ }
633
+ const legacyFormatOnSubmit = nextFormMeta.formatOnSubmit;
634
+ nextFormMeta.formatOnSubmit = (v, c) => formatOnSubmit?.(legacyFormatOnSubmit(v, c), c);
635
+ },
636
+ ...nodeContext
637
+ },
638
+ this.opts
639
+ );
640
+ return nextFormMeta;
641
+ }
556
642
  init(formModel) {
557
643
  this._formModel = formModel;
558
644
  this.config?.onInit?.(this.ctx, this.opts);
@@ -563,9 +649,9 @@ var FormPlugin = class {
563
649
  }
564
650
  }
565
651
  };
566
- function defineFormPluginCreator(name, config) {
652
+ function defineFormPluginCreator(config) {
567
653
  return function(opts) {
568
- return new FormPlugin(name, config, opts);
654
+ return new FormPlugin(config, opts);
569
655
  };
570
656
  }
571
657
 
@@ -584,6 +670,9 @@ function getNodeForm(node) {
584
670
  state: nativeFormModel.state,
585
671
  getValueIn: (name) => nativeFormModel.getValueIn(name),
586
672
  setValueIn: (name, value) => nativeFormModel.setValueIn(name, value),
673
+ updateFormValues: (values) => {
674
+ formModel.updateFormValues(values);
675
+ },
587
676
  render: () => /* @__PURE__ */ import_react3.default.createElement(import_form_core5.NodeRender, { node }),
588
677
  onFormValuesChange: formModel.onFormValuesChange.bind(formModel),
589
678
  onFormValueChangeIn: formModel.onFormValueChangeIn.bind(formModel),