@murumets-ee/imports 0.0.0-preview-20261014110621
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/LICENSE +94 -0
- package/dist/analyze/index.d.mts +265 -0
- package/dist/analyze/index.d.mts.map +1 -0
- package/dist/analyze/index.mjs +2 -0
- package/dist/analyze/index.mjs.map +1 -0
- package/dist/carmaker-feed-B-QYr3PI.mjs +2 -0
- package/dist/carmaker-feed-B-QYr3PI.mjs.map +1 -0
- package/dist/carmaker-feed-CWrZLYUt.d.mts +59 -0
- package/dist/carmaker-feed-CWrZLYUt.d.mts.map +1 -0
- package/dist/cleanup-DDljBe0Z.mjs +2 -0
- package/dist/cleanup-DDljBe0Z.mjs.map +1 -0
- package/dist/engine-B0ExE4jL.mjs +2 -0
- package/dist/engine-B0ExE4jL.mjs.map +1 -0
- package/dist/engine-tkbUXKxB.d.mts +609 -0
- package/dist/engine-tkbUXKxB.d.mts.map +1 -0
- package/dist/index-Bm69N5DW.d.mts +97 -0
- package/dist/index-Bm69N5DW.d.mts.map +1 -0
- package/dist/index.d.mts +390 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/mapping/index.d.mts +42 -0
- package/dist/mapping/index.d.mts.map +1 -0
- package/dist/mapping/index.mjs +1 -0
- package/dist/mapping-transform-CO4MNhMe.mjs +2 -0
- package/dist/mapping-transform-CO4MNhMe.mjs.map +1 -0
- package/dist/matching/index.d.mts +2 -0
- package/dist/matching/index.mjs +1 -0
- package/dist/matching-Sr0z4HvN.mjs +2 -0
- package/dist/matching-Sr0z4HvN.mjs.map +1 -0
- package/dist/parts-schema-M1AtjNJt.d.mts +61 -0
- package/dist/parts-schema-M1AtjNJt.d.mts.map +1 -0
- package/dist/parts-schema-QqLci_Pl.mjs +2 -0
- package/dist/parts-schema-QqLci_Pl.mjs.map +1 -0
- package/dist/plugin.d.mts +148 -0
- package/dist/plugin.d.mts.map +1 -0
- package/dist/plugin.mjs +2 -0
- package/dist/plugin.mjs.map +1 -0
- package/dist/publish-DCXIPwTE.mjs +2 -0
- package/dist/publish-DCXIPwTE.mjs.map +1 -0
- package/dist/read-feed-DsLgRDNR.mjs +2 -0
- package/dist/read-feed-DsLgRDNR.mjs.map +1 -0
- package/dist/realtime/index.d.mts +123 -0
- package/dist/realtime/index.d.mts.map +1 -0
- package/dist/realtime/index.mjs +1 -0
- package/dist/rolldown-runtime-DK3Fl9T5.mjs +1 -0
- package/dist/runner-BnFvID1z.mjs +2 -0
- package/dist/runner-BnFvID1z.mjs.map +1 -0
- package/dist/schema-registry-DB5aIZMN.mjs +2 -0
- package/dist/schema-registry-DB5aIZMN.mjs.map +1 -0
- package/dist/storage-resolver.d.mts +32 -0
- package/dist/storage-resolver.d.mts.map +1 -0
- package/dist/storage-resolver.mjs +2 -0
- package/dist/storage-resolver.mjs.map +1 -0
- package/dist/storage.d.mts +31 -0
- package/dist/storage.d.mts.map +1 -0
- package/dist/storage.mjs +2 -0
- package/dist/storage.mjs.map +1 -0
- package/dist/transform-Cu5YEoOl.mjs +2 -0
- package/dist/transform-Cu5YEoOl.mjs.map +1 -0
- package/dist/transform-WeiiLdYP.d.mts +246 -0
- package/dist/transform-WeiiLdYP.d.mts.map +1 -0
- package/dist/transforms.d.mts +2 -0
- package/dist/transforms.mjs +1 -0
- package/dist/worker-CRH_PjKO.d.mts +940 -0
- package/dist/worker-CRH_PjKO.d.mts.map +1 -0
- package/dist/worker.d.mts +2 -0
- package/dist/worker.mjs +2 -0
- package/dist/worker.mjs.map +1 -0
- package/dist/xlsx-reader-D9Ntxm29.mjs +2 -0
- package/dist/xlsx-reader-D9Ntxm29.mjs.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
import { i as RowTransform, r as RowResult } from "./transform-WeiiLdYP.mjs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/mapping/number-format.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Number parsing for the configurable mapping engine (commerce-demo phase 02).
|
|
7
|
+
*
|
|
8
|
+
* Real supplier feeds (R03) disagree on decimal AND thousands separators:
|
|
9
|
+
* `55.02` (dot decimal), `326,88` (comma decimal), `1.234,56` (EU
|
|
10
|
+
* thousands+decimal), `1,234.56` (US), `1 234,56` (space-grouped). The mapping
|
|
11
|
+
* stores an explicit `{ decimal, thousands }` per profile so there is no guessing
|
|
12
|
+
* — `parseNumber` trusts the configured format.
|
|
13
|
+
*
|
|
14
|
+
* Two parsers live here:
|
|
15
|
+
* - `parseNumber(raw, format)` — the format-driven parser used by the generic
|
|
16
|
+
* `number` per-column transform.
|
|
17
|
+
* - `parseEuropeanNumber(raw)` — the carmaker-feed legacy parser (comma decimal,
|
|
18
|
+
* dot thousands, **bare-dot rejected as ambiguous**). Carries the carmaker feed's
|
|
19
|
+
* documented format with two intentional broadenings vs the old inline parser:
|
|
20
|
+
* it trims surrounding whitespace, and returns `null` (not `NaN`) for an empty /
|
|
21
|
+
* `'NA'` cell so both number ops share absent-vs-malformed semantics. The
|
|
22
|
+
* carmaker doc-shape suite (27 tests) is the regression net.
|
|
23
|
+
*/
|
|
24
|
+
/** Separator config for {@link parseNumber}. Stored per `import_mapping`. */
|
|
25
|
+
interface NumberFormat {
|
|
26
|
+
/** Decimal separator. */
|
|
27
|
+
decimal: '.' | ',';
|
|
28
|
+
/** Thousands grouping separator. `''` = none. */
|
|
29
|
+
thousands: '' | '.' | ',' | ' ';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse a feed cell into a number using an EXPLICIT `{ decimal, thousands }`
|
|
33
|
+
* format. No ambiguity: thousands separators are stripped, the decimal separator
|
|
34
|
+
* is normalised to `.`, and the result is strict-validated.
|
|
35
|
+
*
|
|
36
|
+
* Returns:
|
|
37
|
+
* - `null` for an empty / `'NA'` cell (a legitimately-absent value — the caller
|
|
38
|
+
* decides whether that's allowed for a given target field).
|
|
39
|
+
* - `NaN` for a non-empty but unparseable cell (malformed — the caller surfaces
|
|
40
|
+
* a row-level error rather than coercing to 0).
|
|
41
|
+
* - the parsed number otherwise.
|
|
42
|
+
*
|
|
43
|
+
* A character that is neither a digit, the configured decimal, the configured
|
|
44
|
+
* thousands separator, nor a leading `-` makes the cell unparseable (`NaN`) —
|
|
45
|
+
* e.g. a literal `.` when the format's decimal is `,` and thousands is not `.`.
|
|
46
|
+
*/
|
|
47
|
+
declare function parseNumber(raw: string, format: NumberFormat): number | null;
|
|
48
|
+
/**
|
|
49
|
+
* Convert a major-unit money value (e.g. `55.02` EUR) to integer MINOR units
|
|
50
|
+
* (`5502`). Rounds to the nearest cent to absorb float drift. The commerce-demo
|
|
51
|
+
* PartsDocument money fields (`list_price_minor`, `purchase_price_minor`,
|
|
52
|
+
* `core_charge_minor`) are integer minor units so derived prices (PR4) don't
|
|
53
|
+
* accrue rounding error — see F003 in progress.md.
|
|
54
|
+
*/
|
|
55
|
+
declare function toMinorUnits(value: number): number;
|
|
56
|
+
/**
|
|
57
|
+
* Parse a European-formatted decimal: `,` is the decimal separator, `.` is the
|
|
58
|
+
* (optional) thousands separator. Returns `null` for an empty / `'NA'` cell and
|
|
59
|
+
* `NaN` on unparseable (malformed) input.
|
|
60
|
+
*
|
|
61
|
+
* This is the carmaker-feed legacy parser, preserved from the hardcoded transform.
|
|
62
|
+
* Crucially it **rejects bare-dot** input (`1.98`, `1.234`) as ambiguous rather
|
|
63
|
+
* than guessing — the carmaker feeds are documented as comma-decimal, and a `.`
|
|
64
|
+
* without a `,` could mean a US-format decimal OR a thousands marker. The
|
|
65
|
+
* format-driven {@link parseNumber} doesn't need this guard (its separators are
|
|
66
|
+
* explicit); the carmaker path keeps it.
|
|
67
|
+
*
|
|
68
|
+
* The `null` (absent) vs `NaN` (malformed) split mirrors {@link parseNumber} so
|
|
69
|
+
* the mapping engine treats both number ops uniformly: a target field's `buildRow`
|
|
70
|
+
* reads `null` as "not provided" and `NaN` as "invalid". This is what lets the
|
|
71
|
+
* reimplemented carmaker transform keep its `GrossPrice 'NA' → null` behaviour
|
|
72
|
+
* (optional field) while still erroring on a malformed `NetPrice` (required).
|
|
73
|
+
*
|
|
74
|
+
* Cases: `'1,98'`→`1.98`, `'1.234,56'`→`1234.56`, `'5'`→`5`, `'-5,00'`→`-5`,
|
|
75
|
+
* empty / `'NA'` → `null`. Rejected (`NaN`): bare-dot (`'1.98'`, `'1.234'`),
|
|
76
|
+
* trailing junk (`'1,98EUR'`), multiple commas (`'1,2,3'`), other non-numeric.
|
|
77
|
+
*/
|
|
78
|
+
declare function parseEuropeanNumber(s: string): number | null;
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/mapping/column-transforms.d.ts
|
|
81
|
+
/**
|
|
82
|
+
* Discriminated union of bounded transform ops. The TS type is INFERRED from
|
|
83
|
+
* this schema so there's a single source of truth + the snapshot is validated at
|
|
84
|
+
* the engine boundary.
|
|
85
|
+
*/
|
|
86
|
+
declare const columnTransformSchema: z.ZodDiscriminatedUnion<"op", [z.ZodObject<{
|
|
87
|
+
op: z.ZodLiteral<"trim">;
|
|
88
|
+
}, "strip", z.ZodTypeAny, {
|
|
89
|
+
op: "trim";
|
|
90
|
+
}, {
|
|
91
|
+
op: "trim";
|
|
92
|
+
}>, z.ZodObject<{
|
|
93
|
+
op: z.ZodLiteral<"uppercase">;
|
|
94
|
+
}, "strip", z.ZodTypeAny, {
|
|
95
|
+
op: "uppercase";
|
|
96
|
+
}, {
|
|
97
|
+
op: "uppercase";
|
|
98
|
+
}>, z.ZodObject<{
|
|
99
|
+
op: z.ZodLiteral<"lowercase">;
|
|
100
|
+
}, "strip", z.ZodTypeAny, {
|
|
101
|
+
op: "lowercase";
|
|
102
|
+
}, {
|
|
103
|
+
op: "lowercase";
|
|
104
|
+
}>, z.ZodObject<{
|
|
105
|
+
op: z.ZodLiteral<"stripPrefix">;
|
|
106
|
+
value: z.ZodString;
|
|
107
|
+
}, "strip", z.ZodTypeAny, {
|
|
108
|
+
value: string;
|
|
109
|
+
op: "stripPrefix";
|
|
110
|
+
}, {
|
|
111
|
+
value: string;
|
|
112
|
+
op: "stripPrefix";
|
|
113
|
+
}>, z.ZodObject<{
|
|
114
|
+
op: z.ZodLiteral<"stripSuffix">;
|
|
115
|
+
value: z.ZodString;
|
|
116
|
+
}, "strip", z.ZodTypeAny, {
|
|
117
|
+
value: string;
|
|
118
|
+
op: "stripSuffix";
|
|
119
|
+
}, {
|
|
120
|
+
value: string;
|
|
121
|
+
op: "stripSuffix";
|
|
122
|
+
}>, z.ZodObject<{
|
|
123
|
+
op: z.ZodLiteral<"defaultIfEmpty">;
|
|
124
|
+
value: z.ZodString;
|
|
125
|
+
}, "strip", z.ZodTypeAny, {
|
|
126
|
+
value: string;
|
|
127
|
+
op: "defaultIfEmpty";
|
|
128
|
+
}, {
|
|
129
|
+
value: string;
|
|
130
|
+
op: "defaultIfEmpty";
|
|
131
|
+
}>, z.ZodObject<{
|
|
132
|
+
op: z.ZodLiteral<"number">;
|
|
133
|
+
}, "strip", z.ZodTypeAny, {
|
|
134
|
+
op: "number";
|
|
135
|
+
}, {
|
|
136
|
+
op: "number";
|
|
137
|
+
}>, z.ZodObject<{
|
|
138
|
+
op: z.ZodLiteral<"europeanNumber">;
|
|
139
|
+
}, "strip", z.ZodTypeAny, {
|
|
140
|
+
op: "europeanNumber";
|
|
141
|
+
}, {
|
|
142
|
+
op: "europeanNumber";
|
|
143
|
+
}>]>;
|
|
144
|
+
/** One declarative cleaning operation. */
|
|
145
|
+
type ColumnTransform = z.infer<typeof columnTransformSchema>;
|
|
146
|
+
/** The discriminator literal of a {@link ColumnTransform}. */
|
|
147
|
+
type ColumnTransformOp = ColumnTransform['op'];
|
|
148
|
+
/** UI descriptor for one transform op: its key, a label, and whether it takes a `value` param. */
|
|
149
|
+
interface ColumnTransformOpDescriptor {
|
|
150
|
+
op: ColumnTransformOp;
|
|
151
|
+
label: string;
|
|
152
|
+
/** `true` → the op carries a `value` string param (`stripPrefix`/`stripSuffix`/`defaultIfEmpty`). */
|
|
153
|
+
hasValue: boolean;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Static catalogue of the available per-column transform ops, for the PR3 wizard's
|
|
157
|
+
* transform picker. The ORDER is the suggested UI order; `number`/`europeanNumber`
|
|
158
|
+
* are terminal (see {@link applyColumnTransforms}) and labelled accordingly.
|
|
159
|
+
*/
|
|
160
|
+
declare const COLUMN_TRANSFORM_OPS: readonly ColumnTransformOpDescriptor[];
|
|
161
|
+
/** The value a column carries as it moves through the transform pipeline. */
|
|
162
|
+
type CellValue = string | number | null;
|
|
163
|
+
/**
|
|
164
|
+
* Apply a transform pipeline to a raw cell, left-to-right. String ops act on the
|
|
165
|
+
* string value; the `number` / `europeanNumber` ops are terminal (convert to
|
|
166
|
+
* `number | null`, with `NaN` for a malformed numeric — the schema's `buildRow`
|
|
167
|
+
* surfaces that as a row error). Once the value is non-string, later string ops
|
|
168
|
+
* pass through unchanged.
|
|
169
|
+
*/
|
|
170
|
+
declare function applyColumnTransforms(raw: string, transforms: readonly ColumnTransform[], format: NumberFormat): CellValue;
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region src/mapping/target-schema.d.ts
|
|
173
|
+
/** One whitelisted target field on a schema. */
|
|
174
|
+
interface TargetField {
|
|
175
|
+
/** Stable target key referenced by `column_map[].target`. */
|
|
176
|
+
key: string;
|
|
177
|
+
/** Human label for the wizard dropdown (PR3). */
|
|
178
|
+
label: string;
|
|
179
|
+
/** Whether a mapping for this schema MUST include this target. */
|
|
180
|
+
required: boolean;
|
|
181
|
+
/** Coarse type — drives the wizard's transform suggestions; `buildRow` does the real coercion. */
|
|
182
|
+
type: 'string' | 'number';
|
|
183
|
+
/**
|
|
184
|
+
* Header spellings this field should be SUGGESTED for when the wizard auto-assigns a freshly
|
|
185
|
+
* previewed file. Purely advisory: the operator can always override, and nothing here widens
|
|
186
|
+
* the injection-boundary whitelist — `key` remains the only accepted `column_map[].target`.
|
|
187
|
+
*
|
|
188
|
+
* Real feeds do not name their columns after our keys (a supplier ships `partno`, `VARUOSA
|
|
189
|
+
* KOOD`, `ArticleName`, never `code`), so without aliases the wizard suggests nothing for the
|
|
190
|
+
* columns that matter and the operator has to know the schema by heart. `describeTargetSchemas`
|
|
191
|
+
* ships this to the wizard verbatim, so a field's synonyms live next to the field itself
|
|
192
|
+
* rather than in a lookup table on the client.
|
|
193
|
+
*
|
|
194
|
+
* Only add a spelling whose meaning is UNAMBIGUOUS. An alias is a silent decision applied to
|
|
195
|
+
* somebody's catalogue — see the supersession fields below, where two spellings that both read
|
|
196
|
+
* as "replacement" denote opposite directions and are therefore deliberately absent.
|
|
197
|
+
*/
|
|
198
|
+
aliases?: readonly string[];
|
|
199
|
+
}
|
|
200
|
+
/** The per-row product of the engine: target field key → cleaned value. */
|
|
201
|
+
type MappedRow = Record<string, CellValue>;
|
|
202
|
+
/** Per-row context handed to `buildRow`. `params` is the opaque per-run params object. */
|
|
203
|
+
interface BuildRowContext {
|
|
204
|
+
importRunId: string;
|
|
205
|
+
rowNumber: number;
|
|
206
|
+
/**
|
|
207
|
+
* Opaque per-run params (the parts schema reads brand/supplier identity from
|
|
208
|
+
* it; `discount_table` ignores it). The schema validates the shape it needs.
|
|
209
|
+
*/
|
|
210
|
+
params: Record<string, unknown>;
|
|
211
|
+
}
|
|
212
|
+
/** A registered target schema: a whitelist + a row builder. */
|
|
213
|
+
interface TargetSchema<TOut> {
|
|
214
|
+
/** Registered name — also the `import_mapping.target_schema` value. */
|
|
215
|
+
name: string;
|
|
216
|
+
/** The target-field whitelist (injection boundary). */
|
|
217
|
+
fields: readonly TargetField[];
|
|
218
|
+
/** Build a typed output (success) / skip / error from a mapped row. */
|
|
219
|
+
buildRow(mapped: MappedRow, ctx: BuildRowContext): RowResult<TOut>;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* A nullable text cell → trimmed string, or `null` for empty / non-string. Accepts
|
|
223
|
+
* `undefined` (an UNMAPPED target — indexed access under `noUncheckedIndexedAccess`)
|
|
224
|
+
* and treats it as absent.
|
|
225
|
+
*/
|
|
226
|
+
declare function textOrNull(v: CellValue | undefined): string | null;
|
|
227
|
+
/** The three outcomes a `number` / `europeanNumber` op produces for a cell. */
|
|
228
|
+
type NumberOutcome = {
|
|
229
|
+
kind: 'value';
|
|
230
|
+
value: number;
|
|
231
|
+
} | {
|
|
232
|
+
kind: 'absent';
|
|
233
|
+
} | {
|
|
234
|
+
kind: 'invalid';
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* Classify a cell that should hold a number. `undefined` (unmapped) / `null` →
|
|
238
|
+
* absent; a real number → value (`NaN` → invalid); a non-empty raw string (no
|
|
239
|
+
* number op declared) → invalid; a blank raw string → absent.
|
|
240
|
+
*/
|
|
241
|
+
declare function numberCell(v: CellValue | undefined): NumberOutcome;
|
|
242
|
+
/** Build a `RowResult` error variant (assignable to any `TargetSchema<TOut>`). */
|
|
243
|
+
declare function rowError(errorType: string, message: string, field: string): {
|
|
244
|
+
kind: "error";
|
|
245
|
+
error: {
|
|
246
|
+
errorType: string;
|
|
247
|
+
message: string;
|
|
248
|
+
field: string;
|
|
249
|
+
};
|
|
250
|
+
};
|
|
251
|
+
//#endregion
|
|
252
|
+
//#region src/mapping/engine.d.ts
|
|
253
|
+
/** One column-map entry. `target` is checked against the schema whitelist separately. */
|
|
254
|
+
declare const mappingColumnSchema: z.ZodObject<{
|
|
255
|
+
/** Source header name (or positional index string for headerless feeds). */source: z.ZodString; /** Target field key — must be in the chosen schema's whitelist (enforced in `buildMappingTransform`). */
|
|
256
|
+
target: z.ZodString; /** Ordered per-column cleaning ops. Defaults to none. */
|
|
257
|
+
transforms: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<"op", [z.ZodObject<{
|
|
258
|
+
op: z.ZodLiteral<"trim">;
|
|
259
|
+
}, "strip", z.ZodTypeAny, {
|
|
260
|
+
op: "trim";
|
|
261
|
+
}, {
|
|
262
|
+
op: "trim";
|
|
263
|
+
}>, z.ZodObject<{
|
|
264
|
+
op: z.ZodLiteral<"uppercase">;
|
|
265
|
+
}, "strip", z.ZodTypeAny, {
|
|
266
|
+
op: "uppercase";
|
|
267
|
+
}, {
|
|
268
|
+
op: "uppercase";
|
|
269
|
+
}>, z.ZodObject<{
|
|
270
|
+
op: z.ZodLiteral<"lowercase">;
|
|
271
|
+
}, "strip", z.ZodTypeAny, {
|
|
272
|
+
op: "lowercase";
|
|
273
|
+
}, {
|
|
274
|
+
op: "lowercase";
|
|
275
|
+
}>, z.ZodObject<{
|
|
276
|
+
op: z.ZodLiteral<"stripPrefix">;
|
|
277
|
+
value: z.ZodString;
|
|
278
|
+
}, "strip", z.ZodTypeAny, {
|
|
279
|
+
value: string;
|
|
280
|
+
op: "stripPrefix";
|
|
281
|
+
}, {
|
|
282
|
+
value: string;
|
|
283
|
+
op: "stripPrefix";
|
|
284
|
+
}>, z.ZodObject<{
|
|
285
|
+
op: z.ZodLiteral<"stripSuffix">;
|
|
286
|
+
value: z.ZodString;
|
|
287
|
+
}, "strip", z.ZodTypeAny, {
|
|
288
|
+
value: string;
|
|
289
|
+
op: "stripSuffix";
|
|
290
|
+
}, {
|
|
291
|
+
value: string;
|
|
292
|
+
op: "stripSuffix";
|
|
293
|
+
}>, z.ZodObject<{
|
|
294
|
+
op: z.ZodLiteral<"defaultIfEmpty">;
|
|
295
|
+
value: z.ZodString;
|
|
296
|
+
}, "strip", z.ZodTypeAny, {
|
|
297
|
+
value: string;
|
|
298
|
+
op: "defaultIfEmpty";
|
|
299
|
+
}, {
|
|
300
|
+
value: string;
|
|
301
|
+
op: "defaultIfEmpty";
|
|
302
|
+
}>, z.ZodObject<{
|
|
303
|
+
op: z.ZodLiteral<"number">;
|
|
304
|
+
}, "strip", z.ZodTypeAny, {
|
|
305
|
+
op: "number";
|
|
306
|
+
}, {
|
|
307
|
+
op: "number";
|
|
308
|
+
}>, z.ZodObject<{
|
|
309
|
+
op: z.ZodLiteral<"europeanNumber">;
|
|
310
|
+
}, "strip", z.ZodTypeAny, {
|
|
311
|
+
op: "europeanNumber";
|
|
312
|
+
}, {
|
|
313
|
+
op: "europeanNumber";
|
|
314
|
+
}>]>, "many">>;
|
|
315
|
+
}, "strip", z.ZodTypeAny, {
|
|
316
|
+
target: string;
|
|
317
|
+
transforms: ({
|
|
318
|
+
op: "trim";
|
|
319
|
+
} | {
|
|
320
|
+
op: "uppercase";
|
|
321
|
+
} | {
|
|
322
|
+
op: "lowercase";
|
|
323
|
+
} | {
|
|
324
|
+
value: string;
|
|
325
|
+
op: "stripPrefix";
|
|
326
|
+
} | {
|
|
327
|
+
value: string;
|
|
328
|
+
op: "stripSuffix";
|
|
329
|
+
} | {
|
|
330
|
+
value: string;
|
|
331
|
+
op: "defaultIfEmpty";
|
|
332
|
+
} | {
|
|
333
|
+
op: "number";
|
|
334
|
+
} | {
|
|
335
|
+
op: "europeanNumber";
|
|
336
|
+
})[];
|
|
337
|
+
source: string;
|
|
338
|
+
}, {
|
|
339
|
+
target: string;
|
|
340
|
+
source: string;
|
|
341
|
+
transforms?: ({
|
|
342
|
+
op: "trim";
|
|
343
|
+
} | {
|
|
344
|
+
op: "uppercase";
|
|
345
|
+
} | {
|
|
346
|
+
op: "lowercase";
|
|
347
|
+
} | {
|
|
348
|
+
value: string;
|
|
349
|
+
op: "stripPrefix";
|
|
350
|
+
} | {
|
|
351
|
+
value: string;
|
|
352
|
+
op: "stripSuffix";
|
|
353
|
+
} | {
|
|
354
|
+
value: string;
|
|
355
|
+
op: "defaultIfEmpty";
|
|
356
|
+
} | {
|
|
357
|
+
op: "number";
|
|
358
|
+
} | {
|
|
359
|
+
op: "europeanNumber";
|
|
360
|
+
})[] | undefined;
|
|
361
|
+
}>;
|
|
362
|
+
type MappingColumn = z.infer<typeof mappingColumnSchema>;
|
|
363
|
+
/**
|
|
364
|
+
* Decimal + thousands separators for the `number` transform.
|
|
365
|
+
*
|
|
366
|
+
* The two MUST differ: `parseNumber` strips every thousands separator FIRST, so a
|
|
367
|
+
* config where `decimal === thousands` (e.g. both `,`) would strip the decimal
|
|
368
|
+
* separator too — `326,88` → `32688`, a silent 100× error rather than a row error.
|
|
369
|
+
* Rejected at save (`assertValidMapping`) AND at run (`mappingConfigSchema`).
|
|
370
|
+
*/
|
|
371
|
+
declare const numberFormatSchema: z.ZodEffects<z.ZodObject<{
|
|
372
|
+
decimal: z.ZodEnum<[".", ","]>;
|
|
373
|
+
thousands: z.ZodEnum<["", ".", ",", " "]>;
|
|
374
|
+
}, "strip", z.ZodTypeAny, {
|
|
375
|
+
decimal: "," | ".";
|
|
376
|
+
thousands: "" | "," | "." | " ";
|
|
377
|
+
}, {
|
|
378
|
+
decimal: "," | ".";
|
|
379
|
+
thousands: "" | "," | "." | " ";
|
|
380
|
+
}>, {
|
|
381
|
+
decimal: "," | ".";
|
|
382
|
+
thousands: "" | "," | "." | " ";
|
|
383
|
+
}, {
|
|
384
|
+
decimal: "," | ".";
|
|
385
|
+
thousands: "" | "," | "." | " ";
|
|
386
|
+
}>;
|
|
387
|
+
/**
|
|
388
|
+
* The portable mapping config — the subset of an `import_mapping` row the engine
|
|
389
|
+
* needs. The enqueuer SNAPSHOTS this into `import_run.params.mapping` so a run
|
|
390
|
+
* records the exact mapping it used (reproducible) and the transform stays a pure
|
|
391
|
+
* function of `(row, ctx)` with no per-row DB I/O.
|
|
392
|
+
*/
|
|
393
|
+
declare const mappingConfigSchema: z.ZodObject<{
|
|
394
|
+
targetSchema: z.ZodString;
|
|
395
|
+
numberFormat: z.ZodEffects<z.ZodObject<{
|
|
396
|
+
decimal: z.ZodEnum<[".", ","]>;
|
|
397
|
+
thousands: z.ZodEnum<["", ".", ",", " "]>;
|
|
398
|
+
}, "strip", z.ZodTypeAny, {
|
|
399
|
+
decimal: "," | ".";
|
|
400
|
+
thousands: "" | "," | "." | " ";
|
|
401
|
+
}, {
|
|
402
|
+
decimal: "," | ".";
|
|
403
|
+
thousands: "" | "," | "." | " ";
|
|
404
|
+
}>, {
|
|
405
|
+
decimal: "," | ".";
|
|
406
|
+
thousands: "" | "," | "." | " ";
|
|
407
|
+
}, {
|
|
408
|
+
decimal: "," | ".";
|
|
409
|
+
thousands: "" | "," | "." | " ";
|
|
410
|
+
}>;
|
|
411
|
+
columnMap: z.ZodArray<z.ZodObject<{
|
|
412
|
+
/** Source header name (or positional index string for headerless feeds). */source: z.ZodString; /** Target field key — must be in the chosen schema's whitelist (enforced in `buildMappingTransform`). */
|
|
413
|
+
target: z.ZodString; /** Ordered per-column cleaning ops. Defaults to none. */
|
|
414
|
+
transforms: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<"op", [z.ZodObject<{
|
|
415
|
+
op: z.ZodLiteral<"trim">;
|
|
416
|
+
}, "strip", z.ZodTypeAny, {
|
|
417
|
+
op: "trim";
|
|
418
|
+
}, {
|
|
419
|
+
op: "trim";
|
|
420
|
+
}>, z.ZodObject<{
|
|
421
|
+
op: z.ZodLiteral<"uppercase">;
|
|
422
|
+
}, "strip", z.ZodTypeAny, {
|
|
423
|
+
op: "uppercase";
|
|
424
|
+
}, {
|
|
425
|
+
op: "uppercase";
|
|
426
|
+
}>, z.ZodObject<{
|
|
427
|
+
op: z.ZodLiteral<"lowercase">;
|
|
428
|
+
}, "strip", z.ZodTypeAny, {
|
|
429
|
+
op: "lowercase";
|
|
430
|
+
}, {
|
|
431
|
+
op: "lowercase";
|
|
432
|
+
}>, z.ZodObject<{
|
|
433
|
+
op: z.ZodLiteral<"stripPrefix">;
|
|
434
|
+
value: z.ZodString;
|
|
435
|
+
}, "strip", z.ZodTypeAny, {
|
|
436
|
+
value: string;
|
|
437
|
+
op: "stripPrefix";
|
|
438
|
+
}, {
|
|
439
|
+
value: string;
|
|
440
|
+
op: "stripPrefix";
|
|
441
|
+
}>, z.ZodObject<{
|
|
442
|
+
op: z.ZodLiteral<"stripSuffix">;
|
|
443
|
+
value: z.ZodString;
|
|
444
|
+
}, "strip", z.ZodTypeAny, {
|
|
445
|
+
value: string;
|
|
446
|
+
op: "stripSuffix";
|
|
447
|
+
}, {
|
|
448
|
+
value: string;
|
|
449
|
+
op: "stripSuffix";
|
|
450
|
+
}>, z.ZodObject<{
|
|
451
|
+
op: z.ZodLiteral<"defaultIfEmpty">;
|
|
452
|
+
value: z.ZodString;
|
|
453
|
+
}, "strip", z.ZodTypeAny, {
|
|
454
|
+
value: string;
|
|
455
|
+
op: "defaultIfEmpty";
|
|
456
|
+
}, {
|
|
457
|
+
value: string;
|
|
458
|
+
op: "defaultIfEmpty";
|
|
459
|
+
}>, z.ZodObject<{
|
|
460
|
+
op: z.ZodLiteral<"number">;
|
|
461
|
+
}, "strip", z.ZodTypeAny, {
|
|
462
|
+
op: "number";
|
|
463
|
+
}, {
|
|
464
|
+
op: "number";
|
|
465
|
+
}>, z.ZodObject<{
|
|
466
|
+
op: z.ZodLiteral<"europeanNumber">;
|
|
467
|
+
}, "strip", z.ZodTypeAny, {
|
|
468
|
+
op: "europeanNumber";
|
|
469
|
+
}, {
|
|
470
|
+
op: "europeanNumber";
|
|
471
|
+
}>]>, "many">>;
|
|
472
|
+
}, "strip", z.ZodTypeAny, {
|
|
473
|
+
target: string;
|
|
474
|
+
transforms: ({
|
|
475
|
+
op: "trim";
|
|
476
|
+
} | {
|
|
477
|
+
op: "uppercase";
|
|
478
|
+
} | {
|
|
479
|
+
op: "lowercase";
|
|
480
|
+
} | {
|
|
481
|
+
value: string;
|
|
482
|
+
op: "stripPrefix";
|
|
483
|
+
} | {
|
|
484
|
+
value: string;
|
|
485
|
+
op: "stripSuffix";
|
|
486
|
+
} | {
|
|
487
|
+
value: string;
|
|
488
|
+
op: "defaultIfEmpty";
|
|
489
|
+
} | {
|
|
490
|
+
op: "number";
|
|
491
|
+
} | {
|
|
492
|
+
op: "europeanNumber";
|
|
493
|
+
})[];
|
|
494
|
+
source: string;
|
|
495
|
+
}, {
|
|
496
|
+
target: string;
|
|
497
|
+
source: string;
|
|
498
|
+
transforms?: ({
|
|
499
|
+
op: "trim";
|
|
500
|
+
} | {
|
|
501
|
+
op: "uppercase";
|
|
502
|
+
} | {
|
|
503
|
+
op: "lowercase";
|
|
504
|
+
} | {
|
|
505
|
+
value: string;
|
|
506
|
+
op: "stripPrefix";
|
|
507
|
+
} | {
|
|
508
|
+
value: string;
|
|
509
|
+
op: "stripSuffix";
|
|
510
|
+
} | {
|
|
511
|
+
value: string;
|
|
512
|
+
op: "defaultIfEmpty";
|
|
513
|
+
} | {
|
|
514
|
+
op: "number";
|
|
515
|
+
} | {
|
|
516
|
+
op: "europeanNumber";
|
|
517
|
+
})[] | undefined;
|
|
518
|
+
}>, "many">;
|
|
519
|
+
}, "strip", z.ZodTypeAny, {
|
|
520
|
+
targetSchema: string;
|
|
521
|
+
numberFormat: {
|
|
522
|
+
decimal: "," | ".";
|
|
523
|
+
thousands: "" | "," | "." | " ";
|
|
524
|
+
};
|
|
525
|
+
columnMap: {
|
|
526
|
+
target: string;
|
|
527
|
+
transforms: ({
|
|
528
|
+
op: "trim";
|
|
529
|
+
} | {
|
|
530
|
+
op: "uppercase";
|
|
531
|
+
} | {
|
|
532
|
+
op: "lowercase";
|
|
533
|
+
} | {
|
|
534
|
+
value: string;
|
|
535
|
+
op: "stripPrefix";
|
|
536
|
+
} | {
|
|
537
|
+
value: string;
|
|
538
|
+
op: "stripSuffix";
|
|
539
|
+
} | {
|
|
540
|
+
value: string;
|
|
541
|
+
op: "defaultIfEmpty";
|
|
542
|
+
} | {
|
|
543
|
+
op: "number";
|
|
544
|
+
} | {
|
|
545
|
+
op: "europeanNumber";
|
|
546
|
+
})[];
|
|
547
|
+
source: string;
|
|
548
|
+
}[];
|
|
549
|
+
}, {
|
|
550
|
+
targetSchema: string;
|
|
551
|
+
numberFormat: {
|
|
552
|
+
decimal: "," | ".";
|
|
553
|
+
thousands: "" | "," | "." | " ";
|
|
554
|
+
};
|
|
555
|
+
columnMap: {
|
|
556
|
+
target: string;
|
|
557
|
+
source: string;
|
|
558
|
+
transforms?: ({
|
|
559
|
+
op: "trim";
|
|
560
|
+
} | {
|
|
561
|
+
op: "uppercase";
|
|
562
|
+
} | {
|
|
563
|
+
op: "lowercase";
|
|
564
|
+
} | {
|
|
565
|
+
value: string;
|
|
566
|
+
op: "stripPrefix";
|
|
567
|
+
} | {
|
|
568
|
+
value: string;
|
|
569
|
+
op: "stripSuffix";
|
|
570
|
+
} | {
|
|
571
|
+
value: string;
|
|
572
|
+
op: "defaultIfEmpty";
|
|
573
|
+
} | {
|
|
574
|
+
op: "number";
|
|
575
|
+
} | {
|
|
576
|
+
op: "europeanNumber";
|
|
577
|
+
})[] | undefined;
|
|
578
|
+
}[];
|
|
579
|
+
}>;
|
|
580
|
+
type MappingConfig = z.infer<typeof mappingConfigSchema>;
|
|
581
|
+
/**
|
|
582
|
+
* Build a `RowTransform` from a validated mapping config + its target schema.
|
|
583
|
+
*
|
|
584
|
+
* Throws at BUILD time if any `column_map` target is outside the schema's
|
|
585
|
+
* whitelist (deny-by-default, R02) — so a misconfigured mapping fails loudly
|
|
586
|
+
* before a single row is written, rather than silently dropping a column.
|
|
587
|
+
*
|
|
588
|
+
* Generic over the schema's output type, so passing the concrete `partsSchema`
|
|
589
|
+
* yields a `RowTransform<PartsDocument>` (the carmaker path keeps its typing); the
|
|
590
|
+
* registry-resolved `TargetSchema<unknown>` yields `RowTransform<unknown>` (the
|
|
591
|
+
* `commerce:mapping` path, where the output type isn't known until runtime).
|
|
592
|
+
*/
|
|
593
|
+
declare function buildMappingTransform<TOut>(config: MappingConfig, schema: TargetSchema<TOut>): RowTransform<TOut>;
|
|
594
|
+
/** The minimal shape `resolveMapping` needs — satisfied by an `import_mapping` row or a test fixture. */
|
|
595
|
+
interface ResolvableMapping {
|
|
596
|
+
/** `null` = supplier default (applies to all brands). */
|
|
597
|
+
brandId: string | null;
|
|
598
|
+
active: boolean;
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Most-specific resolution (D002 ladder): given the candidate mappings for one
|
|
602
|
+
* `(supplier, target_schema)` and the requested brand, return the brand-specific
|
|
603
|
+
* mapping if one exists, else the supplier-default (`brandId === null`). Inactive
|
|
604
|
+
* mappings are skipped. Returns `undefined` when nothing matches.
|
|
605
|
+
*/
|
|
606
|
+
declare function resolveMapping<M extends ResolvableMapping>(mappings: readonly M[], brandId: string | null): M | undefined;
|
|
607
|
+
//#endregion
|
|
608
|
+
export { columnTransformSchema as C, toMinorUnits as D, parseNumber as E, applyColumnTransforms as S, parseEuropeanNumber as T, COLUMN_TRANSFORM_OPS as _, mappingColumnSchema as a, ColumnTransformOp as b, resolveMapping as c, NumberOutcome as d, TargetField as f, textOrNull as g, rowError as h, buildMappingTransform as i, BuildRowContext as l, numberCell as m, MappingConfig as n, mappingConfigSchema as o, TargetSchema as p, ResolvableMapping as r, numberFormatSchema as s, MappingColumn as t, MappedRow as u, CellValue as v, NumberFormat as w, ColumnTransformOpDescriptor as x, ColumnTransform as y };
|
|
609
|
+
//# sourceMappingURL=engine-tkbUXKxB.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-tkbUXKxB.d.mts","names":[],"sources":["../src/mapping/number-format.ts","../src/mapping/column-transforms.ts","../src/mapping/target-schema.ts","../src/mapping/engine.ts"],"mappings":";;;;;;;;AAqBA;;;;AAIW;AAsBX;;;;;;;;AAA6D;AA+B7D;;UAzDiB,YAAA;EAyDyB;EAvDxC,OAAA;EAiFc;EA/Ed,SAAS;AAAA;;AA+EkC;;;;AC9E7C;;;;;;;;;;;iBDqBgB,WAAA,CAAY,GAAA,UAAa,MAAA,EAAQ,YAAY;;;;;;;;iBA+B7C,YAAA,CAAa,KAAa;;;;;;;;;;;;;;;;;;;;;;;iBA0B1B,mBAAA,CAAoB,CAAS;;;;AAzDgB;AA+B7D;;;cCpDa,qBAAA,EAAqB,CAAA,CAAA,qBAAA,QAAA,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAYtB,eAAA,GAAkB,CAAA,CAAE,KAAK,QAAQ,qBAAA;;KAGjC,iBAAA,GAAoB,eAAe;;UAG9B,2BAAA;EACf,EAAA,EAAI,iBAAiB;EACrB,KAAA;;EAEA,QAAA;AAAA;;;;;;cAQW,oBAAA,WAA+B,2BAA2B;;KAY3D,SAAA;;;;;;;;iBASI,qBAAA,CACd,GAAA,UACA,UAAA,WAAqB,eAAA,IACrB,MAAA,EAAQ,YAAA,GACP,SAAA;;;;UC/Dc,WAAA;EF6B4C;EE3B3D,GAAA;EF0D0B;EExD1B,KAAA;EFwDwC;EEtDxC,QAAA;EFgFc;EE9Ed,IAAA;;;AF8E2C;;;;AC9E7C;;;;;;;;;ECgBE,OAAA;AAAA;;KAIU,SAAA,GAAY,MAAM,SAAS,SAAA;;UAGtB,eAAA;EACf,WAAA;EACA,SAAA;;;;;EAKA,MAAA,EAAQ,MAAM;AAAA;;UAIC,YAAA;;EAEf,IAAA;;EAEA,MAAA,WAAiB,WAAA;;EAEjB,QAAA,CAAS,MAAA,EAAQ,SAAA,EAAW,GAAA,EAAK,eAAA,GAAkB,SAAA,CAAU,IAAA;AAAA;;;;;;iBAY/C,UAAA,CAAW,CAAwB,EAArB,SAAS;;KAO3B,aAAA;EACN,IAAA;EAAe,KAAA;AAAA;EACf,IAAA;AAAA;EACA,IAAA;AAAA;;;;;;iBAOU,UAAA,CAAW,CAAA,EAAG,SAAA,eAAwB,aAAa;;iBASnD,QAAA,CAAS,SAAA,UAAmB,OAAA,UAAiB,KAAA;;;;;;;;;;;cChFhD,mBAAA,EAAmB,CAAA,CAAA,SAAA;EHsDU,iGA0BP;uBAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KGxEjC,aAAA,GAAgB,CAAA,CAAE,KAAK,QAAQ,mBAAA;;;;;;;;;cAU9B,kBAAA,EAAkB,CAAA,CAAA,UAAA,CAAA,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;cAgBlB,mBAAA,EAAmB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;IFFuC,iGAY3D;yBAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KELT,aAAA,GAAgB,CAAA,CAAE,KAAK,QAAQ,mBAAA;;;;;;;;;;;;;iBAc3B,qBAAA,OACd,MAAA,EAAQ,aAAA,EACR,MAAA,EAAQ,YAAA,CAAa,IAAA,IACpB,YAAA,CAAa,IAAA;;UA+BC,iBAAA;;EAEf,OAAA;EACA,MAAM;AAAA;;;;;;;iBASQ,cAAA,WAAyB,iBAAA,EACvC,QAAA,WAAmB,CAAA,IACnB,OAAA,kBACC,CAAA"}
|