Skip to content

Add crate2tables plugin: export RO-Crate tables via roctable - #16

Merged
ptsefton merged 4 commits into
mainfrom
feature/crate2tables-plugin
Sep 2, 2026
Merged

Add crate2tables plugin: export RO-Crate tables via roctable#16
ptsefton merged 4 commits into
mainfrom
feature/crate2tables-plugin

Conversation

@ptsefton

@ptsefton ptsefton commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • New crate2tables build plugin: exports a built RO-Crate as one CSV per entity type using roctable (config-driven the same way its own inspect/csv CLI works — discovers types/properties into crate2tables-config.json on every build, extracts+writes CSV for whatever the config already selects).
  • load_text support wired to roctable's injectable file reader (Make load_text's file read injectable instead of hardcoded to Node fs ptsefton/roctable#2) via browserFileReader(dirHandle), wrapping readFileTextFromDirectory — no more Node-fs limitation.
  • generic-input now reconciles against an existing crate instead of replacing it: reads ro-crate-metadata.json from the folder (if present) and passes it through to buildCrate() (chaos2crate PR pending) as opts.existingJson. This fixes real data loss — building against an already-curated crate was silently discarding almost everything (reproduced against a real 764-entity collection: rebuild → 465 entities, everything but bare file stubs gone).
  • Any file the scan finds with no matching entity in the existing crate now blocks the build on a checkbox file-tree confirmation modal (new-files-confirm.js) before it's added — never a silent guess.

Dependencies

  • roctable is installed as "roctable": "file:../roctable" (sibling checkout) while both repos are under active development — should switch to a pinned github:ptsefton/roctable git dependency once Make load_text's file read injectable instead of hardcoded to Node fs ptsefton/roctable#2 merges.
  • Depends on chaos2crate's companion PR for buildCrate()'s opts.existingJson/reconciliation support and the deletePluginOutputs() fix that lets reconciliation actually see the existing file.

Test plan

  • Verified crate2tables's crate:built/output:write hooks end-to-end against an in-memory crate, including a real load_text read through the injected reader
  • Verified generic-input's reconciliation end-to-end against a real 764-entity collection: no-op reconcile (0 new/0 missing), a synthetic delta (1 new/1 missing), and a genuinely new file confirmed via "Add selected" — all preserve every existing entity
  • Verified the confirmation-tree UI logic (build/render/checkbox↔indeterminate propagation/result shape) with a minimal fake DOM (no jsdom dependency in this repo)
  • Real vite build (single-plugin and all-plugins) in chaos2crate stays clean with this registered

Closes #15

Flattens a built crate into one CSV per entity type using roctable
(github:ptsefton/roctable, WIP/not on npm), config-driven the same way
its own inspect/csv CLI works: discovers types/properties into
crate2tables-config.json on every build (non-destructive to existing
choices), extracts+writes CSV for whatever the config already selects
into crate2tables-output/. load_text is disabled with a warning rather
than crashing, since roctable's implementation reads files via Node's
fs, not available in chaos2crate's browser build.

See chaos2crate/docs/crate2tables-spec.md for the full design, config
schema, and the Phase 2 UI plan for interactive type/field selection.
roctable's extractTables() now takes an optional fileReader instead of
reading load_text files via Node fs (ptsefton/roctable#1). This plugin
passes browserFileReader(dirHandle), wrapping readFileTextFromDirectory
— dropping the stripUnsupportedFeatures workaround that disabled
load_text with a warning.

Depends on roctable's file:../roctable sibling checkout while both are
under active development — package.json points there for now instead
of the github: dependency, to be switched back once
ptsefton/roctable#1 merges.

Closes #15
…lace it

Reads ro-crate-metadata.json from the folder (if present) and passes it
through to buildCrate() as opts.existingJson, so a build against an
already-curated crate updates it instead of throwing it away — see
chaos2crate SPEC.md §6.1a and its crate.js change for what reconciling
actually does.
A file the scan found with no matching entity in the existing crate
(reconciliation, chaos2crate SPEC.md §6.1a) was previously added
automatically, attached to the root dataset with only a warning after
the fact — a silent guess about a decision a curator should actually
make. buildCrate(ctx) now diffs the scan against the existing crate's
@ids first and, if anything's new, blocks on a confirmation modal
(new-files-confirm.js): a checkbox file tree, everything checked by
default, folders reflecting all/some/none of their contents. Only the
confirmed subset reaches buildCrate() at all — an unchecked file simply
isn't part of this build, same as one the scan never saw, and gets
asked about again next time unless it's removed from the folder.
Dismissing the modal outright (as opposed to confirming even an empty
selection) cancels the whole build, since that made no explicit choice.

Verified the orchestration (fresh build/no-new-files/confirmed/skipped/
cancelled) with a mocked openModal, and the tree itself (build, render,
checkbox↔indeterminate propagation on toggle, confirmed-result shape)
with a minimal fake DOM, since this repo has no jsdom dependency.
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.

crate2tables: wire up load_text once roctable's file reader is injectable

1 participant