@toolpath/tool-scraper 2.0.0 → 2.2.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/columns.d.ts +5 -3
- package/dist/columns.js +11 -5
- package/dist/conventions.d.ts +54 -0
- package/dist/conventions.js +59 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.js +30 -0
- package/dist/families/emuge.d.ts +3 -1
- package/dist/families/emuge.js +8 -4
- package/dist/family.d.ts +16 -2
- package/dist/holding.d.ts +396 -0
- package/dist/holding.js +360 -0
- package/dist/index.d.ts +23 -13
- package/dist/index.js +23 -13
- package/dist/node/cad-mirror.d.ts +58 -1
- package/dist/node/cad-mirror.js +56 -8
- package/dist/node/cli.d.ts +4 -1
- package/dist/node/cli.js +198 -19
- package/dist/node/holder-import.d.ts +223 -0
- package/dist/node/holder-import.js +379 -0
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +1 -0
- package/dist/node/paths.d.ts +16 -0
- package/dist/node/paths.js +20 -0
- package/dist/profiles.d.ts +265 -0
- package/dist/profiles.js +295 -0
- package/dist/records.d.ts +57 -12
- package/dist/records.js +37 -13
- package/dist/registry.d.ts +86 -5
- package/dist/registry.js +149 -8
- package/dist/vendors/destinytool/records.js +8 -0
- package/dist/vendors/emuge/records.d.ts +83 -3
- package/dist/vendors/emuge/records.js +184 -16
- package/dist/vendors/kennametal/family.d.ts +119 -0
- package/dist/vendors/kennametal/family.js +155 -0
- package/dist/vendors/kennametal/holding.d.ts +35 -0
- package/dist/vendors/kennametal/holding.js +112 -0
- package/dist/vendors/kennametal/index.d.ts +2 -0
- package/dist/vendors/kennametal/index.js +2 -0
- package/dist/vendors/kennametal/records.d.ts +16 -0
- package/dist/vendors/kennametal/records.js +32 -0
- package/dist/vendors/kennametal/scrape.d.ts +25 -2
- package/dist/vendors/kennametal/scrape.js +28 -3
- package/dist/vendors/maritool/holding.d.ts +79 -0
- package/dist/vendors/maritool/holding.js +164 -0
- package/dist/vendors/maritool/index.d.ts +1 -0
- package/dist/vendors/maritool/index.js +1 -0
- package/dist/vendors/maritool/scrape.d.ts +37 -13
- package/dist/vendors/maritool/scrape.js +53 -14
- package/dist/vendors/regofix/holding.d.ts +35 -0
- package/dist/vendors/regofix/holding.js +108 -0
- package/dist/vendors/regofix/index.d.ts +1 -0
- package/dist/vendors/regofix/index.js +1 -0
- package/dist/vendors/regofix/scrape.js +2 -2
- package/package.json +1 -1
package/dist/columns.d.ts
CHANGED
|
@@ -20,9 +20,11 @@
|
|
|
20
20
|
* - a column the family maps to nothing is `undefined`, not an error — a family
|
|
21
21
|
* with no neck column is a plain tool, and that is the mapper's fallback to
|
|
22
22
|
* make;
|
|
23
|
-
* - a **required** field with no reading refuses the row
|
|
24
|
-
*
|
|
25
|
-
* a part
|
|
23
|
+
* - a **required** field with no reading refuses the row with an
|
|
24
|
+
* `errors.IncompletePartError`, naming the canonical field and quoting the
|
|
25
|
+
* cell, because a tool with no cutting diameter is not a part — and that is
|
|
26
|
+
* the one refusal `registry.toRecords` skips past rather than failing the
|
|
27
|
+
* whole family on;
|
|
26
28
|
* - an **optional** one answers null and lets the mapper decide.
|
|
27
29
|
*
|
|
28
30
|
* `vendors/destinytool/records.ts` keeps its own `required` and is not wired
|
package/dist/columns.js
CHANGED
|
@@ -20,9 +20,11 @@
|
|
|
20
20
|
* - a column the family maps to nothing is `undefined`, not an error — a family
|
|
21
21
|
* with no neck column is a plain tool, and that is the mapper's fallback to
|
|
22
22
|
* make;
|
|
23
|
-
* - a **required** field with no reading refuses the row
|
|
24
|
-
*
|
|
25
|
-
* a part
|
|
23
|
+
* - a **required** field with no reading refuses the row with an
|
|
24
|
+
* `errors.IncompletePartError`, naming the canonical field and quoting the
|
|
25
|
+
* cell, because a tool with no cutting diameter is not a part — and that is
|
|
26
|
+
* the one refusal `registry.toRecords` skips past rather than failing the
|
|
27
|
+
* whole family on;
|
|
26
28
|
* - an **optional** one answers null and lets the mapper decide.
|
|
27
29
|
*
|
|
28
30
|
* `vendors/destinytool/records.ts` keeps its own `required` and is not wired
|
|
@@ -31,7 +33,7 @@
|
|
|
31
33
|
* has no `optional` at all. Forcing it into this shape would change how it
|
|
32
34
|
* refuses, which is the one thing `measure.ts` says is a vendor's own call.
|
|
33
35
|
*/
|
|
34
|
-
import {
|
|
36
|
+
import { IncompletePartError } from './errors.js';
|
|
35
37
|
/**
|
|
36
38
|
* The three readers, over one vendor's `read`.
|
|
37
39
|
*
|
|
@@ -54,7 +56,11 @@ export function columnReaders(read) {
|
|
|
54
56
|
const raw = cell(row, columns, canonical, unit);
|
|
55
57
|
const value = raw === undefined ? null : read(raw, unit, what, options.warn);
|
|
56
58
|
if (value === null) {
|
|
57
|
-
|
|
59
|
+
// `IncompletePartError` and not the general vendor fault: this is the
|
|
60
|
+
// one refusal `registry.toRecords` skips past, because a single part the
|
|
61
|
+
// vendor left a cell blank on must not end a family's conversion. See
|
|
62
|
+
// that type for why the others still must not be skipped.
|
|
63
|
+
throw new IncompletePartError(what, `publishes no ${canonical} — its cell is ${JSON.stringify(raw ?? '')}`);
|
|
58
64
|
}
|
|
59
65
|
return value;
|
|
60
66
|
};
|
package/dist/conventions.d.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* | `Description` carries the vendor's own free text | Harvey, MariTool |
|
|
23
23
|
* | `contact` says how a holder seats | REGO-FIX, MariTool |
|
|
24
24
|
* | `CST` names the collet series a holder takes | REGO-FIX, MariTool |
|
|
25
|
+
* | `Collet Series` names the series a collet is | Kennametal, REGO-FIX |
|
|
25
26
|
* | `L1_in`/`L1_mm` carry a holder's gage length | REGO-FIX, MariTool |
|
|
26
27
|
* | Unmapped vendor codes keep a `DIN_` prefix | REGO-FIX; rule is general |
|
|
27
28
|
* | The identity columns | **broken** — see below |
|
|
@@ -97,6 +98,24 @@ export declare const CAD_DXF_COLUMN = "CAD_DXF_URL";
|
|
|
97
98
|
* `records.ToolRecord.description`, which states the same rule for the record.
|
|
98
99
|
*/
|
|
99
100
|
export declare const DESCRIPTION_COLUMN = "Description";
|
|
101
|
+
/**
|
|
102
|
+
* The CSV column holding the vendor's own full name for the family a part is
|
|
103
|
+
* in — `KenCut™ FF • HPFT • Square End • 6 Flutes • Plain Shank • Inch`.
|
|
104
|
+
*
|
|
105
|
+
* Constant down a family's whole table, and that is what makes it a *family*
|
|
106
|
+
* title rather than a {@link DESCRIPTION_COLUMN}: it names the group, not the
|
|
107
|
+
* part. Kennametal and WIDIA publish one as the `h1` of a family page and it
|
|
108
|
+
* reaches the CSV whole, while `records.ToolRecord.productLine` keeps only its
|
|
109
|
+
* leading segment — the rest is the vendor's own wording for the shape, the
|
|
110
|
+
* flute count, the shank and the unit, and a receipt that dropped it would be
|
|
111
|
+
* throwing away published text to save a column.
|
|
112
|
+
*
|
|
113
|
+
* Vendor-neutral and here rather than in the Kennametal adapter for the reason
|
|
114
|
+
* {@link CAD_COLUMN} is: a second vendor that publishes a family title writes
|
|
115
|
+
* this column rather than inventing another. Nothing forces one to — a vendor
|
|
116
|
+
* whose parts carry no family title simply has no such column.
|
|
117
|
+
*/
|
|
118
|
+
export declare const FAMILY_TITLE_COLUMN = "Family Title";
|
|
100
119
|
/**
|
|
101
120
|
* The CSV column saying how a holder seats in the spindle: `taper` or `face`.
|
|
102
121
|
*
|
|
@@ -116,6 +135,21 @@ export declare const CONTACT_COLUMN = "contact";
|
|
|
116
135
|
* the same reason.
|
|
117
136
|
*/
|
|
118
137
|
export declare const COLLET_SERIES_COLUMN = "CST";
|
|
138
|
+
/**
|
|
139
|
+
* The CSV column naming the series a collet **is** — `ER16`, `PG25`, `PGST15`.
|
|
140
|
+
*
|
|
141
|
+
* The other half of {@link COLLET_SERIES_COLUMN}, and deliberately a second
|
|
142
|
+
* column rather than the same one: `CST` is the series a *holder takes* and
|
|
143
|
+
* this is the series a *collet belongs to*, so the join between a holder family
|
|
144
|
+
* and a collet family is a comparison of the two. One column carrying both
|
|
145
|
+
* would make that join a row's comparison with itself.
|
|
146
|
+
*
|
|
147
|
+
* Vendor-neutral and here rather than in either adapter for the reason
|
|
148
|
+
* {@link CAD_COLUMN} is: Kennametal's ER collet tables and REGO-FIX's PG collet
|
|
149
|
+
* index both write it, and neither owns it. Both close the vendor's own spacing
|
|
150
|
+
* before writing, exactly as they do for `CST` — two spellings join to nothing.
|
|
151
|
+
*/
|
|
152
|
+
export declare const COLLET_DESIGNATION_COLUMN = "Collet Series";
|
|
119
153
|
/**
|
|
120
154
|
* The CSV columns carrying a holder's gage length, one per unit system.
|
|
121
155
|
*
|
|
@@ -188,6 +222,26 @@ export declare function dimensionalColumn(label: string, unit: string): string;
|
|
|
188
222
|
* indistinguishable from a scrape that lost it.
|
|
189
223
|
*/
|
|
190
224
|
export declare function identityColumns(brand: BrandName): readonly string[];
|
|
225
|
+
/**
|
|
226
|
+
* The identity column a human reads one part by.
|
|
227
|
+
*
|
|
228
|
+
* The catalog designation where the vendor publishes one, and the sole
|
|
229
|
+
* identifier where it does not — the **last** of {@link identityColumns},
|
|
230
|
+
* because that is the order the pair is written in and a deviation lists the
|
|
231
|
+
* one column its vendor has.
|
|
232
|
+
*
|
|
233
|
+
* A lookup rather than a read of the row, for the reason {@link identityColumns}
|
|
234
|
+
* gives: a header that is missing `ISO Catalog Number` is indistinguishable
|
|
235
|
+
* from a scrape that lost it, so a caller that fell back column by column would
|
|
236
|
+
* name half a family's files after part numbers and never say why.
|
|
237
|
+
*
|
|
238
|
+
* It exists because `node/cad-mirror.ts` names a mirrored file after the part
|
|
239
|
+
* it holds, and hardcoded `'ISO Catalog Number'` to do it. That is Kennametal's
|
|
240
|
+
* pair; MariTool publishes one number per part under `Material Number` and no
|
|
241
|
+
* catalog designation at all, so every one of its 357 STEP models was skipped
|
|
242
|
+
* with a warning that the row had no catalog number to name it.
|
|
243
|
+
*/
|
|
244
|
+
export declare function catalogColumn(brand: BrandName): string;
|
|
191
245
|
/**
|
|
192
246
|
* Every identity column `brand` claims is really in the CSV header.
|
|
193
247
|
*
|
package/dist/conventions.js
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* | `Description` carries the vendor's own free text | Harvey, MariTool |
|
|
23
23
|
* | `contact` says how a holder seats | REGO-FIX, MariTool |
|
|
24
24
|
* | `CST` names the collet series a holder takes | REGO-FIX, MariTool |
|
|
25
|
+
* | `Collet Series` names the series a collet is | Kennametal, REGO-FIX |
|
|
25
26
|
* | `L1_in`/`L1_mm` carry a holder's gage length | REGO-FIX, MariTool |
|
|
26
27
|
* | Unmapped vendor codes keep a `DIN_` prefix | REGO-FIX; rule is general |
|
|
27
28
|
* | The identity columns | **broken** — see below |
|
|
@@ -98,6 +99,24 @@ export const CAD_DXF_COLUMN = 'CAD_DXF_URL';
|
|
|
98
99
|
* `records.ToolRecord.description`, which states the same rule for the record.
|
|
99
100
|
*/
|
|
100
101
|
export const DESCRIPTION_COLUMN = 'Description';
|
|
102
|
+
/**
|
|
103
|
+
* The CSV column holding the vendor's own full name for the family a part is
|
|
104
|
+
* in — `KenCut™ FF • HPFT • Square End • 6 Flutes • Plain Shank • Inch`.
|
|
105
|
+
*
|
|
106
|
+
* Constant down a family's whole table, and that is what makes it a *family*
|
|
107
|
+
* title rather than a {@link DESCRIPTION_COLUMN}: it names the group, not the
|
|
108
|
+
* part. Kennametal and WIDIA publish one as the `h1` of a family page and it
|
|
109
|
+
* reaches the CSV whole, while `records.ToolRecord.productLine` keeps only its
|
|
110
|
+
* leading segment — the rest is the vendor's own wording for the shape, the
|
|
111
|
+
* flute count, the shank and the unit, and a receipt that dropped it would be
|
|
112
|
+
* throwing away published text to save a column.
|
|
113
|
+
*
|
|
114
|
+
* Vendor-neutral and here rather than in the Kennametal adapter for the reason
|
|
115
|
+
* {@link CAD_COLUMN} is: a second vendor that publishes a family title writes
|
|
116
|
+
* this column rather than inventing another. Nothing forces one to — a vendor
|
|
117
|
+
* whose parts carry no family title simply has no such column.
|
|
118
|
+
*/
|
|
119
|
+
export const FAMILY_TITLE_COLUMN = 'Family Title';
|
|
101
120
|
/**
|
|
102
121
|
* The CSV column saying how a holder seats in the spindle: `taper` or `face`.
|
|
103
122
|
*
|
|
@@ -117,6 +136,21 @@ export const CONTACT_COLUMN = 'contact';
|
|
|
117
136
|
* the same reason.
|
|
118
137
|
*/
|
|
119
138
|
export const COLLET_SERIES_COLUMN = 'CST';
|
|
139
|
+
/**
|
|
140
|
+
* The CSV column naming the series a collet **is** — `ER16`, `PG25`, `PGST15`.
|
|
141
|
+
*
|
|
142
|
+
* The other half of {@link COLLET_SERIES_COLUMN}, and deliberately a second
|
|
143
|
+
* column rather than the same one: `CST` is the series a *holder takes* and
|
|
144
|
+
* this is the series a *collet belongs to*, so the join between a holder family
|
|
145
|
+
* and a collet family is a comparison of the two. One column carrying both
|
|
146
|
+
* would make that join a row's comparison with itself.
|
|
147
|
+
*
|
|
148
|
+
* Vendor-neutral and here rather than in either adapter for the reason
|
|
149
|
+
* {@link CAD_COLUMN} is: Kennametal's ER collet tables and REGO-FIX's PG collet
|
|
150
|
+
* index both write it, and neither owns it. Both close the vendor's own spacing
|
|
151
|
+
* before writing, exactly as they do for `CST` — two spellings join to nothing.
|
|
152
|
+
*/
|
|
153
|
+
export const COLLET_DESIGNATION_COLUMN = 'Collet Series';
|
|
120
154
|
/**
|
|
121
155
|
* The CSV columns carrying a holder's gage length, one per unit system.
|
|
122
156
|
*
|
|
@@ -218,6 +252,31 @@ export function dimensionalColumn(label, unit) {
|
|
|
218
252
|
export function identityColumns(brand) {
|
|
219
253
|
return IDENTITY_DEVIATIONS[brand] ?? IDENTITY_COLUMNS;
|
|
220
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* The identity column a human reads one part by.
|
|
257
|
+
*
|
|
258
|
+
* The catalog designation where the vendor publishes one, and the sole
|
|
259
|
+
* identifier where it does not — the **last** of {@link identityColumns},
|
|
260
|
+
* because that is the order the pair is written in and a deviation lists the
|
|
261
|
+
* one column its vendor has.
|
|
262
|
+
*
|
|
263
|
+
* A lookup rather than a read of the row, for the reason {@link identityColumns}
|
|
264
|
+
* gives: a header that is missing `ISO Catalog Number` is indistinguishable
|
|
265
|
+
* from a scrape that lost it, so a caller that fell back column by column would
|
|
266
|
+
* name half a family's files after part numbers and never say why.
|
|
267
|
+
*
|
|
268
|
+
* It exists because `node/cad-mirror.ts` names a mirrored file after the part
|
|
269
|
+
* it holds, and hardcoded `'ISO Catalog Number'` to do it. That is Kennametal's
|
|
270
|
+
* pair; MariTool publishes one number per part under `Material Number` and no
|
|
271
|
+
* catalog designation at all, so every one of its 357 STEP models was skipped
|
|
272
|
+
* with a warning that the row had no catalog number to name it.
|
|
273
|
+
*/
|
|
274
|
+
export function catalogColumn(brand) {
|
|
275
|
+
const columns = identityColumns(brand);
|
|
276
|
+
// Non-null: `IDENTITY_COLUMNS` has two entries and every deviation has at
|
|
277
|
+
// least one, which `tests/conventions.test.ts` holds the table to.
|
|
278
|
+
return columns[columns.length - 1];
|
|
279
|
+
}
|
|
221
280
|
/**
|
|
222
281
|
* Every identity column `brand` claims is really in the CSV header.
|
|
223
282
|
*
|
package/dist/errors.d.ts
CHANGED
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
* cannot read.** The variants endpoint changed shape, a scrape's row count
|
|
11
11
|
* disagrees with the declared one, a DIN 4000 code that should be pinned is
|
|
12
12
|
* absent. The catalog is fine; the world moved.
|
|
13
|
+
* - {@link IncompletePartError} — **one part is missing a measurement it
|
|
14
|
+
* cannot be a part without.** A narrower case of the second, and the only
|
|
15
|
+
* one `registry.toRecords` may skip past: see below.
|
|
13
16
|
*
|
|
14
17
|
* They throw rather than exiting the process: a Node backend imports this, and
|
|
15
18
|
* a mapped column that moved must not take down somebody's request handler.
|
|
@@ -43,4 +46,31 @@ export declare class ScraperConfigError extends ScraperError {
|
|
|
43
46
|
*/
|
|
44
47
|
export declare class VendorResponseError extends ScraperError {
|
|
45
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* One part does not publish a dimension its kind requires.
|
|
51
|
+
*
|
|
52
|
+
* **The only failure a whole family survives.** `registry.toRecords` maps a
|
|
53
|
+
* family's rows together, so before this type existed every refusal was
|
|
54
|
+
* equally fatal: one part with an unpublished cell ended the conversion and
|
|
55
|
+
* took every other row with it. EMUGE-FRANKEN omits `overall length l₁` on
|
|
56
|
+
* roughly 175 of its 7,021 end mill variants, and both end mill families
|
|
57
|
+
* produced nothing at all because of them.
|
|
58
|
+
*
|
|
59
|
+
* It is a distinct type rather than a flag on {@link VendorResponseError}
|
|
60
|
+
* because the two must not be skipped alike. A cutting material this package
|
|
61
|
+
* has no word for, a point-angle column a family stopped mapping, a variants
|
|
62
|
+
* table that changed shape — those are the vendor's vocabulary or this
|
|
63
|
+
* package's map having moved, and skipping past them quietly is how a scraper
|
|
64
|
+
* starts publishing a catalog nobody checked. Only `columns.required` raises
|
|
65
|
+
* this one, and only for a cell the vendor left unpublished.
|
|
66
|
+
*
|
|
67
|
+
* **It is not a licence to relax a kind's contract.** `records.RECORD_GEOMETRY`
|
|
68
|
+
* still says an end mill always has an `OAL`, and that stays true of every
|
|
69
|
+
* record this package emits: a part without one does not become a record with
|
|
70
|
+
* a hole in it, it becomes no record and a warning. Where a *vendor* genuinely
|
|
71
|
+
* never publishes a field, the answer is still `sometimes` — that is what a
|
|
72
|
+
* drill's `SIG` is, and why one is a contract decision and the other is not.
|
|
73
|
+
*/
|
|
74
|
+
export declare class IncompletePartError extends VendorResponseError {
|
|
75
|
+
}
|
|
46
76
|
export {};
|
package/dist/errors.js
CHANGED
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
* cannot read.** The variants endpoint changed shape, a scrape's row count
|
|
11
11
|
* disagrees with the declared one, a DIN 4000 code that should be pinned is
|
|
12
12
|
* absent. The catalog is fine; the world moved.
|
|
13
|
+
* - {@link IncompletePartError} — **one part is missing a measurement it
|
|
14
|
+
* cannot be a part without.** A narrower case of the second, and the only
|
|
15
|
+
* one `registry.toRecords` may skip past: see below.
|
|
13
16
|
*
|
|
14
17
|
* They throw rather than exiting the process: a Node backend imports this, and
|
|
15
18
|
* a mapped column that moved must not take down somebody's request handler.
|
|
@@ -51,3 +54,30 @@ export class ScraperConfigError extends ScraperError {
|
|
|
51
54
|
*/
|
|
52
55
|
export class VendorResponseError extends ScraperError {
|
|
53
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* One part does not publish a dimension its kind requires.
|
|
59
|
+
*
|
|
60
|
+
* **The only failure a whole family survives.** `registry.toRecords` maps a
|
|
61
|
+
* family's rows together, so before this type existed every refusal was
|
|
62
|
+
* equally fatal: one part with an unpublished cell ended the conversion and
|
|
63
|
+
* took every other row with it. EMUGE-FRANKEN omits `overall length l₁` on
|
|
64
|
+
* roughly 175 of its 7,021 end mill variants, and both end mill families
|
|
65
|
+
* produced nothing at all because of them.
|
|
66
|
+
*
|
|
67
|
+
* It is a distinct type rather than a flag on {@link VendorResponseError}
|
|
68
|
+
* because the two must not be skipped alike. A cutting material this package
|
|
69
|
+
* has no word for, a point-angle column a family stopped mapping, a variants
|
|
70
|
+
* table that changed shape — those are the vendor's vocabulary or this
|
|
71
|
+
* package's map having moved, and skipping past them quietly is how a scraper
|
|
72
|
+
* starts publishing a catalog nobody checked. Only `columns.required` raises
|
|
73
|
+
* this one, and only for a cell the vendor left unpublished.
|
|
74
|
+
*
|
|
75
|
+
* **It is not a licence to relax a kind's contract.** `records.RECORD_GEOMETRY`
|
|
76
|
+
* still says an end mill always has an `OAL`, and that stays true of every
|
|
77
|
+
* record this package emits: a part without one does not become a record with
|
|
78
|
+
* a hole in it, it becomes no record and a warning. Where a *vendor* genuinely
|
|
79
|
+
* never publishes a field, the answer is still `sometimes` — that is what a
|
|
80
|
+
* drill's `SIG` is, and why one is a contract decision and the other is not.
|
|
81
|
+
*/
|
|
82
|
+
export class IncompletePartError extends VendorResponseError {
|
|
83
|
+
}
|
package/dist/families/emuge.d.ts
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* coating and the coolant supply **per part**, in columns, and a scraped column
|
|
9
9
|
* beats a family constant. Splitting by product line would turn four counted
|
|
10
10
|
* row totals into thirty and buy nothing a `product line` column does not
|
|
11
|
-
* already carry.
|
|
11
|
+
* already carry — and it is carried: `vendors/emuge/records.ts`'s
|
|
12
|
+
* `PRODUCT_LINE_COLUMNS` reads one per part onto `ToolRecord.productLine`, from
|
|
13
|
+
* a column every scrape already writes.
|
|
12
14
|
*
|
|
13
15
|
* So the only fact three of these four state is `unit`, and the fourth adds the
|
|
14
16
|
* two a drill record cannot be built without.
|
package/dist/families/emuge.js
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* coating and the coolant supply **per part**, in columns, and a scraped column
|
|
9
9
|
* beats a family constant. Splitting by product line would turn four counted
|
|
10
10
|
* row totals into thirty and buy nothing a `product line` column does not
|
|
11
|
-
* already carry.
|
|
11
|
+
* already carry — and it is carried: `vendors/emuge/records.ts`'s
|
|
12
|
+
* `PRODUCT_LINE_COLUMNS` reads one per part onto `ToolRecord.productLine`, from
|
|
13
|
+
* a column every scrape already writes.
|
|
12
14
|
*
|
|
13
15
|
* So the only fact three of these four state is `unit`, and the fourth adds the
|
|
14
16
|
* two a drill record cannot be built without.
|
|
@@ -100,9 +102,11 @@ export const FAMILIES = {
|
|
|
100
102
|
kind: 'drill',
|
|
101
103
|
familyCode: 'FB01',
|
|
102
104
|
// `SIG` is a mapped column and not a fact, which no other drill family in
|
|
103
|
-
// this package manages: EMUGE states a point angle on
|
|
104
|
-
//
|
|
105
|
-
//
|
|
105
|
+
// this package manages: EMUGE states a point angle on the detail record of
|
|
106
|
+
// 2,669 of these 2,670 parts, and leaves the cell empty on the last, so the
|
|
107
|
+
// record may carry no `SIG` — see `vendors/emuge/records.ts`'s `angle`.
|
|
108
|
+
// Kennametal's two drill lines assume theirs or derive them from a point
|
|
109
|
+
// length, and both say so at length in `families/kennametal.ts`.
|
|
106
110
|
columns: {
|
|
107
111
|
DC: 'nominal diameter d₁',
|
|
108
112
|
SFDM: 'Shank diameter d₂',
|
package/dist/family.d.ts
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import type { UnitSystem } from './conventions.js';
|
|
20
20
|
import type { BrandName } from './identity.js';
|
|
21
|
+
import type { HoldingMapper, ToolholdingKind } from './holding.js';
|
|
21
22
|
import type { Fact } from './provenance.js';
|
|
22
23
|
import type { ColumnMap, ToolKind, ToolRecord } from './records.js';
|
|
23
24
|
import type { MapperOptions, ScrapedRow } from './scrape.js';
|
|
@@ -121,8 +122,21 @@ export type BoundFamily = Omit<FamilyDefinition, 'columns'> & FamilyFacts & {
|
|
|
121
122
|
/** The adapter that turns this family's rows into records. */
|
|
122
123
|
readonly records: RecordMapper;
|
|
123
124
|
};
|
|
124
|
-
/**
|
|
125
|
-
|
|
125
|
+
/**
|
|
126
|
+
* A toolholding family after its facts have been checked and projected.
|
|
127
|
+
*
|
|
128
|
+
* `kind` is projected by the registry from **which table declared the family**,
|
|
129
|
+
* rather than being a key on {@link ToolholdingDefinition}: the table is the
|
|
130
|
+
* fact, and a `kind` beside it would be a second copy free to disagree with it.
|
|
131
|
+
* `records` is the mapper that brand binds for that kind, and it is optional
|
|
132
|
+
* because a vendor's holders may be scraped long before anybody has read its
|
|
133
|
+
* columns — see `holding.HoldingMappers`.
|
|
134
|
+
*/
|
|
135
|
+
export type BoundToolholding = ToolholdingDefinition & FamilyFacts & {
|
|
136
|
+
readonly kind: ToolholdingKind;
|
|
137
|
+
/** The adapter that turns this family's rows into records, where there is one. */
|
|
138
|
+
readonly records?: HoldingMapper;
|
|
139
|
+
};
|
|
126
140
|
/**
|
|
127
141
|
* A family's id: `<brand>:<vendor-local id>`.
|
|
128
142
|
*
|