@workbench-kit/field-remap 0.0.2-prototype.0.2.30 → 0.0.2-prototype.0.2.31

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workbench-kit/field-remap",
3
- "version": "0.0.2-prototype.0.2.30",
3
+ "version": "0.0.2-prototype.0.2.31",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -16,8 +16,13 @@ import type {
16
16
  ValueTransformRegistry,
17
17
  } from '../types.js';
18
18
  import { applyTransformChain } from '../../registry/createValueTransformRegistry.js';
19
- import { findSourceField, findTargetSlot } from './resolveMappedValue.js';
20
- import { isPlainObject, readObjectPath, writeObjectPath } from './pathUtils.js';
19
+ import {
20
+ findSourceField,
21
+ findTargetSlot,
22
+ readSourceFieldValue,
23
+ resolveTargetSlotOutputPath,
24
+ } from './resolveMappedValue.js';
25
+ import { isPlainObject, writeObjectPath } from './pathUtils.js';
21
26
 
22
27
  /** Max inputs on a combine operator. */
23
28
  export const MAX_MAPPING_FAN_IN = 8;
@@ -68,45 +73,6 @@ function leafKey(field: {
68
73
  return idParts[idParts.length - 1] ?? field.label;
69
74
  }
70
75
 
71
- function outputPathForTarget(slot: TargetSlot): string {
72
- const path = slot.path?.trim();
73
- if (path) {
74
- return path;
75
- }
76
- const id = slot.id.trim();
77
- if (id.includes('.')) {
78
- const parts = id.split('.').filter(Boolean);
79
- if (parts.length >= 2) {
80
- return parts.slice(1).join('.');
81
- }
82
- }
83
- return slot.label.trim() || id;
84
- }
85
-
86
- function readFieldValue(field: SourceField, inputs: Readonly<Record<string, unknown>>): unknown {
87
- const shapeId = field.shapeId?.trim();
88
- const bag =
89
- shapeId && Object.prototype.hasOwnProperty.call(inputs, shapeId)
90
- ? inputs[shapeId]
91
- : Object.keys(inputs).length === 1
92
- ? inputs[Object.keys(inputs)[0]!]
93
- : inputs;
94
-
95
- const path = field.path?.trim();
96
- if (path) {
97
- if (shapeId && Object.prototype.hasOwnProperty.call(inputs, shapeId)) {
98
- return readObjectPath(bag, path);
99
- }
100
- const fromBag = readObjectPath(bag, path);
101
- if (fromBag !== undefined) {
102
- return fromBag;
103
- }
104
- return readObjectPath(inputs, path);
105
- }
106
-
107
- return field.sampleValue;
108
- }
109
-
110
76
  function sanitizeOperatorTransformIds(ids: readonly string[] | undefined): string[] | undefined {
111
77
  const cleaned = ids
112
78
  ?.map((id) => id.trim())
@@ -234,7 +200,7 @@ export async function applyMappingOperators(
234
200
  if (!field) {
235
201
  throw new MappingOperatorError(operator.id, `Unknown source field "${fieldId}".`);
236
202
  }
237
- bag[leafKey(field)] = readFieldValue(field, input.inputs);
203
+ bag[leafKey(field)] = readSourceFieldValue(field, input.inputs);
238
204
  }
239
205
 
240
206
  const target = findTargetSlot(input.targets, operator.outputSlotId);
@@ -251,7 +217,7 @@ export async function applyMappingOperators(
251
217
  bag,
252
218
  context,
253
219
  );
254
- output = writeObjectPath(output, outputPathForTarget(target), value);
220
+ output = writeObjectPath(output, resolveTargetSlotOutputPath(target), value);
255
221
  continue;
256
222
  }
257
223
 
@@ -264,7 +230,7 @@ export async function applyMappingOperators(
264
230
  );
265
231
  }
266
232
 
267
- let current = readFieldValue(source, input.inputs);
233
+ let current = readSourceFieldValue(source, input.inputs);
268
234
  current = await applyTransformChain(
269
235
  input.transforms,
270
236
  operator.transformIds ?? [],
@@ -285,7 +251,7 @@ export async function applyMappingOperators(
285
251
  throw new MappingOperatorError(operator.id, `Unknown target slot "${slotId}".`);
286
252
  }
287
253
  const key = leafKey(target);
288
- output = writeObjectPath(output, outputPathForTarget(target), current[key]);
254
+ output = writeObjectPath(output, resolveTargetSlotOutputPath(target), current[key]);
289
255
  }
290
256
  }
291
257
 
@@ -1,11 +1,12 @@
1
1
  import type {
2
2
  MappingEdge,
3
3
  SourceField,
4
+ TargetSlot,
4
5
  TransformContext,
5
6
  ValueTransformRegistry,
6
7
  } from '../types.js';
7
8
  import { edgeItemTransformIds, edgeTransformIds } from '../document/mappingEdge.js';
8
- import { projectCollectionItems } from './pathUtils.js';
9
+ import { projectCollectionItems, readObjectPath } from './pathUtils.js';
9
10
  import { applyTransformChain } from '../../registry/createValueTransformRegistry.js';
10
11
  import { BUILTIN_TRANSFORM_IDS } from '../../registry/builtinTransforms.js';
11
12
  import { resolveOptionSteps } from './transformOptions.js';
@@ -22,6 +23,44 @@ export function findSourceField(
22
23
  return flattenSourceFields(fields).find((field) => field.id === fieldId);
23
24
  }
24
25
 
26
+ export function readSourceFieldValue(
27
+ field: SourceField,
28
+ inputs: Readonly<Record<string, unknown>>,
29
+ ): unknown {
30
+ const shapeId = field.shapeId?.trim();
31
+ const bag =
32
+ shapeId && Object.prototype.hasOwnProperty.call(inputs, shapeId)
33
+ ? inputs[shapeId]
34
+ : Object.keys(inputs).length === 1
35
+ ? inputs[Object.keys(inputs)[0]!]
36
+ : inputs;
37
+
38
+ const path = field.path?.trim();
39
+ if (!path) {
40
+ return field.sampleValue;
41
+ }
42
+ if (shapeId && Object.prototype.hasOwnProperty.call(inputs, shapeId)) {
43
+ return readObjectPath(bag, path);
44
+ }
45
+ const fromBag = readObjectPath(bag, path);
46
+ return fromBag === undefined ? readObjectPath(inputs, path) : fromBag;
47
+ }
48
+
49
+ export function resolveTargetSlotOutputPath(slot: TargetSlot): string {
50
+ const path = slot.path?.trim();
51
+ if (path) {
52
+ return path;
53
+ }
54
+ const id = slot.id.trim();
55
+ if (id.includes('.')) {
56
+ const parts = id.split('.').filter(Boolean);
57
+ if (parts.length >= 2) {
58
+ return parts.slice(1).join('.');
59
+ }
60
+ }
61
+ return slot.label.trim() || id;
62
+ }
63
+
25
64
  /**
26
65
  * Resolve an edge against a live / sample source value.
27
66
  *
@@ -7,15 +7,15 @@ import {
7
7
  type DataShapeRegistry,
8
8
  } from './dataShape.js';
9
9
  import { convertArrayWithItemEdges } from '../mapping/convertItemEdges.js';
10
- import { isPlainObject, readObjectPath, writeObjectPath } from '../mapping/pathUtils.js';
11
- import { findSourceField, resolveMappedValue } from '../mapping/resolveMappedValue.js';
10
+ import { isPlainObject, writeObjectPath } from '../mapping/pathUtils.js';
11
+ import {
12
+ findSourceField,
13
+ readSourceFieldValue,
14
+ resolveMappedValue,
15
+ resolveTargetSlotOutputPath,
16
+ } from '../mapping/resolveMappedValue.js';
12
17
  import { findTargetSlot, flattenTargetSlots } from '../mapping/treeUtils.js';
13
- import type {
14
- SourceField,
15
- TargetSlot,
16
- TransformContext,
17
- ValueTransformRegistry,
18
- } from '../types.js';
18
+ import type { TransformContext, ValueTransformRegistry } from '../types.js';
19
19
 
20
20
  export interface ConvertToShapeInput {
21
21
  readonly conversion: ConversionDefinition;
@@ -66,54 +66,6 @@ function resolveShape(
66
66
  return shapes.find((shape) => shape.id === id);
67
67
  }
68
68
 
69
- function outputPathForTarget(slot: TargetSlot): string {
70
- const path = slot.path?.trim();
71
- if (path) {
72
- return path;
73
- }
74
- // Prefer last id segment when hosts use dotted ids (`slot.display.timeText`).
75
- const id = slot.id.trim();
76
- if (id.includes('.')) {
77
- const parts = id.split('.').filter(Boolean);
78
- // Drop a leading registry prefix like `slot` when present with 3+ segments.
79
- if (parts.length >= 3 && (parts[0] === 'slot' || parts[0] === 'tgt')) {
80
- return parts.slice(1).join('.');
81
- }
82
- if (parts.length >= 2) {
83
- return parts.slice(1).join('.');
84
- }
85
- }
86
- return slot.label.trim() || id;
87
- }
88
-
89
- function readFieldValue(field: SourceField, inputs: Readonly<Record<string, unknown>>): unknown {
90
- const shapeId = field.shapeId?.trim();
91
- const bag =
92
- shapeId && Object.prototype.hasOwnProperty.call(inputs, shapeId)
93
- ? inputs[shapeId]
94
- : // Single-bag fallback: use the only input, or the whole inputs record.
95
- Object.keys(inputs).length === 1
96
- ? inputs[Object.keys(inputs)[0]!]
97
- : inputs;
98
-
99
- const path = field.path?.trim();
100
- if (path) {
101
- // When bags are per-shape, paths are relative to that bag.
102
- // When falling back to the whole inputs record, absolute paths still work.
103
- if (shapeId && Object.prototype.hasOwnProperty.call(inputs, shapeId)) {
104
- return readObjectPath(bag, path);
105
- }
106
- const fromBag = readObjectPath(bag, path);
107
- if (fromBag !== undefined) {
108
- return fromBag;
109
- }
110
- // Absolute path into combined inputs (e.g. `order.totalCents`).
111
- return readObjectPath(inputs, path);
112
- }
113
-
114
- return field.sampleValue;
115
- }
116
-
117
69
  /**
118
70
  * Apply a conversion to named input bags and build target-shaped JSON.
119
71
  *
@@ -170,7 +122,7 @@ export async function convertToShape(input: ConvertToShapeInput): Promise<Conver
170
122
  continue;
171
123
  }
172
124
 
173
- const sourceValue = readFieldValue(sourceField, input.inputs);
125
+ const sourceValue = readSourceFieldValue(sourceField, input.inputs);
174
126
  const value =
175
127
  edge.itemEdges && edge.itemEdges.length > 0
176
128
  ? await convertArrayWithItemEdges({
@@ -191,7 +143,7 @@ export async function convertToShape(input: ConvertToShapeInput): Promise<Conver
191
143
  : undefined,
192
144
  });
193
145
 
194
- const path = outputPathForTarget(targetSlot);
146
+ const path = resolveTargetSlotOutputPath(targetSlot);
195
147
  output = writeObjectPath(output, path, value);
196
148
  slots.push({
197
149
  edgeId: edge.id,