@toolpath/tool-scraper 0.1.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/LICENSE +21 -0
- package/README.md +98 -0
- package/dist/conventions.d.ts +124 -0
- package/dist/conventions.js +143 -0
- package/dist/errors.d.ts +46 -0
- package/dist/errors.js +53 -0
- package/dist/families/destinytool.d.ts +49 -0
- package/dist/families/destinytool.js +55 -0
- package/dist/families/index.d.ts +59 -0
- package/dist/families/index.js +91 -0
- package/dist/families/kennametal.d.ts +757 -0
- package/dist/families/kennametal.js +660 -0
- package/dist/families/regofix.d.ts +185 -0
- package/dist/families/regofix.js +250 -0
- package/dist/family.d.ts +130 -0
- package/dist/family.js +38 -0
- package/dist/fetch.d.ts +98 -0
- package/dist/fetch.js +116 -0
- package/dist/identity.d.ts +133 -0
- package/dist/identity.js +118 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +31 -0
- package/dist/node/cad-mirror.d.ts +55 -0
- package/dist/node/cad-mirror.js +89 -0
- package/dist/node/cli.d.ts +35 -0
- package/dist/node/cli.js +340 -0
- package/dist/node/csv.d.ts +47 -0
- package/dist/node/csv.js +123 -0
- package/dist/node/index.d.ts +16 -0
- package/dist/node/index.js +16 -0
- package/dist/node/main.d.ts +13 -0
- package/dist/node/main.js +14 -0
- package/dist/node/paths.d.ts +60 -0
- package/dist/node/paths.js +80 -0
- package/dist/node/receipts.d.ts +100 -0
- package/dist/node/receipts.js +107 -0
- package/dist/order.d.ts +10 -0
- package/dist/order.js +12 -0
- package/dist/provenance.d.ts +125 -0
- package/dist/provenance.js +133 -0
- package/dist/records.d.ts +305 -0
- package/dist/records.js +297 -0
- package/dist/registry.d.ts +63 -0
- package/dist/registry.js +145 -0
- package/dist/scrape.d.ts +70 -0
- package/dist/scrape.js +37 -0
- package/dist/thread.d.ts +48 -0
- package/dist/thread.js +98 -0
- package/dist/uuid5.d.ts +31 -0
- package/dist/uuid5.js +64 -0
- package/dist/vendors/destinytool/index.d.ts +11 -0
- package/dist/vendors/destinytool/index.js +11 -0
- package/dist/vendors/destinytool/records.d.ts +118 -0
- package/dist/vendors/destinytool/records.js +266 -0
- package/dist/vendors/destinytool/scrape.d.ts +108 -0
- package/dist/vendors/destinytool/scrape.js +192 -0
- package/dist/vendors/kennametal/cad.d.ts +87 -0
- package/dist/vendors/kennametal/cad.js +119 -0
- package/dist/vendors/kennametal/index.d.ts +21 -0
- package/dist/vendors/kennametal/index.js +21 -0
- package/dist/vendors/kennametal/materials.d.ts +143 -0
- package/dist/vendors/kennametal/materials.js +200 -0
- package/dist/vendors/kennametal/records.d.ts +88 -0
- package/dist/vendors/kennametal/records.js +241 -0
- package/dist/vendors/kennametal/scrape.d.ts +111 -0
- package/dist/vendors/kennametal/scrape.js +226 -0
- package/dist/vendors/kennametal/thread-column.d.ts +28 -0
- package/dist/vendors/kennametal/thread-column.js +41 -0
- package/dist/vendors/regofix/index.d.ts +8 -0
- package/dist/vendors/regofix/index.js +8 -0
- package/dist/vendors/regofix/scrape.d.ts +237 -0
- package/dist/vendors/regofix/scrape.js +521 -0
- package/package.json +76 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REGO-FIX's families — toolholding only.
|
|
3
|
+
*
|
|
4
|
+
* There is no `FAMILIES` table here: REGO-FIX publishes no cutting tools, so this
|
|
5
|
+
* vendor never goes through a column map. What it publishes is powRgrip holders
|
|
6
|
+
* and the PG collets that press into them, and both are scraped from the
|
|
7
|
+
* ProductFinder's Elasticsearch index rather than from a family page — which is
|
|
8
|
+
* why there is no `familyCode` either. The scrape target is a set of index
|
|
9
|
+
* filters, and it lives with the scraper that posts them.
|
|
10
|
+
*/
|
|
11
|
+
export declare const HOLDER_FAMILIES: {
|
|
12
|
+
readonly 'regofix_bt30_pg_holders.csv': {
|
|
13
|
+
readonly catalogName: "REGO-FIX powRgrip BT30 Toolholders";
|
|
14
|
+
readonly rows: 21;
|
|
15
|
+
readonly brand: "regofix";
|
|
16
|
+
readonly facts: {
|
|
17
|
+
readonly taper: {
|
|
18
|
+
readonly value: "BT30";
|
|
19
|
+
readonly source: "vendor-stated";
|
|
20
|
+
readonly cite: "every row's DIN 4000 J1 property is DINISO7388-2 — the same 7/24 cone whether or not the flange face seats";
|
|
21
|
+
};
|
|
22
|
+
readonly clamping: {
|
|
23
|
+
readonly value: "collet";
|
|
24
|
+
readonly source: "vendor-stated";
|
|
25
|
+
readonly cite: "the holder publishes a CST collet series, so it grips through a collet";
|
|
26
|
+
};
|
|
27
|
+
readonly style: {
|
|
28
|
+
readonly value: "pg-collet-chuck";
|
|
29
|
+
readonly source: "vendor-stated";
|
|
30
|
+
readonly cite: "REGO-FIX's own system name, /products/system/powrgrip";
|
|
31
|
+
};
|
|
32
|
+
readonly unit: {
|
|
33
|
+
readonly value: "millimeters";
|
|
34
|
+
readonly source: "vendor-stated";
|
|
35
|
+
readonly cite: "the family is titled and catalogued in this system; both unit columns are usually published, so this decides which is displayed";
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
export declare const COLLET_FAMILIES: {
|
|
41
|
+
readonly 'regofix_pg_collets_standard.csv': {
|
|
42
|
+
readonly catalogName: "REGO-FIX powRgrip PG Standard Collets";
|
|
43
|
+
readonly rows: 71;
|
|
44
|
+
readonly brand: "regofix";
|
|
45
|
+
readonly facts: {
|
|
46
|
+
readonly style: {
|
|
47
|
+
readonly value: "pg-standard";
|
|
48
|
+
readonly source: "vendor-stated";
|
|
49
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'Standard'";
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
readonly 'regofix_pg_collets_coolant_flush.csv': {
|
|
54
|
+
readonly catalogName: "REGO-FIX powRgrip PG Coolant Flush Collets";
|
|
55
|
+
readonly rows: 51;
|
|
56
|
+
readonly brand: "regofix";
|
|
57
|
+
readonly facts: {
|
|
58
|
+
readonly style: {
|
|
59
|
+
readonly value: "pg-coolant-flush";
|
|
60
|
+
readonly source: "vendor-stated";
|
|
61
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'Coolant flush'";
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
readonly 'regofix_pg_collets_short.csv': {
|
|
66
|
+
readonly catalogName: "REGO-FIX powRgrip PG Short Collets";
|
|
67
|
+
readonly rows: 34;
|
|
68
|
+
readonly brand: "regofix";
|
|
69
|
+
readonly facts: {
|
|
70
|
+
readonly style: {
|
|
71
|
+
readonly value: "pg-short";
|
|
72
|
+
readonly source: "vendor-stated";
|
|
73
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'Short'";
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
readonly 'regofix_pg_collets_cool_bore.csv': {
|
|
78
|
+
readonly catalogName: "REGO-FIX powRgrip PG Cool Bore Collets";
|
|
79
|
+
readonly rows: 30;
|
|
80
|
+
readonly brand: "regofix";
|
|
81
|
+
readonly facts: {
|
|
82
|
+
readonly style: {
|
|
83
|
+
readonly value: "pg-cool-bore";
|
|
84
|
+
readonly source: "vendor-stated";
|
|
85
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'Cool bore'";
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
readonly 'regofix_pgst_collets.csv': {
|
|
90
|
+
readonly catalogName: "REGO-FIX powRgrip PGST Short Tail Collets";
|
|
91
|
+
readonly rows: 28;
|
|
92
|
+
readonly brand: "regofix";
|
|
93
|
+
readonly facts: {
|
|
94
|
+
readonly style: {
|
|
95
|
+
readonly value: "pgst-short-tail";
|
|
96
|
+
readonly source: "vendor-stated";
|
|
97
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'PGST'";
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
readonly 'regofix_pg_collets_tap.csv': {
|
|
102
|
+
readonly catalogName: "REGO-FIX powRgrip PG Tapping Collets";
|
|
103
|
+
readonly rows: 26;
|
|
104
|
+
readonly brand: "regofix";
|
|
105
|
+
readonly facts: {
|
|
106
|
+
readonly style: {
|
|
107
|
+
readonly value: "pg-tap";
|
|
108
|
+
readonly source: "vendor-stated";
|
|
109
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'Tapping collet TAP'";
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
readonly 'regofix_pg_collets_long.csv': {
|
|
114
|
+
readonly catalogName: "REGO-FIX powRgrip PG Long Collets";
|
|
115
|
+
readonly rows: 21;
|
|
116
|
+
readonly brand: "regofix";
|
|
117
|
+
readonly facts: {
|
|
118
|
+
readonly style: {
|
|
119
|
+
readonly value: "pg-long";
|
|
120
|
+
readonly source: "vendor-stated";
|
|
121
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'Long'";
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
readonly 'regofix_pg_collets_microbore.csv': {
|
|
126
|
+
readonly catalogName: "REGO-FIX powRgrip PG Microbore Collets";
|
|
127
|
+
readonly rows: 16;
|
|
128
|
+
readonly brand: "regofix";
|
|
129
|
+
readonly facts: {
|
|
130
|
+
readonly style: {
|
|
131
|
+
readonly value: "pg-microbore";
|
|
132
|
+
readonly source: "vendor-stated";
|
|
133
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'Microbore'";
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
readonly 'regofix_pg_collets_turning.csv': {
|
|
138
|
+
readonly catalogName: "REGO-FIX powRgrip PG Turning Collets";
|
|
139
|
+
readonly rows: 16;
|
|
140
|
+
readonly brand: "regofix";
|
|
141
|
+
readonly facts: {
|
|
142
|
+
readonly style: {
|
|
143
|
+
readonly value: "pg-turning";
|
|
144
|
+
readonly source: "vendor-stated";
|
|
145
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'PG-T'";
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
readonly 'regofix_pg_collets_mql.csv': {
|
|
150
|
+
readonly catalogName: "REGO-FIX powRgrip PG MQL Collets";
|
|
151
|
+
readonly rows: 11;
|
|
152
|
+
readonly brand: "regofix";
|
|
153
|
+
readonly facts: {
|
|
154
|
+
readonly style: {
|
|
155
|
+
readonly value: "pg-mql";
|
|
156
|
+
readonly source: "vendor-stated";
|
|
157
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'PG-MQL'";
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
readonly 'regofix_pg_collets_securgrip.csv': {
|
|
162
|
+
readonly catalogName: "REGO-FIX powRgrip PG secuRgrip Collets";
|
|
163
|
+
readonly rows: 10;
|
|
164
|
+
readonly brand: "regofix";
|
|
165
|
+
readonly facts: {
|
|
166
|
+
readonly style: {
|
|
167
|
+
readonly value: "pg-securgrip";
|
|
168
|
+
readonly source: "vendor-stated";
|
|
169
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'secuRgrip'";
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
readonly 'regofix_pg_collets_sealed_cap.csv': {
|
|
174
|
+
readonly catalogName: "REGO-FIX powRgrip PG Sealed Cap Collets";
|
|
175
|
+
readonly rows: 7;
|
|
176
|
+
readonly brand: "regofix";
|
|
177
|
+
readonly facts: {
|
|
178
|
+
readonly style: {
|
|
179
|
+
readonly value: "pg-sealed-cap";
|
|
180
|
+
readonly source: "vendor-stated";
|
|
181
|
+
readonly cite: "the ProductFinder index groups these under product_group_name 'PG-SC'";
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
};
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REGO-FIX's families — toolholding only.
|
|
3
|
+
*
|
|
4
|
+
* There is no `FAMILIES` table here: REGO-FIX publishes no cutting tools, so this
|
|
5
|
+
* vendor never goes through a column map. What it publishes is powRgrip holders
|
|
6
|
+
* and the PG collets that press into them, and both are scraped from the
|
|
7
|
+
* ProductFinder's Elasticsearch index rather than from a family page — which is
|
|
8
|
+
* why there is no `familyCode` either. The scrape target is a set of index
|
|
9
|
+
* filters, and it lives with the scraper that posts them.
|
|
10
|
+
*/
|
|
11
|
+
export const HOLDER_FAMILIES = {
|
|
12
|
+
// ── REGO-FIX powRgrip, BT 30 (JG 2026-08-07) ───────────────────────────
|
|
13
|
+
// The first non-Kennametal toolholding family, and the first one whose
|
|
14
|
+
// `contact` is **not** here. REGO-FIX publishes plain and dual-contact BT30
|
|
15
|
+
// in one product group — `BT 30 / PG 25 x 080 H` and `BT+ 30 / PG 25 x 080
|
|
16
|
+
// H` are two rows of one table — and states which is which in a `form_name`
|
|
17
|
+
// field. So the CSV carries a `contact` column, and the rule is that a
|
|
18
|
+
// scraped fact beats a family constant. There is deliberately no `contact`
|
|
19
|
+
// key below; supplying one would silently mask a scrape that lost the
|
|
20
|
+
// column.
|
|
21
|
+
//
|
|
22
|
+
// `clamping: 'collet'` and `style: 'pg-collet-chuck'`. A powRgrip holder
|
|
23
|
+
// takes a PG collet, which is pressed in with a hydraulic clamping unit
|
|
24
|
+
// rather than closed by a nut — so it grips through a collet exactly as an
|
|
25
|
+
// ER chuck does, and the picker asks it the same question. What differs is
|
|
26
|
+
// that seating one needs a PGU/PGS press on the bench, which is why it is
|
|
27
|
+
// its own `style` and not `er-collet-chuck` with a different series.
|
|
28
|
+
// REGO-FIX's own words for the line are "powRgrip" and "PG toolholders"
|
|
29
|
+
// (`/en/products/system/powrgrip`, `/en/products/components/toolholders/
|
|
30
|
+
// powRgrip`).
|
|
31
|
+
//
|
|
32
|
+
// **`taper: 'BT30'` covers BT+ 30 too**, the same call BTKV30 got and for
|
|
33
|
+
// the same reason: the vendor's own `J1` property is `DINISO7388-2` on
|
|
34
|
+
// every one of these rows, plus-form included, so the cone is identical and
|
|
35
|
+
// the plus is a face that also seats. Recording `BT+30` as a taper would
|
|
36
|
+
// hide ten holders from every BT30 filter.
|
|
37
|
+
//
|
|
38
|
+
// `rows` is 21 against 22 in the vendor's group: `4130.71506` (BT+ 30 / PG
|
|
39
|
+
// 15 x 075 H) has DXF and PDF drawings but no DIN 4000 document, so it has
|
|
40
|
+
// no published gage length and is skipped by the scraper with a message.
|
|
41
|
+
// The three `BT-OM 30` parts are excluded at a different level — see
|
|
42
|
+
// `vendors/regofix/scrape.ts`'s `SCRAPED_TAPERS` — because nothing on the
|
|
43
|
+
// vendor's site says what OM designates.
|
|
44
|
+
'regofix_bt30_pg_holders.csv': {
|
|
45
|
+
catalogName: 'REGO-FIX powRgrip BT30 Toolholders',
|
|
46
|
+
rows: 21,
|
|
47
|
+
brand: 'regofix',
|
|
48
|
+
facts: {
|
|
49
|
+
taper: {
|
|
50
|
+
value: 'BT30',
|
|
51
|
+
source: 'vendor-stated',
|
|
52
|
+
cite: "every row's DIN 4000 J1 property is DINISO7388-2 — the same 7/24 cone whether or not the flange face seats",
|
|
53
|
+
},
|
|
54
|
+
clamping: {
|
|
55
|
+
value: 'collet',
|
|
56
|
+
source: 'vendor-stated',
|
|
57
|
+
cite: 'the holder publishes a CST collet series, so it grips through a collet',
|
|
58
|
+
},
|
|
59
|
+
style: {
|
|
60
|
+
value: 'pg-collet-chuck',
|
|
61
|
+
source: 'vendor-stated',
|
|
62
|
+
cite: "REGO-FIX's own system name, /products/system/powrgrip",
|
|
63
|
+
},
|
|
64
|
+
unit: {
|
|
65
|
+
value: 'millimeters',
|
|
66
|
+
source: 'vendor-stated',
|
|
67
|
+
cite: 'the family is titled and catalogued in this system; both unit columns are usually published, so this decides which is displayed',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
export const COLLET_FAMILIES = {
|
|
73
|
+
// ── REGO-FIX powRgrip PG collets (JG 2026-08-07) ───────────────────────
|
|
74
|
+
// Twelve product groups, restricted to the PG series a BT30 holder takes
|
|
75
|
+
// (6, 10, 15, 25). PG 32 and PG 48 collets exist and no BT30 holder in this
|
|
76
|
+
// catalog accepts one.
|
|
77
|
+
//
|
|
78
|
+
// **None of these declares a `unit`, and that is the change this package
|
|
79
|
+
// promised itself.** Every group holds metric and fractional-inch collets
|
|
80
|
+
// side by side — `PG 25 Ø 6.0 mm` and `PG 25 Ø 1/4"` are two rows of one
|
|
81
|
+
// group — so there is no family-level answer to declare. The unit is a
|
|
82
|
+
// column. Kennametal's TT HPV family is the one place a mixed family was
|
|
83
|
+
// handled by splitting the CSV, and the note there says a second one means
|
|
84
|
+
// making the unit per-record instead of splitting twice. This is that
|
|
85
|
+
// second one, twelve times over.
|
|
86
|
+
//
|
|
87
|
+
// **`style` is the vendor's own product group**, not a coinage: each value
|
|
88
|
+
// below is a slug of `product_group_name` in the ProductFinder index, and
|
|
89
|
+
// a consumer's label for it comes from the matching
|
|
90
|
+
// `product_category_name`. Both are re-checkable with one POST to the
|
|
91
|
+
// endpoint in `REGOFIX_PRODUCTFINDER_API.md` — no browser, no scraper
|
|
92
|
+
// change. They are config rather than a scraped column for the same reason
|
|
93
|
+
// Kennametal's are: constant per family, and this table is where per-family
|
|
94
|
+
// constants live.
|
|
95
|
+
//
|
|
96
|
+
// **PGST is a separate series, not a PG collet.** Its parts are designated
|
|
97
|
+
// `PGST 15`, REGO-FIX sells dedicated `.../PGST Short Tail` toolholders for
|
|
98
|
+
// them, and nothing published says whether a PGST collet also seats in a
|
|
99
|
+
// plain PG holder. `collet_row` therefore writes the series exactly as the
|
|
100
|
+
// vendor designates it, so a PGST collet matches no PG holder. That is the
|
|
101
|
+
// conservative direction on purpose: hiding a collet that would have fitted
|
|
102
|
+
// costs an option, while offering one that does not fit costs a machinist a
|
|
103
|
+
// purchase. Resolve it by asking REGO-FIX, not by widening the string.
|
|
104
|
+
// Today no BT30 short-tail holder exists either way, so all 28 sit in the
|
|
105
|
+
// catalog fitting nothing.
|
|
106
|
+
'regofix_pg_collets_standard.csv': {
|
|
107
|
+
catalogName: 'REGO-FIX powRgrip PG Standard Collets',
|
|
108
|
+
rows: 71,
|
|
109
|
+
brand: 'regofix',
|
|
110
|
+
facts: {
|
|
111
|
+
style: {
|
|
112
|
+
value: 'pg-standard',
|
|
113
|
+
source: 'vendor-stated',
|
|
114
|
+
cite: "the ProductFinder index groups these under product_group_name 'Standard'",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
'regofix_pg_collets_coolant_flush.csv': {
|
|
119
|
+
catalogName: 'REGO-FIX powRgrip PG Coolant Flush Collets',
|
|
120
|
+
rows: 51,
|
|
121
|
+
brand: 'regofix',
|
|
122
|
+
facts: {
|
|
123
|
+
style: {
|
|
124
|
+
value: 'pg-coolant-flush',
|
|
125
|
+
source: 'vendor-stated',
|
|
126
|
+
cite: "the ProductFinder index groups these under product_group_name 'Coolant flush'",
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
'regofix_pg_collets_short.csv': {
|
|
131
|
+
catalogName: 'REGO-FIX powRgrip PG Short Collets',
|
|
132
|
+
rows: 34,
|
|
133
|
+
brand: 'regofix',
|
|
134
|
+
facts: {
|
|
135
|
+
style: {
|
|
136
|
+
value: 'pg-short',
|
|
137
|
+
source: 'vendor-stated',
|
|
138
|
+
cite: "the ProductFinder index groups these under product_group_name 'Short'",
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
'regofix_pg_collets_cool_bore.csv': {
|
|
143
|
+
catalogName: 'REGO-FIX powRgrip PG Cool Bore Collets',
|
|
144
|
+
rows: 30,
|
|
145
|
+
brand: 'regofix',
|
|
146
|
+
facts: {
|
|
147
|
+
style: {
|
|
148
|
+
value: 'pg-cool-bore',
|
|
149
|
+
source: 'vendor-stated',
|
|
150
|
+
cite: "the ProductFinder index groups these under product_group_name 'Cool bore'",
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
'regofix_pgst_collets.csv': {
|
|
155
|
+
catalogName: 'REGO-FIX powRgrip PGST Short Tail Collets',
|
|
156
|
+
rows: 28,
|
|
157
|
+
brand: 'regofix',
|
|
158
|
+
facts: {
|
|
159
|
+
style: {
|
|
160
|
+
value: 'pgst-short-tail',
|
|
161
|
+
source: 'vendor-stated',
|
|
162
|
+
cite: "the ProductFinder index groups these under product_group_name 'PGST'",
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
'regofix_pg_collets_tap.csv': {
|
|
167
|
+
catalogName: 'REGO-FIX powRgrip PG Tapping Collets',
|
|
168
|
+
rows: 26,
|
|
169
|
+
brand: 'regofix',
|
|
170
|
+
facts: {
|
|
171
|
+
style: {
|
|
172
|
+
value: 'pg-tap',
|
|
173
|
+
source: 'vendor-stated',
|
|
174
|
+
cite: "the ProductFinder index groups these under product_group_name 'Tapping collet TAP'",
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
'regofix_pg_collets_long.csv': {
|
|
179
|
+
catalogName: 'REGO-FIX powRgrip PG Long Collets',
|
|
180
|
+
rows: 21,
|
|
181
|
+
brand: 'regofix',
|
|
182
|
+
facts: {
|
|
183
|
+
style: {
|
|
184
|
+
value: 'pg-long',
|
|
185
|
+
source: 'vendor-stated',
|
|
186
|
+
cite: "the ProductFinder index groups these under product_group_name 'Long'",
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
'regofix_pg_collets_microbore.csv': {
|
|
191
|
+
catalogName: 'REGO-FIX powRgrip PG Microbore Collets',
|
|
192
|
+
rows: 16,
|
|
193
|
+
brand: 'regofix',
|
|
194
|
+
facts: {
|
|
195
|
+
style: {
|
|
196
|
+
value: 'pg-microbore',
|
|
197
|
+
source: 'vendor-stated',
|
|
198
|
+
cite: "the ProductFinder index groups these under product_group_name 'Microbore'",
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
'regofix_pg_collets_turning.csv': {
|
|
203
|
+
catalogName: 'REGO-FIX powRgrip PG Turning Collets',
|
|
204
|
+
rows: 16,
|
|
205
|
+
brand: 'regofix',
|
|
206
|
+
facts: {
|
|
207
|
+
style: {
|
|
208
|
+
value: 'pg-turning',
|
|
209
|
+
source: 'vendor-stated',
|
|
210
|
+
cite: "the ProductFinder index groups these under product_group_name 'PG-T'",
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
'regofix_pg_collets_mql.csv': {
|
|
215
|
+
catalogName: 'REGO-FIX powRgrip PG MQL Collets',
|
|
216
|
+
rows: 11,
|
|
217
|
+
brand: 'regofix',
|
|
218
|
+
facts: {
|
|
219
|
+
style: {
|
|
220
|
+
value: 'pg-mql',
|
|
221
|
+
source: 'vendor-stated',
|
|
222
|
+
cite: "the ProductFinder index groups these under product_group_name 'PG-MQL'",
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
'regofix_pg_collets_securgrip.csv': {
|
|
227
|
+
catalogName: 'REGO-FIX powRgrip PG secuRgrip Collets',
|
|
228
|
+
rows: 10,
|
|
229
|
+
brand: 'regofix',
|
|
230
|
+
facts: {
|
|
231
|
+
style: {
|
|
232
|
+
value: 'pg-securgrip',
|
|
233
|
+
source: 'vendor-stated',
|
|
234
|
+
cite: "the ProductFinder index groups these under product_group_name 'secuRgrip'",
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
'regofix_pg_collets_sealed_cap.csv': {
|
|
239
|
+
catalogName: 'REGO-FIX powRgrip PG Sealed Cap Collets',
|
|
240
|
+
rows: 7,
|
|
241
|
+
brand: 'regofix',
|
|
242
|
+
facts: {
|
|
243
|
+
style: {
|
|
244
|
+
value: 'pg-sealed-cap',
|
|
245
|
+
source: 'vendor-stated',
|
|
246
|
+
cite: "the ProductFinder index groups these under product_group_name 'PG-SC'",
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
};
|
package/dist/family.d.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a family declares, and what it looks like once the registry has bound it.
|
|
3
|
+
*
|
|
4
|
+
* `families/` is the config table: what to fetch, how its columns are
|
|
5
|
+
* labelled, and the per-family constants no vendor table states. This module
|
|
6
|
+
* is the *shape* of one, kept apart from the tables themselves so that
|
|
7
|
+
* `families/` stays data and `registry` stays the only module that knows both
|
|
8
|
+
* halves.
|
|
9
|
+
*
|
|
10
|
+
* ## Facts are the only place a constant is authored
|
|
11
|
+
*
|
|
12
|
+
* A constant is authored as a {@link Fact} and nowhere else:
|
|
13
|
+
* {@link FamilyDefinition} declares `facts` and no constant keys, so setting
|
|
14
|
+
* one directly does not compile. The projection still happens —
|
|
15
|
+
* {@link BoundFamily} carries the values under their own names, and a mapper
|
|
16
|
+
* says `family.pointAngle` and never learns about provenance — but there is
|
|
17
|
+
* only ever one authored copy to drift from.
|
|
18
|
+
*/
|
|
19
|
+
import type { UnitSystem } from './conventions.js';
|
|
20
|
+
import type { BrandName } from './identity.js';
|
|
21
|
+
import type { Fact } from './provenance.js';
|
|
22
|
+
import type { ColumnMap, ToolKind, ToolRecord } from './records.js';
|
|
23
|
+
import type { MapperOptions, ScrapedRow } from './scrape.js';
|
|
24
|
+
/**
|
|
25
|
+
* The per-family constants a fact can carry, and their types.
|
|
26
|
+
*
|
|
27
|
+
* Ten keys, which is the whole vocabulary the catalog uses. Naming them rather
|
|
28
|
+
* than accepting any string is what lets a mapper read `family.coolantThrough`
|
|
29
|
+
* as a `boolean` instead of casting an `unknown` out of a bag — and what makes
|
|
30
|
+
* a fact whose value is the wrong type a compile error where the family is
|
|
31
|
+
* written.
|
|
32
|
+
*/
|
|
33
|
+
export interface FamilyFacts {
|
|
34
|
+
/** Which unit system this family's dimensional columns are published in. */
|
|
35
|
+
unit?: UnitSystem;
|
|
36
|
+
/** Cutting-material code — `carbide`, `hss`, `diamond`. */
|
|
37
|
+
bmc?: string;
|
|
38
|
+
coolantThrough?: boolean;
|
|
39
|
+
flutes?: number;
|
|
40
|
+
/** Degrees included. */
|
|
41
|
+
pointAngle?: number;
|
|
42
|
+
nonFerrous?: boolean;
|
|
43
|
+
/** The holder or collet product style, as the vendor names it. */
|
|
44
|
+
style?: string;
|
|
45
|
+
/** `BT30`, `CAT40` — the spindle interface. */
|
|
46
|
+
taper?: string;
|
|
47
|
+
/** How the holder grips: `collet`, `hydraulic`, `shrink`. */
|
|
48
|
+
clamping?: string;
|
|
49
|
+
/** `taper` or `face` — whether the flange face seats as well as the cone. */
|
|
50
|
+
contact?: string;
|
|
51
|
+
}
|
|
52
|
+
/** A family's facts, each carrying the type its projected value will have. */
|
|
53
|
+
export type FactSet = {
|
|
54
|
+
[K in keyof FamilyFacts]?: Fact<NonNullable<FamilyFacts[K]>>;
|
|
55
|
+
};
|
|
56
|
+
/** One CSV row -> one record. An adapter supplies these, keyed by tool kind. */
|
|
57
|
+
export type RecordMapper = (row: ScrapedRow, family: BoundFamily, columns: ColumnMap, options?: MapperOptions) => ToolRecord;
|
|
58
|
+
/** A vendor adapter's mappers, by the kind of tool they build. */
|
|
59
|
+
export type RecordMappers = Partial<Record<ToolKind, RecordMapper>>;
|
|
60
|
+
/** What every family declares, cutting tool or toolholding alike. */
|
|
61
|
+
interface CommonDefinition {
|
|
62
|
+
/**
|
|
63
|
+
* How many rows a human counted in this CSV at scrape time.
|
|
64
|
+
*
|
|
65
|
+
* The one key here that no code needs. It is an independent restatement,
|
|
66
|
+
* which is the whole value: every other count is computed from the same file
|
|
67
|
+
* it is checking, so a scrape that silently lost rows agrees with itself. It
|
|
68
|
+
* is per family and not a total, because a total hides the case it exists to
|
|
69
|
+
* catch — one family gaining a row while another loses one sums to no change.
|
|
70
|
+
*/
|
|
71
|
+
readonly rows: number;
|
|
72
|
+
/** Defaults to `kennametal` when a family does not name one. */
|
|
73
|
+
readonly brand?: BrandName;
|
|
74
|
+
readonly facts?: FactSet;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A cutting-tool family: something with a column map and a record mapper.
|
|
78
|
+
*
|
|
79
|
+
* `columns` holds the vendor's own column labels keyed by canonical ISO 13399
|
|
80
|
+
* name, *without* a unit suffix — `registry` runs each through
|
|
81
|
+
* `records.checkColumnMap`, so a typo fails when the registry binds, naming
|
|
82
|
+
* the family.
|
|
83
|
+
*/
|
|
84
|
+
export interface FamilyDefinition extends CommonDefinition {
|
|
85
|
+
/**
|
|
86
|
+
* The vendor-local half of the family id, kebab-cased.
|
|
87
|
+
*
|
|
88
|
+
* What lets a REGO-FIX family be called whatever REGO-FIX calls it without
|
|
89
|
+
* checking Kennametal's list first — see {@link familyId}.
|
|
90
|
+
*/
|
|
91
|
+
readonly id: string;
|
|
92
|
+
readonly kind: ToolKind;
|
|
93
|
+
/**
|
|
94
|
+
* The vendor's own code for the family, where the scrape target is a family
|
|
95
|
+
* page. Absent where it is a set of index filters instead.
|
|
96
|
+
*/
|
|
97
|
+
readonly familyCode?: string;
|
|
98
|
+
readonly columns: Readonly<Record<string, string>>;
|
|
99
|
+
}
|
|
100
|
+
/** A holder or collet family: no column map, no record mapper, no kind. */
|
|
101
|
+
export interface ToolholdingDefinition extends CommonDefinition {
|
|
102
|
+
/** What a human calls this family. Holders and collets have no `id`. */
|
|
103
|
+
readonly catalogName: string;
|
|
104
|
+
}
|
|
105
|
+
/** A cutting-tool family after {@link FamilyDefinition} has been validated. */
|
|
106
|
+
export type BoundFamily = Omit<FamilyDefinition, 'columns'> & FamilyFacts & {
|
|
107
|
+
/** The validated map. Only `checkColumnMap` can produce one. */
|
|
108
|
+
readonly columns: ColumnMap;
|
|
109
|
+
/** The adapter that turns this family's rows into records. */
|
|
110
|
+
readonly records: RecordMapper;
|
|
111
|
+
};
|
|
112
|
+
/** A toolholding family after its facts have been checked and projected. */
|
|
113
|
+
export type BoundToolholding = ToolholdingDefinition & FamilyFacts;
|
|
114
|
+
/**
|
|
115
|
+
* A family's id: `<brand>:<vendor-local id>`.
|
|
116
|
+
*
|
|
117
|
+
* Bare filename stems were the id in the source package until 2026-08-08 —
|
|
118
|
+
* `godrill_3xd_metric` — and they are a route parameter and a join key
|
|
119
|
+
* downstream. With one vendor there was no collision to fix; with four there
|
|
120
|
+
* is a latent one the moment two ship a family called `endmills_metric`, and
|
|
121
|
+
* it would land as a route that resolves to whichever library was read last.
|
|
122
|
+
*
|
|
123
|
+
* The **colon** is deliberate: it is a legal `pchar` in a URL path segment
|
|
124
|
+
* (RFC 3986), so `/family/kennametal:godrill-3xd-metric` needs no encoding and
|
|
125
|
+
* stays one route parameter.
|
|
126
|
+
*/
|
|
127
|
+
export declare function familyId(cfg: FamilyDefinition | BoundFamily): string;
|
|
128
|
+
/** The brand that published a family, defaulting as the catalog does. */
|
|
129
|
+
export declare function familyBrand(cfg: CommonDefinition | BoundFamily | BoundToolholding): BrandName;
|
|
130
|
+
export {};
|
package/dist/family.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a family declares, and what it looks like once the registry has bound it.
|
|
3
|
+
*
|
|
4
|
+
* `families/` is the config table: what to fetch, how its columns are
|
|
5
|
+
* labelled, and the per-family constants no vendor table states. This module
|
|
6
|
+
* is the *shape* of one, kept apart from the tables themselves so that
|
|
7
|
+
* `families/` stays data and `registry` stays the only module that knows both
|
|
8
|
+
* halves.
|
|
9
|
+
*
|
|
10
|
+
* ## Facts are the only place a constant is authored
|
|
11
|
+
*
|
|
12
|
+
* A constant is authored as a {@link Fact} and nowhere else:
|
|
13
|
+
* {@link FamilyDefinition} declares `facts` and no constant keys, so setting
|
|
14
|
+
* one directly does not compile. The projection still happens —
|
|
15
|
+
* {@link BoundFamily} carries the values under their own names, and a mapper
|
|
16
|
+
* says `family.pointAngle` and never learns about provenance — but there is
|
|
17
|
+
* only ever one authored copy to drift from.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* A family's id: `<brand>:<vendor-local id>`.
|
|
21
|
+
*
|
|
22
|
+
* Bare filename stems were the id in the source package until 2026-08-08 —
|
|
23
|
+
* `godrill_3xd_metric` — and they are a route parameter and a join key
|
|
24
|
+
* downstream. With one vendor there was no collision to fix; with four there
|
|
25
|
+
* is a latent one the moment two ship a family called `endmills_metric`, and
|
|
26
|
+
* it would land as a route that resolves to whichever library was read last.
|
|
27
|
+
*
|
|
28
|
+
* The **colon** is deliberate: it is a legal `pchar` in a URL path segment
|
|
29
|
+
* (RFC 3986), so `/family/kennametal:godrill-3xd-metric` needs no encoding and
|
|
30
|
+
* stays one route parameter.
|
|
31
|
+
*/
|
|
32
|
+
export function familyId(cfg) {
|
|
33
|
+
return `${cfg.brand ?? 'kennametal'}:${cfg.id}`;
|
|
34
|
+
}
|
|
35
|
+
/** The brand that published a family, defaulting as the catalog does. */
|
|
36
|
+
export function familyBrand(cfg) {
|
|
37
|
+
return cfg.brand ?? 'kennametal';
|
|
38
|
+
}
|