Historical note: this plan predates the final naming. As shipped, the
crossrefCLI keeps thecrossref-utilsnpm name (packages/crossref-utils) and the library is published ascrossref-utils-sdk(packages/crossref-utils-sdk). Package names below are the ones under discussion at planning time.
Revised implementation plan after PR #27 review (Franklin Koch). Aligns with SDK.md.
- Split the repo into two packages (JATS-style monorepo):
packages/crossref-utils— lightweight, in-memory library (the “SDK”)packages/crossref-cli— filesystem, myst-cli session, inquirer; depends on-utils
- Keep existing DTOs and APIs — Crossref types +
*Xmlbuilders, and MyST frontmatter +*FromMystadapters. No newDepositInput/buildDepositfacade. - Maintain Crossref vs content-format separation — core is format-agnostic; MyST is one adapter; future
*FromOtherhelpers can map other frontmatter/layouts into Crossref DTOs without growing the core. - Ship in-process XML validation on
crossref-utils(replace or supersede CLI-onlyxmllintfor library callers). - Remove Curvenote-specific hardcoding from the library (resource URL defaults, DOI prefix alias map in code).
- New Crossref-oriented deposit DTO layer / single
buildDepositentrypoint - Shipping myst-cli /
parseMyst/ markdown pipelines insidecrossref-utils - Interactive DOI checkbox UI inside
-utils(stays CLI or caller-owned) - Changing Crossref schema version (stay on 5.3.1)
Gut check: easier than a long facade plan — an initial package split gets ~90% of the way there.
- Tear the single package into
-cli(FS + interactivity) and-utils(everything else). Keep interfaces mostly unchanged. - Massage details: decouple abstract extraction (CLI / upstream MyST) from light mdast→JATS transforms (utils); swap MyST
Sessionfor a logger interface on adapters; injectable DOI resource resolution. - Land TS-native (or otherwise in-process) XSD validation on
-utils; retire reliance onxmllintfor the library API.
packages/
crossref-utils/ # published as crossref-utils
src/
# Crossref core
batch.ts, types.ts, dates.ts, contributors.ts, funding.ts, …
journal.ts, conference.ts, preprint.ts, dataset.ts
abstract.ts # mdast → jats:abstract (transforms + myst-to-jats)
doi.ts # generateDoi, suggestDois (prefix always passed in)
validate.ts # in-process XSD validate
fromMyst/ # adapter layer (not “core”)
… *FromMyst helpers, Session→logger refactors
crossref-cli/ # published as crossref-cli (bin: crossref)
src/
deposit.ts, generate.ts, parse.ts, validate.ts (CLI wrappers)
# FS discovery, inquirer, myst-cli load/extract, write-back to myst.yml
Published names can stay crossref-utils for the library; CLI package name TBD (crossref-cli vs keeping a single npm name that re-exports — decide at implement time to minimize breakages).
- Introduce workspace (
packages/*) following continuous-foundation JATS / similar monorepos. - Move existing library modules →
crossref-utils; CLI (src/cli/**, bin) →crossref-cli. -clidepends on-utils;-utilsmust not depend on commander/inquirer/myst-cli FS workflows.- Keep
myst-frontmatter/myst-to-jats/ light myst types only where needed (adapters + abstract helper). - Green existing tests; CLI smoke still works via workspace link.
Core (crossref-utils): Crossref DTOs (types.ts), *Xml, DoiBatch, contributors/dates/funding XML, DOI helpers, validate, abstractFromMdast.
Adapter (crossref-utils/fromMyst or equivalent exports): *FromMyst — maps myst-frontmatter → Crossref DTOs / elements. Document as the MyST adapter, not the only input path.
Future: other X→Crossref adapters (same package or later packages) map into core DTOs + *Xml. Do not fold foreign pipelines into core.
Refactor *FromMyst / fundrefFromMyst to take a logger (or Pick<ISession, 'log'>) instead of a full myst Session.
Agreed direction (Franklin option 2 + prior spike):
- Upstream (CLI or serverless caller) owns myst processing and supplies processed abstract mdast.
-utilsexposesabstractFromMdast(mdast)— FS-free transforms +myst-to-jats+jats:abstractwrap (logic lifted from today’s CLI).- CLI: split
depositArticleFromSource— extract/load with myst-cli in CLI; callabstractFromMdastfrom utils. - Do not ship
parseMystin-utils(avoids pulling full MyST into the library). - Plain-text-only abstract (lossy option 3) is out of scope as the primary path.
generateDoi(prefix: string)— keep; numeric prefix always passed in (nocurvenote→10.62329map in library code).suggestDois(count, prefix)— non-interactive candidates for UIs; callers must still human-review before Crossref submit (slur / pronounceability concern).- Prefix aliases (if needed) live in caller config or CLI only — not hardcoded in
-utils. - Remove hardcoded
https://doi.curvenote.com/...from*FromMyst/ helpers; require explicitdoi_data.resourceor an injectable resolver callback on adapters. - Bonus (not SDK-specific): strip other Curvenote-only defaults as found.
- Expose e.g.
validateDeposit(xml: string): Promise<ValidationResult>from-utils. - Spike for a maintained pure JS/Node XSD validator usable in serverless (no native addon if possible).
- Bundle Crossref 5.3.1 schema assets with the package (or load from package files without network).
- If in-process XSD proves blocked: document fallback (external validation service) but still ship a library
validate*API contract — do not leave validation CLI/xmllint-only. - CLI can call the utils validator;
xmllintpath may remain as optional local fallback during transition.
- Rewrite
SDK.mdto describecrossref-utilsas the public library (core + MyST adapter), not a/sdksubpath facade. - Update root README for monorepo / package install (
crossref-utilsvs CLI). - Changesets per package; note breaking changes (Curvenote defaults removed, Session→logger, package layout).
- Monorepo scaffolding + move files (utils vs cli)
- Logger refactor + Curvenote resource/prefix cleanup
- Extract
abstractFromMdast; slim CLI deposit path generateDoi/suggestDois(prefix required); CLI uses them- Validation spike → implement
validateDepositon utils - Docs (
SDK.md, README) + changesets
- Workspace build/publish layout for both packages
- Existing unit tests pass under
crossref-utils - CLI deposit/generate/validate still work against workspace utils
-
abstractFromMdastfixture; CLI no longer duplicates transform logic -
*FromMystworks with logger only (no Session) - No Curvenote URL/prefix defaults in utils
-
validateDepositcatches known-bad deposit XML; known-good passes - Serverless-shaped usage: import utils only, no FS
- Exact npm name for the CLI package and whether the current
crossrefbin moves with a major bump. - Which XSD-in-JS library survives the spike (or external service shape if none does).
crossref-utils/sdksubpath entry- New
DepositInput/buildDeposit/mystToDepositItemfacade types - Bundling DOI prefix alias constants into the library
- Treating MyST frontmatter JSON as the only primary SDK input (both Crossref DTOs and MyST adapters remain)