Skip to content

Write the order list as a Mastercam tool library - #13

Merged
wevanscfi merged 3 commits into
paul/tool_catalogfrom
paul/mastercam-export
Sep 14, 2026
Merged

wevanscfi merged 3 commits into
paul/tool_catalogfrom
paul/mastercam-export

Conversation

@JustinSGray

@JustinSGray JustinSGray commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

What this is

The order list leaves as a Mastercam .TOOLDB as well as a Fusion library. The
exporter is not this application's — a .TOOLDB is a SQLite database carrying
Mastercam's own 79-table schema, pinned upstream from a real library — so what
is here is the seam, app/shared/mastercam-input.ts.

Stacked on #9. Based on paul/tool_catalog, so the diff here is the
Mastercam work alone. GitHub will retarget it to main when #9 merges.

Why it reads differently from the Fusion seam

Fusion embeds a holder inside the tool record, so one tool in two holders is
two records, and fusion-input.ts mints a guid per stack to keep them apart.
Mastercam's schema is relational — TlTool holds the tool, TlAssembly joins
it to a holder — so the order list goes in grouped: one entry per distinct
tool carrying one set-up per stack, one entry per distinct holder, under the
catalog's own guids. Six stacks sharing an ER32 chuck put one holder in the
file rather than six, which is what a machinist sees in Mastercam's own tree.

The one guid this mints

An assembly's identifier is derived upstream from its tool and holder, which is
stable across re-exports but cannot tell apart the same tool in the same holder
at two different stickouts
— those two would collapse into one assembly and the
second stickout would be lost silently. So every set-up states its own guid,
minted per stack. The cost is that a re-export is a fresh set of assemblies; the
tools and holders under them keep their catalog guids and do update.

The extraction

app/shared/export-input.ts is what both formats read, pulled out of
fusion-input.ts now that there is a second consumer — the repo's rule being
that the second consumer is the trigger and a copy is a divergence with a delay
on it. It stays inside the application rather than moving to packages/,
because everything in it reaches for this catalog's own record types.

One dialog serves both, library-export-dialog.tsx: only four strings differ
between a Fusion export and a Mastercam one. ExportReport.holderWarnings is
now warnings, meaning the same quantity for each — rows of the order list that
reached the file.

Loaded on the press

The exporter is imported by a dynamic import() in the button handler rather
than at the top of the route: it carries 82 KB of pinned schema before a single
tool, and every visitor to the order list would otherwise download it to find
out whether they wanted it. vite.config.ts pre-bundles the subpath so that
import is a fetch rather than a discovery mid-session.

The version move, and why it is four packages

tool-support 0.6.0 is what carries export/mastercam. Bumping it alone is not
enough: app-support, tool-drawing and tool-scraper each depended on
^0.5.0, and a 0.x caret does not span a minor, so the install carried two
copies of tool-support — the split #10 closed, reopened. They move together to
0.1.6, 1.0.3 and 3.0.3, each on ^0.6.0, and the lockfile resolves one copy.

A behaviour change that came with the bump

tool-support 0.5.0 changed what a holder stating no gauge length means to the
Fusion exporter: it used to drop the gauge length and leave Fusion to ask, and
now fills it with the height of the shape it exported — a real number rather
than a gap. A filled note is the format's own convention and is deliberately
not surfaced, so that case stopped being a warning and its test failed against
0.6.0.

fusion-input.test.ts now pins the case that still raises something a shop must
act on — a stated gauge length its own published dimensions contradict — and
pins the silence on the case that stopped being one. This is a Fusion
behaviour change riding in on the bump, not something the Mastercam work did.

Tests

  • app/shared/mastercam-input.test.ts — the grouping, the minted assembly guid,
    the notes read back per row.
  • apps/catalog/tests/on-the-part.spec.ts — a separate end-to-end test from the
    Fusion one, because a .TOOLDB is a database: it opens the downloaded file
    with node:sqlite and runs PRAGMA integrity_check, which is the only way to
    catch a b-tree written slightly wrong. It also proves the dynamic import()
    behind the press resolves in a real browser.
  • pnpm check green (check-style, lint, build, check-types, 1,509 unit tests),
    and both export e2e tests pass — all of it against the published 0.6.0
    rather than a local link.

A `.TOOLDB` is a SQLite database carrying Mastercam's own 79-table schema,
and writing one is `@toolpath/tool-support/export/mastercam`, not this
application. `app/shared/mastercam-input.ts` is the seam.

It reads differently from the Fusion one on purpose. Fusion embeds a holder
inside the tool record, so one tool in two holders is two records; Mastercam
joins them relationally, so the order list goes in grouped — one entry per
distinct tool carrying one set-up per stack, one entry per distinct holder,
under the catalog's own guids. Six stacks sharing an ER32 chuck put one
holder in the file rather than six.

The one identifier this mints is the assembly's, per stack. An assembly's id
is derived upstream from its tool and holder, which cannot tell apart the
same tool in the same holder at two stickouts — those would collapse and the
second stickout would be lost. A minted guid costs a re-export a fresh set of
assemblies; the tools and holders under them keep their catalog guids.

`app/shared/export-input.ts` is what both formats read, extracted from
`fusion-input.ts` now that there is a second consumer. One dialog serves both,
`library-export-dialog.tsx` — only four strings differ between the two — and
`ExportReport.holderWarnings` is `warnings`, meaning the same quantity for
each: rows of the order list that reached the file.

The exporter is imported on the press rather than at the top of the route: it
carries 82 KB of pinned schema, and `vite.config.ts` pre-bundles the subpath
so that import is a fetch rather than a discovery.

`tool-support` moves to 0.6.0, which is what carries the Mastercam exporter.
That release also changed what a holder stating no gauge length means: the
Fusion exporter `filled`s it with the height of the shape it wrote rather than
`dropped`ing it, so it is no longer a warning. `fusion-input.test.ts` now pins
a stated gauge length its own dimensions contradict, which still is one, and
pins the silence on the case that stopped being.
`tool-support` 0.6.0 carries the Mastercam exporter, and `app-support` 0.1.6,
`tool-drawing` 1.0.3 and `tool-scraper` 3.0.3 each depend on `^0.6.0`. A 0.x
caret does not span a minor, so bumping `tool-support` alone left the older
three asking for 0.4.0 and the install carried two copies — the same split
`build: resolve the Toolpath packages onto one tool-support` closed before.

`pnpm-lock.yaml` resolves one copy again, and the suite now runs against the
published package rather than a local link.
@wevanscfi
wevanscfi marked this pull request as ready for review September 14, 2026 13:27
The dialog says `aria-modal="true"`, which tells a screen reader the page
behind it is inert, and nothing kept that promise: Tab walked straight onto the
order list underneath while the reader still announced the dialog, and opening
it left the focus on the button behind the overlay.

The kit's `Dialog` is the component to reach for and does not fit — it is an
alert whose `confirm()` resolves to a boolean and closes on the press, where
this dialog reads a name back off an input and goes on showing a report
afterwards; its `@base-ui/react` primitive is not a dependency here. So the
focus is handled beside the markup it governs, and the component now says which
kit component it turned down and why.

The name takes the focus on open, Tab cycles within the dialog, and the opener
gets the focus back when it closes. Three tests pin those, because the markup
makes the claim whether or not the behaviour is there.
@wevanscfi
wevanscfi merged commit df75d8b into paul/tool_catalog Sep 14, 2026
1 check passed
@dementive dementive mentioned this pull request Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants