@toolpath/dfm 0.4.0 → 1.0.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/README.md CHANGED
@@ -1,194 +1,83 @@
1
1
  # Toolpath DFM
2
2
 
3
- `@toolpath/dfm` is the DFM (design for manufacturing) rule list: each rule
4
- written as the sentence it is — "Holes with L/D to top of part ≥ 8" — whose
5
- words are its fields, beside its colour and how many of a part's features
6
- break it. Under the list, Import, Export and Copy LLM prompt share a rule set
7
- as one JSON file.
3
+ `@toolpath/dfm` is the DFM (design for manufacturing) rules and the part
4
+ checker: what a rule is, how a part's features break it, and the rule-set file
5
+ a set is shared in. **It is logic, data types and functions only** — no React,
6
+ no DOM, no CSS — so a server route can import it as readily as a browser.
8
7
 
9
- It also draws a feature's reach chart: the walls beside the feature, how high
10
- they stand and how far out.
11
-
12
- And it shows a feature as the Engine read it — the feature panel: the features
13
- a clicked face could mean, the rules the chosen one breaks, what was measured
14
- of it, its reach, and its datasheet as sent. Its pinch points, the widest tool
15
- standing where the feature is tightest, are placed here and drawn by
16
- `@toolpath/viewer`.
17
-
18
- The rules and the checker that counts them ship too, with no React, under
19
- `@toolpath/dfm/model`.
8
+ The views that show and edit the rules — `RuleList`, `ReachChart`,
9
+ `FeaturePanel` — are in [`@toolpath/ui`](https://www.npmjs.com/package/@toolpath/ui).
20
10
 
21
11
  ## Install
22
12
 
23
13
  ```sh
24
- npm install @toolpath/dfm @toolpath/ui react react-dom
25
- ```
26
-
27
- Add the styles after Tailwind and the `@toolpath/ui` theme:
28
-
29
- ```css
30
- @import 'tailwindcss';
31
- @import '@toolpath/ui/theme.css';
32
- @import '@toolpath/dfm/dfm.css';
14
+ npm install @toolpath/dfm
33
15
  ```
34
16
 
35
17
  ## Exports
36
18
 
37
- | Entry point | What it is |
38
- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
39
- | `@toolpath/dfm` | `RuleList`, `Swatch`, the list's keyboard helpers, `ReachChart`, `ReachDrawing`, the feature panel (`FeaturePanel`, `FeatureDetails`, `CandidateList`, `ComparisonTable`, `storageFolds`), their types |
40
- | `@toolpath/dfm/model` | The rules, `checkPart`, the rule-set file, the feature panel's rows, pinch points — no React, no DOM |
41
- | `@toolpath/dfm/dfm.css` | Lets the app's Tailwind see the list's and chart's classes |
19
+ | Entry point | What it is |
20
+ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
21
+ | `@toolpath/dfm` | The rules and both vocabularies (`MILLING_RULES`, `TURNING_RULES`), `checkPart` and `checkTurnedPart`, the rule-set file and `llmRulePrompt`, the feature panel's rows, pinch points |
22
+ | `@toolpath/dfm/model` | The same entry, under its name from before the views moved |
42
23
 
43
24
  ## The rules are an input
44
25
 
45
- The package ships no default rules and stores nothing — not the rules, nor
46
- which of the feature panel's sections are open. The app keeps the rules
47
- — in memory, `localStorage`, a server — and passes them in with the functions
48
- that change them:
49
-
50
- ```tsx
51
- import { RuleList, type DfmRules } from '@toolpath/dfm'
52
- import { checkPart, dfmFeatures } from '@toolpath/dfm/model'
26
+ The package ships no default rules and stores nothing. The app keeps the rules
27
+ — in memory, `localStorage`, a server — and checks a part against them:
53
28
 
54
- const rules: DfmRules = { rules, add, update, remove, replace }
29
+ ```ts
30
+ import { checkPart, dfmFeatures } from '@toolpath/dfm'
55
31
 
56
32
  // From a part analysis: the Engine's report, and each feature's datasheet.
57
33
  const features = dfmFeatures(report.features)
58
- const check = checkPart(features, { sheets, datasheets, regionAreas }, rules.rules)
59
-
60
- <RuleList
61
- rules={rules}
62
- check={check} // null while the part is still being analysed
63
- features={features}
64
- sheets={sheets}
65
- units="mm"
66
- selected={selectedTag}
67
- selectedGroup={selectedGroup}
68
- onInspect={(tag, group) => inspect(tag, group)}
69
- onHover={(hovered) => highlight(hovered)}
70
- />
34
+ const check = checkPart(features, { sheets, datasheets, regionAreas }, rules)
71
35
  ```
72
36
 
73
37
  `sheets` is each feature's measurements, built with `featureSheet` from its
74
38
  datasheet; `datasheets` is the datasheets as the API sent them, both by
75
39
  lower-cased feature tag; `regionAreas` is each face's area by region index.
76
40
 
77
- Put `ruleListKeys` on the panel that holds the list, so the arrow keys walk the
78
- rules from anywhere in it.
79
-
80
- `actions` puts the app's own buttons at the end of the footer's row, after
81
- Import…, Export and Copy LLM prompt — a way back to the app's default rules,
82
- say, since the package has none of its own.
41
+ ## Turning rules
83
42
 
84
- ## Reach chart
43
+ `TURNING_RULES` is the turning vocabulary: turned subjects (grooves, threads,
44
+ axial holes, OD and ID features) and their measures. Each vocabulary keeps its
45
+ own rules: a rule-set file of the other process is refused, and
46
+ `parseRules(raw, TURNING_RULES)` drops milling ones. Every helper that reads a
47
+ rule takes the vocabulary last, and reads milling where it is left out.
85
48
 
86
- `ReachChart` draws a feature's reach curve: the section through the part at the
87
- feature's wall, to scale. The feature is on the left, in blue; the walls step up
88
- on the right, with their heights and their distances from the feature written
89
- on. Pointing at the walls reads the curve at that distance.
49
+ ```ts
50
+ import { checkTurnedPart, turnedStretches } from '@toolpath/dfm'
90
51
 
91
- ```tsx
92
- import { ReachChart, ReachDrawing } from '@toolpath/dfm'
93
- import { featureProfile, readReachCurve } from '@toolpath/dfm/model'
94
-
95
- const curve = readReachCurve(datasheet) // null where the feature has none
96
- const feature = featureProfile(sheets[tag], featureType)
97
-
98
- export const Reach = () =>
99
- curve ? <ReachChart curve={curve} units="mm" feature={feature} /> : null
52
+ // From a part analysis's `turning.features`.
53
+ const stretches = turnedStretches(report.turning.features)
54
+ const check = checkTurnedPart(stretches, rules)
100
55
  ```
101
56
 
102
- `ReachChart` is as wide as its container. `ReachDrawing` is the same section
103
- with a caption and a note on how to read it, for a larger window of its own.
104
- Both stop drawing the curve half an inch past where the walls reach full
105
- height; `ReachDrawing` says so in its note.
106
-
107
- This is not the clearance overlay in `@toolpath/tool-drawing/clearance`: that
108
- draws the walls beside a cutting tool, to show whether the tool fits. This
109
- draws the walls alone.
57
+ The Engine reports a stretch both ends of the part reach as two features, one
58
+ per end; `turnedStretches` makes them one again, under the first one's tag. A
59
+ stretch breaks a rule only if it breaks it from every end it is cut from, and
60
+ every stretch counts — a turned face has one reading — so nothing is left in
61
+ `otherTags`. Turning is experimental in the API, so a datasheet field that is
62
+ missing or malformed is no figure, never an error.
110
63
 
111
- ## Feature panel
112
-
113
- `FeaturePanel` is the card a click on the part opens: every feature the face
114
- belongs to, then the details of the one being read. With several faces
115
- shift-clicked, each face's candidates sit under a letter, above a table of
116
- what each was read as. It fills what it is put in — where it sits, and
117
- whether it can be dragged, is the app's — and the app decides what a click
118
- means: which faces, which candidates in which order, which is read.
119
-
120
- ```tsx
121
- import { FeatureDetails, FeaturePanel, storageFolds } from '@toolpath/dfm'
122
- import { brokenRules, featureMeasurements, featureProfile } from '@toolpath/dfm/model'
123
-
124
- const folds = storageFolds(localStorage, 'toolpath.fold.')
125
-
126
- export const Inspector = () => (
127
- <FeaturePanel
128
- faces={[{ region, rows, selected }]}
129
- active={0}
130
- onSelect={(tag) => setSelected(tag)}
131
- onHover={setHovered}
132
- onClose={close}
133
- folds={folds}
134
- >
135
- <FeatureDetails
136
- feature={feature}
137
- units="mm"
138
- directionColor={directionHex}
139
- profile={featureProfile(sheets[key], feature.featureType)}
140
- required={check.required.has(key)}
141
- onFrame={() => frame(feature.tag)}
142
- rules={brokenRules(check, feature.tag, 'mm')}
143
- measurements={{
144
- status: 'ready',
145
- value: featureMeasurements({ features, feature, sheets, units: 'mm' }),
146
- }}
147
- record={{ status: 'ready', value: records[key] ?? null }}
148
- PopOut={AppWindow}
149
- folds={folds}
150
- />
151
- </FeaturePanel>
152
- )
153
- ```
64
+ ## Rule-set files and the LLM prompt
154
65
 
155
- The parts work alone too. An app with an inspect panel of its own puts
156
- `CandidateList` and `FeatureDetails` in it and fills their slots with its own
157
- controls — a folder in a row's `detail`, a Pin button in its `action`, Zoom to
158
- in the details' `actions`, a folder badge in `status`.
159
-
160
- - **Rules broken** are `BrokenRule` rows: a colour, the rule's text, the figure
161
- that broke it, and optionally the limit and a note on hover. `brokenRules`
162
- builds them from this package's check; an app with a checker of its own
163
- builds them from its hits.
164
- - **Measurements** are `featureMeasurements` rows, each with how it was worked
165
- out behind an ⓘ. `inchMark` writes inches as `0.46"`.
166
- - **Reach, the datasheet fields and the raw record** read the feature's
167
- `FeatureRecord`: its report entry and datasheet as the API sent them.
168
- - **Reads take time.** `measurements` and `record` are `Loadable`. While
169
- `loading`, a section says what it is reading; on `error` it shows the app's
170
- message and a Retry, held until `retryAt`.
171
- - **The look** differs where apps want it to: `look.rules`, `look.selected` and
172
- `look.muted`. Left out, it is the CAD viewer's.
173
- - **Folds** are kept in the app's `FoldStore`; `storageFolds(storage, prefix)`
174
- builds one over a `Storage`. Without one, a section remembers only while it
175
- is mounted.
176
- - **Pop-outs** need `PopOut`, the app's window component: the panel decides
177
- what is open and fills it, and the app draws the frame. Define it at module
178
- level, and render it through a portal to the page's body: the panel's blur
179
- makes it the box a `fixed` window inside it would be placed in.
180
- - **Keys:** Escape closes the panel and the arrow keys walk the candidates. On
181
- a `CandidateList` used alone, put `candidateListKeys` on whatever holds it.
66
+ `serializeRuleSet` writes a set as one JSON file and `parseRuleSetFile` reads
67
+ one back. `llmRulePrompt(rules, vocabulary)` is a prompt that walks an LLM
68
+ through writing a set for a shop. The rule list in `@toolpath/ui` has no button
69
+ for it; an app that wants one adds it through the list's `actions`.
182
70
 
183
71
  ## Pinch points
184
72
 
185
73
  The widest tool a feature admits, standing where the feature is tightest. The
186
- data is here; the drawing is `@toolpath/viewer`'s `<ToolMarks>`, which knows
187
- nothing of datasheets:
74
+ data is here. **Drawing it is the viewer's job, and needs `@toolpath/viewer`**;
75
+ this package does not depend on it. The viewer's `<ToolMarks>` knows nothing of
76
+ datasheets:
188
77
 
189
78
  ```tsx
190
79
  import { useMemo } from 'react'
191
- import { pinchLabel, pinchMark, placePinchTool } from '@toolpath/dfm/model'
80
+ import { pinchLabel, pinchMark, placePinchTool } from '@toolpath/dfm'
192
81
  import { featureTriangles, ToolMarks, usePartContext } from '@toolpath/viewer'
193
82
 
194
83
  // A child of <EnginePart> or <PartMesh>, which gives it the part.