@esfaenza/flow-builder 20.3.13 → 20.3.14

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/README.md CHANGED
@@ -90,7 +90,7 @@ l'attributo di scope di Angular, quindi un CSS incapsulato non li raggiunge.
90
90
  | `version` | la versione da aprire; assente → l'attiva se c'e', altrimenti l'ultima (§6.1) |
91
91
  | `author` | registrato sulla versione e mostrato nell'elenco |
92
92
  | `defaultProcessType` | `processType` iniziale di un flow nuovo |
93
- | `inspectorMode` | `'dialog'` (predefinito) apre il dettaglio dell'elemento in una finestra sopra il canvas, come il flow builder di Salesforce; `'panel'` lo tiene nel pannello laterale |
93
+ | `inspectorMode` | `'dialog'` (predefinito) apre il dettaglio dell'elemento in una finestra sopra il canvas; `'panel'` lo tiene nel pannello laterale |
94
94
 
95
95
  | Output | Quando |
96
96
  |---|---|
@@ -334,6 +334,17 @@ vuoto resta "non lo so" — primitiva non esposta, tipo senza valori dichiarati,
334
334
  da scegliere — e allora il valore si digita; con l'elenco popolato un valore fuori elenco e' un
335
335
  **avviso**, perche' nessun codice della §7 lo blocca ed e' l'editor ad accorgersene prima del runtime.
336
336
 
337
+ **Un campo a `null` e' assente.** Il valore ha un campo per tipo e va valorizzato **uno e un solo**
338
+ campo (§4.2); la §2 dice che cio' che non c'e' si omette, ma un backend che serializza tutte le
339
+ proprieta' — `System.Text.Json` senza `IgnoreNullValues` lo fa di default — manda
340
+ `{"enumValue": "InIstruttoria", "formulaExpression": null, …}`: un solo valore e sette caselle piene
341
+ di niente. Riconoscere il campo con `!== undefined` faceva vincere il primo letto, cioe'
342
+ `formulaExpression`: l'editor apriva la **formula** (vuota) e il valore, pur presente nel documento,
343
+ spariva dalla vista — e il conteggio dei campi accusava `VALUE_AMBIGUOUS`. La regola sta in
344
+ `core/flow-value.util.ts` (`isValued`, `valuedFieldOf`, `valuedFieldsOf`) e la usano l'editor del
345
+ valore e quello delle condizioni: `null` e `undefined` significano la stessa cosa, mentre
346
+ `booleanValue: false`, `numberValue: 0` e `stringValue: ''` restano valori.
347
+
337
348
  Perche' l'editor conosca il tipo della destinazione serve saperlo, e i percorsi non fanno eccezione:
338
349
  `POST /flows/references` elenca le **radici** e non i percorsi, quindi su `Richiesta.Stato` la
339
350
  corrispondenza esatta del nome non trova niente. Il tipo si ricava allora navigando la catena —
@@ -1205,6 +1205,67 @@ function parseInvariantNumber(raw) {
1205
1205
  return Number.isFinite(parsed) ? parsed : undefined;
1206
1206
  }
1207
1207
 
1208
+ /**
1209
+ * Quale campo di un `FlowElementReferenceOrValue` porta davvero il valore — FRONTEND.md §4.2.
1210
+ *
1211
+ * La regola del contratto e' "uno e un solo campo valorizzato", e la §2 dice che cio' che non c'e'
1212
+ * si **omette**. Un backend che serializza tutte le proprieta' — `System.Text.Json` senza
1213
+ * `IgnoreNullValues` lo fa di default — rispetta il contratto nella sostanza e lo viola nella forma:
1214
+ * arriva `{"enumValue": "InIstruttoria", "formulaExpression": null, ...}`, cioe' un solo valore e
1215
+ * sette caselle piene di niente.
1216
+ *
1217
+ * Il campo si sceglieva con `!== undefined`, e un `null` passava: la prima casella letta —
1218
+ * `formulaExpression` — vinceva, l'editor apriva la formula (vuota) e il valore, pur presente nel
1219
+ * documento, spariva dalla vista. Da qui questa funzione sola: **`null` e' assente quanto
1220
+ * `undefined`**, e chi interpreta un valore la usa invece di confrontare con `undefined`.
1221
+ *
1222
+ * Sta in `core/` perche' i chiamanti sono piu' d'uno — l'editor del valore, l'editor delle
1223
+ * condizioni — e la regola non deve divergere fra loro.
1224
+ */
1225
+ /**
1226
+ * I campi che possono portare il valore, **nell'ordine in cui si interpretano**: `formulaExpression`
1227
+ * per primo perche' e' l'unico a due campi, poi il riferimento, poi i letterali. `formulaDataType`
1228
+ * non c'e': accompagna l'espressione, non e' un valore da solo.
1229
+ */
1230
+ const FLOW_VALUE_FIELDS = [
1231
+ 'formulaExpression',
1232
+ 'elementReference',
1233
+ 'stringValue',
1234
+ 'integerValue',
1235
+ 'numberValue',
1236
+ 'dateValue',
1237
+ 'booleanValue',
1238
+ 'enumValue',
1239
+ ];
1240
+ /** I soli campi letterali: quelli che l'editor mostra sotto la modalita' «Valore». */
1241
+ const FLOW_VALUE_LITERAL_FIELDS = [
1242
+ 'stringValue',
1243
+ 'integerValue',
1244
+ 'numberValue',
1245
+ 'dateValue',
1246
+ 'booleanValue',
1247
+ 'enumValue',
1248
+ ];
1249
+ /**
1250
+ * `true` se il campo porta un valore. Attenzione ai falsi legittimi: `booleanValue: false`,
1251
+ * `numberValue: 0` e `stringValue: ''` sono valori, quindi il confronto e' con `null`/`undefined`
1252
+ * e non una verifica di verita'.
1253
+ */
1254
+ function isValued(field) {
1255
+ return field !== undefined && field !== null;
1256
+ }
1257
+ /** I campi valorizzati, nell'ordine di interpretazione: piu' di uno e' `VALUE_AMBIGUOUS` (§4.2). */
1258
+ function valuedFieldsOf(value) {
1259
+ if (!value) {
1260
+ return [];
1261
+ }
1262
+ return FLOW_VALUE_FIELDS.filter((field) => isValued(value[field]));
1263
+ }
1264
+ /** Il campo che l'editor considera **il** valore, cioe' il primo valorizzato nell'ordine sopra. */
1265
+ function valuedFieldOf(value) {
1266
+ return valuedFieldsOf(value)[0];
1267
+ }
1268
+
1208
1269
  /**
1209
1270
  * Gli step di uno stage di orchestrazione — FRONTEND.md §5.13.
1210
1271
  *
@@ -5406,18 +5467,16 @@ class ValueEditorComponent {
5406
5467
  // valore che il modello non sa portare (§4.2, §4.7).
5407
5468
  return this.dataType() && this.literalAllowed() ? 'literal' : 'reference';
5408
5469
  }
5409
- if (value.formulaExpression !== undefined) {
5470
+ // `isValued` e non `!== undefined`: un backend che serializza anche cio' che non c'e' manda
5471
+ // `formulaExpression: null`, e il primo controllo apriva la formula (vuota) su un valore che nel
5472
+ // documento c'era — un letterale che sparisce dalla vista senza che nulla lo segnali (§4.2).
5473
+ if (isValued(value.formulaExpression)) {
5410
5474
  return 'formula';
5411
5475
  }
5412
- if (value.elementReference !== undefined) {
5476
+ if (isValued(value.elementReference)) {
5413
5477
  return value.elementReference.startsWith('$GlobalConstant.') ? 'globalConstant' : 'reference';
5414
5478
  }
5415
- if (value.stringValue !== undefined ||
5416
- value.integerValue !== undefined ||
5417
- value.numberValue !== undefined ||
5418
- value.dateValue !== undefined ||
5419
- value.booleanValue !== undefined ||
5420
- value.enumValue !== undefined) {
5479
+ if (FLOW_VALUE_LITERAL_FIELDS.some((field) => isValued(value[field]))) {
5421
5480
  return 'literal';
5422
5481
  }
5423
5482
  return 'empty';
@@ -5427,23 +5486,7 @@ class ValueEditorComponent {
5427
5486
  * Puo' capitare su un documento arrivato da un altro editor: si segnala e si offre
5428
5487
  * di normalizzarlo, invece di nasconderlo.
5429
5488
  */
5430
- filledFieldCount = computed(() => {
5431
- const value = this.value();
5432
- if (!value) {
5433
- return 0;
5434
- }
5435
- const keys = [
5436
- 'elementReference',
5437
- 'stringValue',
5438
- 'integerValue',
5439
- 'numberValue',
5440
- 'dateValue',
5441
- 'booleanValue',
5442
- 'enumValue',
5443
- 'formulaExpression',
5444
- ];
5445
- return keys.filter((key) => value[key] !== undefined).length;
5446
- }, ...(ngDevMode ? [{ debugName: "filledFieldCount" }] : []));
5489
+ filledFieldCount = computed(() => valuedFieldsOf(this.value()).length, ...(ngDevMode ? [{ debugName: "filledFieldCount" }] : []));
5447
5490
  isAmbiguous = computed(() => this.filledFieldCount() > 1, ...(ngDevMode ? [{ debugName: "isAmbiguous" }] : []));
5448
5491
  /**
5449
5492
  * Il campo del valore che corrisponde al `dataType` (§4.2, tabella degli otto tipi). `Object` e
@@ -5498,7 +5541,7 @@ class ValueEditorComponent {
5498
5541
  return '';
5499
5542
  }
5500
5543
  const field = this.literalField();
5501
- if (field === 'dateValue' && value.dateValue !== undefined) {
5544
+ if (field === 'dateValue' && isValued(value.dateValue)) {
5502
5545
  // `datetime-local` rifiuta un valore col fuso e resterebbe **vuoto** pur avendo un
5503
5546
  // valore: il suffisso si toglie qui e si riscrive in uscita. Se il documento porta un
5504
5547
  // campo diverso da quello atteso si passa al fallback qui sotto, che lo mostra comunque.
@@ -5658,7 +5701,13 @@ class ValueEditorComponent {
5658
5701
  this.emit({ elementReference: value.elementReference });
5659
5702
  return;
5660
5703
  default: {
5661
- const field = this.literalField();
5704
+ // Il campo del tipo atteso, ma solo se e' quello che porta il valore: dove il tipo non si
5705
+ // sa — o il documento usa un campo diverso — «normalizza» scriverebbe un valore vuoto e
5706
+ // butterebbe via l'unico che c'era.
5707
+ const expected = this.literalField();
5708
+ const field = isValued(value[expected])
5709
+ ? expected
5710
+ : (FLOW_VALUE_LITERAL_FIELDS.find((candidate) => isValued(value[candidate])) ?? expected);
5662
5711
  this.emit({ [field]: value[field] });
5663
5712
  }
5664
5713
  }
@@ -5780,31 +5829,29 @@ class ConditionEditorComponent {
5780
5829
  if (!value) {
5781
5830
  return undefined;
5782
5831
  }
5783
- if (value.formulaExpression !== undefined) {
5784
- return value.formulaDataType;
5785
- }
5786
- if (value.elementReference !== undefined) {
5787
- return this.typeOfReference(value.elementReference);
5788
- }
5789
- if (value.stringValue !== undefined) {
5790
- return 'String';
5791
- }
5792
- if (value.integerValue !== undefined) {
5793
- return 'Integer';
5794
- }
5795
- if (value.numberValue !== undefined) {
5796
- return 'Number';
5797
- }
5798
- if (value.dateValue !== undefined) {
5799
- return 'Date';
5800
- }
5801
- if (value.booleanValue !== undefined) {
5802
- return 'Boolean';
5803
- }
5804
- if (value.enumValue !== undefined) {
5805
- return 'Enum';
5832
+ // Stessa regola dell'editor del valore: un campo a `null` e' assente, non valorizzato — con
5833
+ // `!== undefined` un backend che serializza tutto faceva risultare **formula** ogni letterale,
5834
+ // e il tipo dedotto era quello sbagliato (§4.2).
5835
+ switch (valuedFieldOf(value)) {
5836
+ case 'formulaExpression':
5837
+ return value.formulaDataType;
5838
+ case 'elementReference':
5839
+ return this.typeOfReference(value.elementReference);
5840
+ case 'stringValue':
5841
+ return 'String';
5842
+ case 'integerValue':
5843
+ return 'Integer';
5844
+ case 'numberValue':
5845
+ return 'Number';
5846
+ case 'dateValue':
5847
+ return 'Date';
5848
+ case 'booleanValue':
5849
+ return 'Boolean';
5850
+ case 'enumValue':
5851
+ return 'Enum';
5852
+ default:
5853
+ return undefined;
5806
5854
  }
5807
- return undefined;
5808
5855
  }
5809
5856
  /**
5810
5857
  * `true` quando i due lati sono incompatibili: e' `CONDITION_TYPE_MISMATCH`, un errore che
@@ -5975,7 +6022,7 @@ class ConditionEditorComponent {
5975
6022
  // "confronta con questo" ma "l'esito atteso e' questo": va riscritto, non tenuto.
5976
6023
  condition.rightValue = { booleanValue: true };
5977
6024
  }
5978
- else if (condition.rightValue?.booleanValue !== undefined && operator !== 'EqualTo') {
6025
+ else if (isValued(condition.rightValue?.booleanValue) && operator !== 'EqualTo') {
5979
6026
  condition.rightValue = undefined;
5980
6027
  }
5981
6028
  });
@@ -10585,5 +10632,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
10585
10632
  * Generated bundle index. Do not edit.
10586
10633
  */
10587
10634
 
10588
- export { ConditionEditorComponent, ConnectorEditorComponent, DebugPanelComponent, ElementDialogComponent, ElementInspectorComponent, ElementPaletteComponent, EnumValuePickerComponent, FALLBACK_COLLECTION_BY_TYPE, FALLBACK_TYPE_LABEL, FLOW_BUILDER_HTTP_CONFIG, FLOW_ELEMENT_ICONS, FLOW_ELEMENT_VARIANT_FIELDS, FLOW_ELEMENT_VARIANT_ICONS, FLOW_ERROR_FALLBACK_MESSAGE, FLOW_ERROR_HTTP_STATUS, FLOW_NAME_PATTERN, FLOW_NODE_COLLECTIONS, FLOW_NODE_HEIGHT, FLOW_NODE_WIDTH, FLOW_RESOURCE_COLLECTIONS, FieldAssignmentEditorComponent, FieldPickerComponent, FlowApiError, FlowBuilderApi, FlowBuilderComponent, FlowCanvasComponent, FlowCatalogStore, FlowDictionaryStore, FlowDocumentStore, FlowEditorSession, FlowLayoutService, FlowValidationStore, HttpFlowBuilderApi, NamePickerComponent, NodeInspectorBase, ORCHESTRATION_CONDITION_OUTPUT, ObjectPickerComponent, OrchestratedStageInspectorComponent, ParameterEditorComponent, ProblemsPanelComponent, RecordFilterEditorComponent, ReferencePickerComponent, ResourcePanelComponent, SEVERITY_BUCKETS, SEVERITY_ICON, SEVERITY_LABEL, START_NODE_NAME, SelectValueDirective, StartInspectorComponent, StructureMemberPickerComponent, StructurePickerComponent, TYPES_WITH_AUTOMATIC_OUTPUT, TYPE_BY_COLLECTION, UNSUPPORTED_TYPES, ValueEditorComponent, VersionPanelComponent, areTypesComparable, canvasNodeId, checkConditionLogic, checkFlowName, describePathEntry, elementIcon, emptyFlowDefinition, filterReferences, flowNodeWidth, flowNodeWidthClass, isCustomConditionLogic, isEmptyReferenceFilter, isGlobalReference, isNumericType, isTypeCheckedOperator, isValidFlowName, loadPathLevel, matchesReferenceFilter, moveCondition, navigatePath, outletByKey, outletsOf, parseCanvasNodeId, parseInvariantNumber, parseSourceConnectorId, parseTargetConnectorId, pathAvailableNames, pathContainerLabel, pathNotVerifiableMessage, referenceRoot, remapConditionLogic, removeCondition, resolvePath, severityBucket, slugifyFlowName, sourceConnectorId, stageStepNames, stageStepOutputReferenced, stepsOf, targetConnectorId, uniqueFlowName, variantFieldOf, variantOf, variantPresetOf };
10635
+ export { ConditionEditorComponent, ConnectorEditorComponent, DebugPanelComponent, ElementDialogComponent, ElementInspectorComponent, ElementPaletteComponent, EnumValuePickerComponent, FALLBACK_COLLECTION_BY_TYPE, FALLBACK_TYPE_LABEL, FLOW_BUILDER_HTTP_CONFIG, FLOW_ELEMENT_ICONS, FLOW_ELEMENT_VARIANT_FIELDS, FLOW_ELEMENT_VARIANT_ICONS, FLOW_ERROR_FALLBACK_MESSAGE, FLOW_ERROR_HTTP_STATUS, FLOW_NAME_PATTERN, FLOW_NODE_COLLECTIONS, FLOW_NODE_HEIGHT, FLOW_NODE_WIDTH, FLOW_RESOURCE_COLLECTIONS, FLOW_VALUE_FIELDS, FLOW_VALUE_LITERAL_FIELDS, FieldAssignmentEditorComponent, FieldPickerComponent, FlowApiError, FlowBuilderApi, FlowBuilderComponent, FlowCanvasComponent, FlowCatalogStore, FlowDictionaryStore, FlowDocumentStore, FlowEditorSession, FlowLayoutService, FlowValidationStore, HttpFlowBuilderApi, NamePickerComponent, NodeInspectorBase, ORCHESTRATION_CONDITION_OUTPUT, ObjectPickerComponent, OrchestratedStageInspectorComponent, ParameterEditorComponent, ProblemsPanelComponent, RecordFilterEditorComponent, ReferencePickerComponent, ResourcePanelComponent, SEVERITY_BUCKETS, SEVERITY_ICON, SEVERITY_LABEL, START_NODE_NAME, SelectValueDirective, StartInspectorComponent, StructureMemberPickerComponent, StructurePickerComponent, TYPES_WITH_AUTOMATIC_OUTPUT, TYPE_BY_COLLECTION, UNSUPPORTED_TYPES, ValueEditorComponent, VersionPanelComponent, areTypesComparable, canvasNodeId, checkConditionLogic, checkFlowName, describePathEntry, elementIcon, emptyFlowDefinition, filterReferences, flowNodeWidth, flowNodeWidthClass, isCustomConditionLogic, isEmptyReferenceFilter, isGlobalReference, isNumericType, isTypeCheckedOperator, isValidFlowName, isValued, loadPathLevel, matchesReferenceFilter, moveCondition, navigatePath, outletByKey, outletsOf, parseCanvasNodeId, parseInvariantNumber, parseSourceConnectorId, parseTargetConnectorId, pathAvailableNames, pathContainerLabel, pathNotVerifiableMessage, referenceRoot, remapConditionLogic, removeCondition, resolvePath, severityBucket, slugifyFlowName, sourceConnectorId, stageStepNames, stageStepOutputReferenced, stepsOf, targetConnectorId, uniqueFlowName, valuedFieldOf, valuedFieldsOf, variantFieldOf, variantOf, variantPresetOf };
10589
10636
  //# sourceMappingURL=esfaenza-flow-builder.mjs.map