@octaviaflow/flow-rules 0.14.0 → 0.15.0
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/catalog/general/transform/config.d.ts +21 -0
- package/dist/index.cjs +20 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +20 -1
- package/package.json +1 -1
|
@@ -24,6 +24,19 @@ export interface FieldMapping {
|
|
|
24
24
|
parentId?: string;
|
|
25
25
|
/** Nesting depth (0 = root) */
|
|
26
26
|
depth?: number;
|
|
27
|
+
/** With `groupBy`: this field goes into each line of the record's list, not the record (DEV-478). Root level only. */
|
|
28
|
+
lineField?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* One record per key (DEV-478): rows whose `key` resolves to the same value
|
|
32
|
+
* become one record (fields from the group's first row); the mappings marked
|
|
33
|
+
* `lineField` become a list of line objects under `into`, in row order.
|
|
34
|
+
*/
|
|
35
|
+
export interface TransformGroupBy {
|
|
36
|
+
/** Source expression of the key, written like a sourceField: `{{orders[].number}}`. */
|
|
37
|
+
key: string;
|
|
38
|
+
/** Target field holding the list of lines: `line_items` (Shopify), `Line` (QuickBooks), `order_line` (Odoo). */
|
|
39
|
+
into: string;
|
|
27
40
|
}
|
|
28
41
|
export type TransformMode = 'visual' | 'expression';
|
|
29
42
|
/**
|
|
@@ -65,6 +78,8 @@ export interface TransformConfigType {
|
|
|
65
78
|
/** Explicit upsert/update match field (legacy externalid/pkey). Empty =
|
|
66
79
|
* per-connector auto-detection (Mongo _id, SF Id, SQL primary key). */
|
|
67
80
|
upsertMatchKey?: string;
|
|
81
|
+
/** One record per key, with the `lineField` mappings collected into a list (DEV-478). */
|
|
82
|
+
groupBy?: TransformGroupBy;
|
|
68
83
|
/** Ordered column header names — the exact columns + header text written. */
|
|
69
84
|
sheetHeaders?: string[];
|
|
70
85
|
/** Create the target tab on first write if it doesn't exist (default true). */
|
|
@@ -117,6 +132,12 @@ export declare const TransformConfig: {
|
|
|
117
132
|
mappings: {
|
|
118
133
|
type: string;
|
|
119
134
|
required: boolean;
|
|
135
|
+
description: string;
|
|
136
|
+
};
|
|
137
|
+
groupBy: {
|
|
138
|
+
type: string;
|
|
139
|
+
required: boolean;
|
|
140
|
+
description: string;
|
|
120
141
|
};
|
|
121
142
|
expression: {
|
|
122
143
|
type: string;
|
package/dist/index.cjs
CHANGED
|
@@ -3771,7 +3771,16 @@ var TransformConfig = {
|
|
|
3771
3771
|
options: TRANSFORM_MODES,
|
|
3772
3772
|
description: "How the mappings are authored: visual (the Field Mapper — the only mode the editor offers) or expression (legacy JavaScript). This is not the write mode; that is `operation`."
|
|
3773
3773
|
},
|
|
3774
|
-
mappings: {
|
|
3774
|
+
mappings: {
|
|
3775
|
+
type: "array",
|
|
3776
|
+
required: false,
|
|
3777
|
+
description: "Field mappings: [{ id, sourceField, targetField, targetType, transform? }]. sourceField is a token like {{orders[].email}}; " + "an index picks one list element ({{products[].variants[0].price}}). With groupBy, set lineField: true on the mappings that make each line."
|
|
3778
|
+
},
|
|
3779
|
+
groupBy: {
|
|
3780
|
+
type: "json",
|
|
3781
|
+
required: false,
|
|
3782
|
+
description: 'One record per key, with line items: { "key": "{{orders[].number}}", "into": "line_items" }. Rows whose key is the same become ONE record ' + "(its fields from the first row); mappings with lineField: true become a list of lines under `into` (Shopify line_items, QuickBooks Line, Odoo order_line). " + "Dotted line fields nest inside each line (SalesItemLineDetail.ItemRef.value)."
|
|
3783
|
+
},
|
|
3775
3784
|
expression: { type: "code", required: false }
|
|
3776
3785
|
},
|
|
3777
3786
|
generateName: (operation, connectorLabel, objectName) => {
|
|
@@ -3812,6 +3821,16 @@ var TransformConfig = {
|
|
|
3812
3821
|
});
|
|
3813
3822
|
}
|
|
3814
3823
|
}
|
|
3824
|
+
const groupBy = config.groupBy;
|
|
3825
|
+
if (groupBy && (groupBy.key || groupBy.into)) {
|
|
3826
|
+
if (!groupBy.key)
|
|
3827
|
+
errors.push("One record per key: choose the key field (groupBy.key)");
|
|
3828
|
+
if (!groupBy.into)
|
|
3829
|
+
errors.push("One record per key: name the field that holds the lines (groupBy.into)");
|
|
3830
|
+
if (groupBy.key && groupBy.into && !(config.mappings ?? []).some((m) => m.lineField)) {
|
|
3831
|
+
errors.push("One record per key: mark at least one mapping as a line field (lineField: true)");
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3815
3834
|
return { valid: errors.length === 0, errors };
|
|
3816
3835
|
},
|
|
3817
3836
|
merge: (userConfig) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export { EmailConfig, } from "./catalog/communication/email-send/config";
|
|
|
36
36
|
export { queryDefinition, } from "./catalog/general/query/index";
|
|
37
37
|
export { isQueryableConnector, } from "./catalog/general/query/config";
|
|
38
38
|
export { AggregateFunction, type BuildQueryConfig, type ColumnSchema, type ConnectorSchema, JoinType, LogicalOperator, type QueryExecutionResult, type QueryField, type QueryFilter, type QueryFilterGroup, type QueryJoin, type QuerySort, SortDirection, type VisualQueryConfig, } from "./catalog/general/query/types";
|
|
39
|
-
export { DATABASE_CONNECTOR_IDS, type FieldMapping, TRANSFORM_MODES, TRANSFORM_OPERATIONS, TransformConfig, type TransformConfigType, type TransformOperation, } from "./catalog/general/transform/config";
|
|
39
|
+
export { DATABASE_CONNECTOR_IDS, type FieldMapping, TRANSFORM_MODES, TRANSFORM_OPERATIONS, TransformConfig, type TransformConfigType, type TransformGroupBy, type TransformOperation, } from "./catalog/general/transform/config";
|
|
40
40
|
export { AGGREGATE_FUNCTIONS, AGGREGATE_FUNCTION_DESCRIPTIONS, AggregateConfig, type AggregateConfigType, type AggregateFn, type AggregateMetric, type AggregateSchemaNode, groupKeyName, } from "./catalog/general/aggregate/config";
|
|
41
41
|
export { detectRecordFields, resolveRecordSchema, type RecordSchemaLike, } from "./catalog/logic/for-each/recordSchema";
|
|
42
42
|
export { STORAGE_CONNECTOR_IDS, type StorageExtraField, type StoragePathField, getStorageProvider, storageConfigKeys, } from "./catalog/storage/storageCapabilities";
|
package/dist/index.js
CHANGED
|
@@ -3613,7 +3613,16 @@ var TransformConfig = {
|
|
|
3613
3613
|
options: TRANSFORM_MODES,
|
|
3614
3614
|
description: "How the mappings are authored: visual (the Field Mapper — the only mode the editor offers) or expression (legacy JavaScript). This is not the write mode; that is `operation`."
|
|
3615
3615
|
},
|
|
3616
|
-
mappings: {
|
|
3616
|
+
mappings: {
|
|
3617
|
+
type: "array",
|
|
3618
|
+
required: false,
|
|
3619
|
+
description: "Field mappings: [{ id, sourceField, targetField, targetType, transform? }]. sourceField is a token like {{orders[].email}}; " + "an index picks one list element ({{products[].variants[0].price}}). With groupBy, set lineField: true on the mappings that make each line."
|
|
3620
|
+
},
|
|
3621
|
+
groupBy: {
|
|
3622
|
+
type: "json",
|
|
3623
|
+
required: false,
|
|
3624
|
+
description: 'One record per key, with line items: { "key": "{{orders[].number}}", "into": "line_items" }. Rows whose key is the same become ONE record ' + "(its fields from the first row); mappings with lineField: true become a list of lines under `into` (Shopify line_items, QuickBooks Line, Odoo order_line). " + "Dotted line fields nest inside each line (SalesItemLineDetail.ItemRef.value)."
|
|
3625
|
+
},
|
|
3617
3626
|
expression: { type: "code", required: false }
|
|
3618
3627
|
},
|
|
3619
3628
|
generateName: (operation, connectorLabel, objectName) => {
|
|
@@ -3654,6 +3663,16 @@ var TransformConfig = {
|
|
|
3654
3663
|
});
|
|
3655
3664
|
}
|
|
3656
3665
|
}
|
|
3666
|
+
const groupBy = config.groupBy;
|
|
3667
|
+
if (groupBy && (groupBy.key || groupBy.into)) {
|
|
3668
|
+
if (!groupBy.key)
|
|
3669
|
+
errors.push("One record per key: choose the key field (groupBy.key)");
|
|
3670
|
+
if (!groupBy.into)
|
|
3671
|
+
errors.push("One record per key: name the field that holds the lines (groupBy.into)");
|
|
3672
|
+
if (groupBy.key && groupBy.into && !(config.mappings ?? []).some((m) => m.lineField)) {
|
|
3673
|
+
errors.push("One record per key: mark at least one mapping as a line field (lineField: true)");
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3657
3676
|
return { valid: errors.length === 0, errors };
|
|
3658
3677
|
},
|
|
3659
3678
|
merge: (userConfig) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octaviaflow/flow-rules",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "The flow action catalog and the rules engine behind Flow Doctor — one definition of what a step accepts and what makes a flow valid, shared by the editor and the server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|