@workbench-kit/field-remap 0.0.2-prototype.0.2.27 → 0.0.2-prototype.0.2.28

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
@@ -60,9 +60,10 @@ a lighter mapping detail rail (chain overview, palette, list context).
60
60
 
61
61
  ### Shape ownership
62
62
 
63
- `FieldRemapDocument` (v1) stores **edges only**. Hosts own input/output shapes
64
- (`SourceField[]` / `TargetSlot[]`, or `defineDataShape` + ingest helpers) and pass
65
- them into `convertToShape` / the shell `FieldRemapPanel` / `FieldRemapFlowMapper`.
63
+ `FieldRemapDocument` stores edges plus optional combine/split operators. Hosts own
64
+ input/output shapes (`SourceField[]` / `TargetSlot[]`, or `defineDataShape` + ingest
65
+ helpers) and pass them into `convertToShape` / the shell `FieldRemapPanel` /
66
+ `FieldRemapFlowMapper`.
66
67
  Optional `classRef` / `hidden` on fields and slots are additive; use
67
68
  `projectShapes` / `projectSourceFields` / `projectTargetSlots` with
68
69
  `includeHidden` (default omit hidden) before wiring Flow columns, and
@@ -119,7 +120,7 @@ build `defineConversion` / `defineDataShape` registries yourself.
119
120
  Place-then-wire uses **ephemeral draft nodes** in the shell Flow UI: place a
120
121
  transform, wire source then target (or the reverse), and the draft finalizes into
121
122
  a `MappingEdge` with `transformIds: [id]`. Escape discards unfinished drafts.
122
- The persisted document stays edges-only — no free graph. You can also add steps
123
+ The persisted document stays mapping-only — no free graph nodes. You can also add steps
123
124
  via the detail palette / `+ node` onto an existing binding (max 3). List context
124
125
  uses `itemEdges` on array→array bindings.
125
126
 
@@ -135,13 +136,13 @@ uses `itemEdges` on array→array bindings.
135
136
 
136
137
  ### n→m operators (combine / split)
137
138
 
138
- `FieldRemapDocument` **v1** is edges-only (1→1 bindings). **v2** (current) adds an
139
- optional `operators[]` list for fan-in / fan-out. Call `applyMappingOperators` with
139
+ `FieldRemapDocument` v2 includes an optional `operators[]` list for fan-in / fan-out.
140
+ Call `applyMappingOperators` with
140
141
  `combine` / `split` operators (limits: `MAX_MAPPING_FAN_IN` / `MAX_MAPPING_FAN_OUT`
141
142
  = 8). Hosts may merge the result with `convertToShape` output.
142
- `migrateFieldRemapDocument` / `parseFieldRemapDocument` accept v1 and v2 and always
143
- emit the current version. Shell Flow renders combine/split as multi-port nodes and
144
- supports authoring (create / wire ports / delete) when hosts pass `operators` +
143
+ `parseFieldRemapDocument` accepts the current version and normalizes edges and operators.
144
+ Shell Flow renders combine/split as multi-port nodes and supports authoring
145
+ (create / wire ports / delete) when hosts pass `operators` +
145
146
  `onOperatorsChange` into `FieldRemapFlowMapper` (sample `nm-combine-split`).
146
147
 
147
148
  ```ts
@@ -269,8 +270,8 @@ Pass `signal` on `convertToShape` (or `TransformContext.signal`) to cancel stale
269
270
  Aborted runs reject with `AbortError` and stop further edges / chain steps. The shell Field Remap
270
271
  panel wires an `AbortController` to effect cleanup.
271
272
 
272
- Host JSONata transforms in `@workbench-kit/shell-react` are bounded by default (`timeoutMs`,
273
- `maxExpressionLength`, `onError: 'throw'`). Use `createJsonataValueTransform()` to override.
273
+ Host JSONata transforms in `@workbench-kit/shell-react` are fail-closed and bounded by default
274
+ (`timeoutMs`, `maxExpressionLength`). Use `createJsonataValueTransform()` to override the bounds.
274
275
 
275
276
  ## Layout
276
277
 
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.27",
3
+ "version": "0.0.2-prototype.0.2.28",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -3,12 +3,3 @@ export const MAX_TRANSFORM_CHAIN = 3;
3
3
 
4
4
  /** Built-in pass-through transform id (kept here to avoid import cycles). */
5
5
  export const IDENTITY_TRANSFORM_ID = 'identity';
6
-
7
- /** Legacy id aliases → canonical ids (empty until hosts need migration). */
8
- export const TRANSFORM_ID_ALIASES: Readonly<Record<string, string>> = {};
9
-
10
- /** Map a legacy or canonical transform id to its canonical form. */
11
- export function canonicalizeTransformId(id: string): string {
12
- const trimmed = id.trim();
13
- return TRANSFORM_ID_ALIASES[trimmed] ?? trimmed;
14
- }
@@ -4,20 +4,15 @@ import type { MappingEdge, MappingOperator, FieldRemapDocument } from '../types.
4
4
 
5
5
  /** Current persistence version (edges + optional `operators[]`). */
6
6
  export const FIELD_REMAP_DOCUMENT_VERSION = 2 as const;
7
- /** Legacy edges-only documents. */
8
- export const FIELD_REMAP_DOCUMENT_V1_VERSION = 1 as const;
9
7
 
10
- type SupportedDocumentVersion =
11
- typeof FIELD_REMAP_DOCUMENT_VERSION | typeof FIELD_REMAP_DOCUMENT_V1_VERSION;
12
-
13
- /** Thrown when parse/deserialize sees a document `version` other than a supported constant. */
8
+ /** Thrown when parse/deserialize sees a document `version` other than the current constant. */
14
9
  export class UnsupportedFieldRemapDocumentVersionError extends Error {
15
10
  readonly version: unknown;
16
11
  readonly expectedVersion: typeof FIELD_REMAP_DOCUMENT_VERSION;
17
12
 
18
13
  constructor(version: unknown) {
19
14
  super(
20
- `Unsupported field remap document version ${String(version)}; expected ${FIELD_REMAP_DOCUMENT_V1_VERSION} or ${FIELD_REMAP_DOCUMENT_VERSION}.`,
15
+ `Unsupported field remap document version ${String(version)}; expected ${FIELD_REMAP_DOCUMENT_VERSION}.`,
21
16
  );
22
17
  this.name = 'UnsupportedFieldRemapDocumentVersionError';
23
18
  this.version = version;
@@ -50,13 +45,9 @@ export function createFieldRemapDocument(
50
45
  };
51
46
  }
52
47
 
53
- function isSupportedVersion(version: unknown): version is SupportedDocumentVersion {
54
- return version === FIELD_REMAP_DOCUMENT_V1_VERSION || version === FIELD_REMAP_DOCUMENT_VERSION;
55
- }
56
-
57
- /** Normalize edges / operators on a persisted document; always emits the current version. */
48
+ /** Normalize edges / operators on a current persisted document. */
58
49
  export function normalizeFieldRemapDocument(document: FieldRemapDocument): FieldRemapDocument {
59
- if (!isSupportedVersion(document.version)) {
50
+ if (document.version !== FIELD_REMAP_DOCUMENT_VERSION) {
60
51
  throw new UnsupportedFieldRemapDocumentVersionError(document.version);
61
52
  }
62
53
  const operators = normalizeMappingOperators(document.operators);
@@ -83,8 +74,7 @@ export function serializeFieldRemapDocument(
83
74
  }
84
75
 
85
76
  /**
86
- * Parse an unknown JSON value into a normalized `FieldRemapDocument`.
87
- * Accepts v1 (edges-only) and v2 (optional operators); always returns current version.
77
+ * Parse an unknown JSON value into a normalized current `FieldRemapDocument`.
88
78
  */
89
79
  export function parseFieldRemapDocument(input: unknown): FieldRemapDocument {
90
80
  if (!input || typeof input !== 'object' || Array.isArray(input)) {
@@ -97,7 +87,7 @@ export function parseFieldRemapDocument(input: unknown): FieldRemapDocument {
97
87
  if (!('version' in record)) {
98
88
  throw new InvalidFieldRemapDocumentError('Field remap document is missing version.');
99
89
  }
100
- if (!isSupportedVersion(record.version)) {
90
+ if (record.version !== FIELD_REMAP_DOCUMENT_VERSION) {
101
91
  throw new UnsupportedFieldRemapDocumentVersionError(record.version);
102
92
  }
103
93
  if (!Array.isArray(record.edges)) {
@@ -114,7 +104,7 @@ export function parseFieldRemapDocument(input: unknown): FieldRemapDocument {
114
104
  }
115
105
 
116
106
  return normalizeFieldRemapDocument({
117
- version: record.version,
107
+ version: FIELD_REMAP_DOCUMENT_VERSION,
118
108
  edges: record.edges as MappingEdge[],
119
109
  operators: record.operators as MappingOperator[] | undefined,
120
110
  });
@@ -131,33 +121,3 @@ export function deserializeFieldRemapDocument(json: string): FieldRemapDocument
131
121
  }
132
122
  return parseFieldRemapDocument(parsed);
133
123
  }
134
-
135
- /**
136
- * Migrate an unknown persisted value to the current {@link FieldRemapDocument}.
137
- *
138
- * Hosts should call this (or `parseFieldRemapDocument`) at load time so future
139
- * document versions can be rewritten here without changing call sites.
140
- *
141
- * **v1:** edges-only → current version (operators omitted).
142
- * **v2:** normalize edges + operators.
143
- */
144
- export function migrateFieldRemapDocument(input: unknown): FieldRemapDocument {
145
- if (!input || typeof input !== 'object' || Array.isArray(input)) {
146
- throw new InvalidFieldRemapDocumentError(
147
- 'Expected a field remap document object with version and edges.',
148
- );
149
- }
150
-
151
- const record = input as Record<string, unknown>;
152
- if (!('version' in record)) {
153
- throw new InvalidFieldRemapDocumentError('Field remap document is missing version.');
154
- }
155
-
156
- switch (record.version) {
157
- case FIELD_REMAP_DOCUMENT_V1_VERSION:
158
- case FIELD_REMAP_DOCUMENT_VERSION:
159
- return parseFieldRemapDocument(input);
160
- default:
161
- throw new UnsupportedFieldRemapDocumentVersionError(record.version);
162
- }
163
- }
@@ -1,20 +1,12 @@
1
- import {
2
- canonicalizeTransformId,
3
- IDENTITY_TRANSFORM_ID,
4
- MAX_TRANSFORM_CHAIN,
5
- } from '../constants.js';
6
- import {
7
- sanitizeOptionRecord,
8
- sanitizeOptionSteps,
9
- sharedOptionsFromSteps,
10
- } from '../mapping/transformOptions.js';
1
+ import { IDENTITY_TRANSFORM_ID, MAX_TRANSFORM_CHAIN } from '../constants.js';
2
+ import { sanitizeOptionSteps } from '../mapping/transformOptions.js';
11
3
  import type { MappingEdge } from '../types.js';
12
4
 
13
5
  export { MAX_TRANSFORM_CHAIN } from '../constants.js';
14
6
 
15
7
  function sanitizeTransformIds(ids: readonly string[] | undefined): string[] {
16
8
  const cleaned = ids
17
- ?.map((id) => canonicalizeTransformId(id))
9
+ ?.map((id) => id.trim())
18
10
  .filter((id) => id.length > 0 && id !== IDENTITY_TRANSFORM_ID);
19
11
  if (!cleaned || cleaned.length === 0) {
20
12
  return [];
@@ -32,12 +24,7 @@ export function edgeItemTransformIds(edge: MappingEdge): string[] {
32
24
  return sanitizeTransformIds(edge.itemTransformIds);
33
25
  }
34
26
 
35
- /**
36
- * Option bags:
37
- * - Prefer `transformOptionSteps` when present (aligned to chain length).
38
- * - Keep `transformOptions` as the first non-empty step (or the legacy shared bag).
39
- * - Same rules for `itemTransformOptionSteps` / `itemTransformOptions`.
40
- */
27
+ /** Normalize transform chains and their aligned per-step option bags. */
41
28
  export function normalizeMappingEdge(edge: MappingEdge): MappingEdge {
42
29
  const ids = edgeTransformIds(edge);
43
30
  const itemIds = edgeItemTransformIds(edge);
@@ -52,16 +39,10 @@ export function normalizeMappingEdge(edge: MappingEdge): MappingEdge {
52
39
  : undefined;
53
40
 
54
41
  const transformOptionSteps = sanitizeOptionSteps(edge.transformOptionSteps, ids.length);
55
- const transformOptions =
56
- sharedOptionsFromSteps(transformOptionSteps) ?? sanitizeOptionRecord(edge.transformOptions);
57
-
58
42
  const itemTransformOptionSteps = sanitizeOptionSteps(
59
43
  edge.itemTransformOptionSteps,
60
44
  itemIds.length,
61
45
  );
62
- const itemTransformOptions =
63
- sharedOptionsFromSteps(itemTransformOptionSteps) ??
64
- sanitizeOptionRecord(edge.itemTransformOptions);
65
46
 
66
47
  return {
67
48
  id: edge.id,
@@ -69,11 +50,9 @@ export function normalizeMappingEdge(edge: MappingEdge): MappingEdge {
69
50
  targetSlotId: edge.targetSlotId,
70
51
  transformIds: ids.length > 0 ? ids : undefined,
71
52
  ...(transformOptionSteps ? { transformOptionSteps } : {}),
72
- ...(transformOptions ? { transformOptions } : {}),
73
53
  ...(itemSourcePath && !itemEdges ? { itemSourcePath } : {}),
74
54
  ...(itemIds.length > 0 && !itemEdges ? { itemTransformIds: itemIds } : {}),
75
55
  ...(itemTransformOptionSteps && !itemEdges ? { itemTransformOptionSteps } : {}),
76
- ...(itemTransformOptions && !itemEdges ? { itemTransformOptions } : {}),
77
56
  ...(itemEdges ? { itemEdges } : {}),
78
57
  };
79
58
  }
@@ -89,13 +68,11 @@ export function createMappingEdge(input: {
89
68
  readonly targetSlotId: string;
90
69
  readonly transformIds?: readonly string[];
91
70
  readonly transformOptionSteps?: readonly (Readonly<Record<string, unknown>> | undefined)[];
92
- readonly transformOptions?: Readonly<Record<string, unknown>>;
93
71
  /** Optional per-item projection path for array mappings. */
94
72
  readonly itemSourcePath?: string;
95
73
  /** Optional per-item transform chain after projection. */
96
74
  readonly itemTransformIds?: readonly string[];
97
75
  readonly itemTransformOptionSteps?: readonly (Readonly<Record<string, unknown>> | undefined)[];
98
- readonly itemTransformOptions?: Readonly<Record<string, unknown>>;
99
76
  /** List-context child edges for array-of-object → array-of-object. */
100
77
  readonly itemEdges?: readonly MappingEdge[];
101
78
  }): MappingEdge {
@@ -105,11 +82,9 @@ export function createMappingEdge(input: {
105
82
  targetSlotId: input.targetSlotId,
106
83
  transformIds: input.transformIds,
107
84
  transformOptionSteps: input.transformOptionSteps,
108
- transformOptions: input.transformOptions,
109
85
  itemSourcePath: input.itemSourcePath,
110
86
  itemTransformIds: input.itemTransformIds,
111
87
  itemTransformOptionSteps: input.itemTransformOptionSteps,
112
- itemTransformOptions: input.itemTransformOptions,
113
88
  itemEdges: input.itemEdges,
114
89
  });
115
90
  }
@@ -75,7 +75,7 @@ export async function convertArrayWithItemEdges(input: {
75
75
  ? await identity.apply(sourceValue, { ...input.context, sampleValue: sourceValue })
76
76
  : sourceValue;
77
77
  } else {
78
- const steps = resolveOptionSteps(chain, edge.transformOptionSteps, edge.transformOptions);
78
+ const steps = resolveOptionSteps(chain, edge.transformOptionSteps);
79
79
  value = await applyTransformChain(
80
80
  input.transforms,
81
81
  chain,
@@ -4,11 +4,7 @@
4
4
  * {@link applyMappingOperators} explicitly without persisting.
5
5
  */
6
6
 
7
- import {
8
- canonicalizeTransformId,
9
- IDENTITY_TRANSFORM_ID,
10
- MAX_TRANSFORM_CHAIN,
11
- } from '../constants.js';
7
+ import { IDENTITY_TRANSFORM_ID, MAX_TRANSFORM_CHAIN } from '../constants.js';
12
8
  import { throwIfAborted } from '../abort.js';
13
9
  import type {
14
10
  CombineMappingOperator,
@@ -113,7 +109,7 @@ function readFieldValue(field: SourceField, inputs: Readonly<Record<string, unkn
113
109
 
114
110
  function sanitizeOperatorTransformIds(ids: readonly string[] | undefined): string[] | undefined {
115
111
  const cleaned = ids
116
- ?.map((id) => canonicalizeTransformId(id))
112
+ ?.map((id) => id.trim())
117
113
  .filter((id) => id.length > 0 && id !== IDENTITY_TRANSFORM_ID);
118
114
  if (!cleaned || cleaned.length === 0) {
119
115
  return undefined;
@@ -30,8 +30,7 @@ export function findSourceField(
30
30
  * 2. Optional `itemTransformIds` per element (when the value is still an array)
31
31
  * 3. `transformIds` on the whole value (including array reduces)
32
32
  *
33
- * Per-step options (`transformOptionSteps` / `itemTransformOptionSteps`) win when
34
- * present; otherwise shared `transformOptions` / `itemTransformOptions` apply to all steps.
33
+ * Per-step options are aligned through `transformOptionSteps` / `itemTransformOptionSteps`.
35
34
  */
36
35
  export async function resolveMappedValue(
37
36
  edge: MappingEdge,
@@ -44,11 +43,7 @@ export async function resolveMappedValue(
44
43
  : sourceValue;
45
44
 
46
45
  const itemChain = edgeItemTransformIds(edge);
47
- const itemSteps = resolveOptionSteps(
48
- itemChain,
49
- edge.itemTransformOptionSteps,
50
- edge.itemTransformOptions,
51
- );
46
+ const itemSteps = resolveOptionSteps(itemChain, edge.itemTransformOptionSteps);
52
47
 
53
48
  if (itemChain.length > 0 && Array.isArray(current)) {
54
49
  current = await Promise.all(
@@ -62,7 +57,7 @@ export async function resolveMappedValue(
62
57
  return identity ? await identity.apply(current, context) : current;
63
58
  }
64
59
 
65
- const valueSteps = resolveOptionSteps(chain, edge.transformOptionSteps, edge.transformOptions);
60
+ const valueSteps = resolveOptionSteps(chain, edge.transformOptionSteps);
66
61
  return applyTransformChain(registry, chain, current, context, valueSteps);
67
62
  }
68
63
 
@@ -1,39 +1,4 @@
1
- import type { TransformContext, TransformOptionField, ValueTransformRegistry } from '../types.js';
2
-
3
- /** Merge edge-local options over host `context.options` (edge wins). */
4
- export function contextWithEdgeOptions(
5
- context: TransformContext,
6
- edgeOptions: Readonly<Record<string, unknown>> | undefined,
7
- ): TransformContext {
8
- if (!edgeOptions || Object.keys(edgeOptions).length === 0) {
9
- return context;
10
- }
11
- return {
12
- ...context,
13
- options: {
14
- ...context.options,
15
- ...edgeOptions,
16
- },
17
- };
18
- }
19
-
20
- /** Collect unique `optionFields` declared by transforms in a chain (later ids win per key). */
21
- export function collectOptionFields(
22
- registry: ValueTransformRegistry,
23
- transformIds: readonly string[],
24
- ): TransformOptionField[] {
25
- const byKey = new Map<string, TransformOptionField>();
26
- for (const id of transformIds) {
27
- const fields = registry.get(id)?.optionFields;
28
- if (!fields) {
29
- continue;
30
- }
31
- for (const field of fields) {
32
- byKey.set(field.key, field);
33
- }
34
- }
35
- return [...byKey.values()];
36
- }
1
+ import type { TransformOptionField, ValueTransformRegistry } from '../types.js';
37
2
 
38
3
  /** Option fields for a single chain step. */
39
4
  export function optionFieldsForStep(
@@ -63,17 +28,6 @@ export function sanitizeOptionRecord(
63
28
  return Object.keys(next).length > 0 ? next : undefined;
64
29
  }
65
30
 
66
- export function patchOptionRecord(
67
- previous: Readonly<Record<string, unknown>> | undefined,
68
- key: string,
69
- value: unknown,
70
- ): Readonly<Record<string, unknown>> | undefined {
71
- return sanitizeOptionRecord({
72
- ...previous,
73
- [key]: value,
74
- });
75
- }
76
-
77
31
  /**
78
32
  * Align / sanitize per-step option bags to `length`.
79
33
  * Returns `undefined` when every step is empty.
@@ -97,79 +51,16 @@ export function sanitizeOptionSteps(
97
51
  return any ? next : undefined;
98
52
  }
99
53
 
100
- /**
101
- * Resolve per-step options for a transform chain.
102
- * Prefers `steps`; otherwise expands shared `transformOptions` to every step (apply-to-all).
103
- */
54
+ /** Resolve sanitized per-step options aligned to a transform chain. */
104
55
  export function resolveOptionSteps(
105
56
  transformIds: readonly string[],
106
57
  steps: readonly (Readonly<Record<string, unknown>> | undefined)[] | undefined,
107
- shared: Readonly<Record<string, unknown>> | undefined,
108
58
  ): (Readonly<Record<string, unknown>> | undefined)[] {
109
59
  const length = transformIds.length;
110
60
  if (length === 0) {
111
61
  return [];
112
62
  }
113
- if (steps && steps.length > 0) {
114
- return Array.from({ length }, (_, index) => sanitizeOptionRecord(steps[index]));
115
- }
116
- const bag = sanitizeOptionRecord(shared);
117
- if (!bag) {
118
- return Array.from({ length }, () => undefined);
119
- }
120
- return Array.from({ length }, () => bag);
121
- }
122
-
123
- /** Back-compat summary: first non-empty step bag (else undefined). */
124
- export function sharedOptionsFromSteps(
125
- steps: readonly (Readonly<Record<string, unknown>> | undefined)[] | undefined,
126
- ): Readonly<Record<string, unknown>> | undefined {
127
- if (!steps) {
128
- return undefined;
129
- }
130
- for (const step of steps) {
131
- const sanitized = sanitizeOptionRecord(step);
132
- if (sanitized) {
133
- return sanitized;
134
- }
135
- }
136
- return undefined;
137
- }
138
-
139
- /** Merge all step bags (later steps win) — useful for live format-sample chips. */
140
- export function mergeOptionSteps(
141
- steps: readonly (Readonly<Record<string, unknown>> | undefined)[] | undefined,
142
- ): Readonly<Record<string, unknown>> | undefined {
143
- if (!steps || steps.length === 0) {
144
- return undefined;
145
- }
146
- const merged: Record<string, unknown> = {};
147
- for (const step of steps) {
148
- if (!step) {
149
- continue;
150
- }
151
- Object.assign(merged, step);
152
- }
153
- return sanitizeOptionRecord(merged);
154
- }
155
-
156
- export function patchOptionStep(
157
- steps: readonly (Readonly<Record<string, unknown>> | undefined)[] | undefined,
158
- length: number,
159
- index: number,
160
- key: string,
161
- value: unknown,
162
- sharedFallback?: Readonly<Record<string, unknown>>,
163
- ): readonly (Readonly<Record<string, unknown>> | undefined)[] | undefined {
164
- const base = resolveOptionSteps(
165
- Array.from({ length }, () => ''),
166
- steps,
167
- sharedFallback,
168
- );
169
- const next = base.map((step, stepIndex) =>
170
- stepIndex === index ? patchOptionRecord(step, key, value) : step,
171
- );
172
- return sanitizeOptionSteps(next, length);
63
+ return Array.from({ length }, (_, index) => sanitizeOptionRecord(steps?.[index]));
173
64
  }
174
65
 
175
66
  export function resizeOptionSteps(
@@ -87,15 +87,9 @@ export interface MappingEdge {
87
87
  readonly transformIds?: readonly string[];
88
88
  /**
89
89
  * Per-step options aligned with `transformIds` (index N applies to step N).
90
- * Prefer this when steps need different bags (e.g. `showSeconds` then `maxLength`).
90
+ * Steps may use different bags (e.g. `showSeconds` then `maxLength`).
91
91
  */
92
92
  readonly transformOptionSteps?: readonly (Readonly<Record<string, unknown>> | undefined)[];
93
- /**
94
- * Shared options for all `transformIds` steps (legacy / apply-to-all).
95
- * Used when `transformOptionSteps` is omitted. Still written as a back-compat
96
- * summary of step 0 (or the first non-empty step) by `normalizeMappingEdge`.
97
- */
98
- readonly transformOptions?: Readonly<Record<string, unknown>>;
99
93
  /**
100
94
  * When the source is an array of objects, optional dotted path into each item
101
95
  * (e.g. `name` or `meta.label`) before the value is written to the target.
@@ -113,11 +107,6 @@ export interface MappingEdge {
113
107
  * Per-step options aligned with `itemTransformIds`.
114
108
  */
115
109
  readonly itemTransformOptionSteps?: readonly (Readonly<Record<string, unknown>> | undefined)[];
116
- /**
117
- * Shared options for all `itemTransformIds` steps (legacy / apply-to-all).
118
- * Independent of `transformOptions` / `transformOptionSteps`.
119
- */
120
- readonly itemTransformOptions?: Readonly<Record<string, unknown>>;
121
110
  /**
122
111
  * List-context child bindings (Stedi-style): when source is an array of objects,
123
112
  * each element is converted through these edges into a target item object.
@@ -154,16 +143,14 @@ export type MappingOperator = CombineMappingOperator | SplitMappingOperator;
154
143
 
155
144
  /**
156
145
  * Minimal JSON-serializable mapping document for host persistence.
157
- * Hosts own schema trees; this document stores the binding graph (and optional
158
- * n→m operators from document v2 onward).
146
+ * Hosts own schema trees; this document stores the binding graph and optional n→m operators.
159
147
  */
160
148
  export interface FieldRemapDocument {
161
- /** `1` = edges-only; `2` = edges + optional `operators[]`. */
162
- readonly version: 1 | 2;
149
+ readonly version: 2;
163
150
  readonly edges: readonly MappingEdge[];
164
151
  /**
165
- * Optional n→m combine/split operators (document v2).
166
- * Omitted / empty on v1 documents and on v2 hosts that only use 1→1 edges.
152
+ * Optional n→m combine/split operators.
153
+ * Omitted / empty on hosts that only use 1→1 edges.
167
154
  */
168
155
  readonly operators?: readonly MappingOperator[];
169
156
  }
@@ -216,8 +203,7 @@ export interface ValueTransformDefinition {
216
203
  /**
217
204
  * Data-driven option editors (mapped rows / convert panel).
218
205
  * Values are stored per step (`transformOptionSteps` / `itemTransformOptionSteps`)
219
- * or as a shared bag (`transformOptions` / `itemTransformOptions`), or on host
220
- * `TransformContext.options`.
206
+ * or on host `TransformContext.options`.
221
207
  */
222
208
  readonly optionFields?: readonly TransformOptionField[];
223
209
  }
package/src/index.ts CHANGED
@@ -15,12 +15,7 @@ export type {
15
15
  ValueTransformRegistry,
16
16
  } from './domain/types.js';
17
17
 
18
- export {
19
- canonicalizeTransformId,
20
- IDENTITY_TRANSFORM_ID,
21
- MAX_TRANSFORM_CHAIN,
22
- TRANSFORM_ID_ALIASES,
23
- } from './domain/constants.js';
18
+ export { IDENTITY_TRANSFORM_ID, MAX_TRANSFORM_CHAIN } from './domain/constants.js';
24
19
 
25
20
  export {
26
21
  createMappingEdge,
@@ -34,11 +29,9 @@ export {
34
29
  createFieldRemapDocument,
35
30
  deserializeFieldRemapDocument,
36
31
  InvalidFieldRemapDocumentError,
37
- migrateFieldRemapDocument,
38
32
  normalizeFieldRemapDocument,
39
33
  parseFieldRemapDocument,
40
34
  FIELD_REMAP_DOCUMENT_VERSION,
41
- FIELD_REMAP_DOCUMENT_V1_VERSION,
42
35
  serializeFieldRemapDocument,
43
36
  UnsupportedFieldRemapDocumentVersionError,
44
37
  } from './domain/document/fieldRemapDocument.js';
@@ -93,17 +86,11 @@ export type {
93
86
  } from './domain/mapping/mappingOperators.js';
94
87
 
95
88
  export {
96
- collectOptionFields,
97
- contextWithEdgeOptions,
98
- mergeOptionSteps,
99
89
  optionFieldsForStep,
100
- patchOptionRecord,
101
- patchOptionStep,
102
90
  resolveOptionSteps,
103
91
  resizeOptionSteps,
104
92
  sanitizeOptionRecord,
105
93
  sanitizeOptionSteps,
106
- sharedOptionsFromSteps,
107
94
  } from './domain/mapping/transformOptions.js';
108
95
 
109
96
  export {
@@ -1,5 +1,5 @@
1
1
  import { throwIfAborted } from '../domain/abort.js';
2
- import { canonicalizeTransformId, MAX_TRANSFORM_CHAIN } from '../domain/constants.js';
2
+ import { MAX_TRANSFORM_CHAIN } from '../domain/constants.js';
3
3
  import type {
4
4
  FieldDataType,
5
5
  TransformContext,
@@ -18,8 +18,7 @@ export function createValueTransformRegistry(
18
18
  }
19
19
 
20
20
  function resolve(id: string): ValueTransformDefinition | undefined {
21
- const canonical = canonicalizeTransformId(id);
22
- return byId.get(canonical) ?? byId.get(id);
21
+ return byId.get(id.trim()) ?? byId.get(id);
23
22
  }
24
23
 
25
24
  return {