Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
"$schema": "https://unpkg.com/@changesets/config@4.0.1/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"fixed": [["crossref-utils", "crossref-utils-sdk"]],
"linked": [],
"access": "public",
"baseBranch": "main",
Expand Down
2 changes: 1 addition & 1 deletion .changeset/fair-hotels-juggle.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
"crossref-utils": patch
"crossref-utils-sdk": patch
---

Do not add doi to deposit if it cannot be normalized
2 changes: 1 addition & 1 deletion .changeset/gold-phones-serve.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
"crossref-utils": patch
"crossref-utils-sdk": patch
---

Support math in abstract
4 changes: 2 additions & 2 deletions .changeset/monorepo-headless-sdk.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
"crossref-utils-sdk": minor
"crossref-utils": minor
"crossref-cli": minor
---

Split into monorepo packages for headless library use: `crossref-utils` (in-memory builders, MyST adapters, `abstractFromMdast`, DOI helpers, `validateDeposit`) and `crossref-cli` (filesystem / interactive workflows). Remove Curvenote DOI resource defaults from the library; callers pass `resolveDoiData`.
Split into monorepo packages for headless library use: `crossref-utils-sdk` (in-memory builders, MyST adapters, `abstractFromMdast`, DOI helpers, `validateDeposit`) and `crossref-utils` (the `crossref` CLI — filesystem / interactive workflows). Remove Curvenote DOI resource defaults from the library; callers pass `resolveDoiData`.
2 changes: 1 addition & 1 deletion .changeset/perfect-numbers-beg.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
"crossref-utils": patch
"crossref-utils-sdk": patch
---

Add chair contributor_type option
2 changes: 1 addition & 1 deletion .changeset/pretty-otters-fix.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
"crossref-utils": patch
"crossref-utils-sdk": patch
---

Remove xrefs from abstract tree
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
- run: npm install
node-version: 24.x
- run: npm ci
- run: npm run lint:format
- run: npm run lint
test:
if: github.actor != 'dependabot[bot]'
runs-on: ubuntu-latest
strategy:
matrix:
node: ['18', '20']
node: ['22', '24']
name: Testing on node ${{ matrix.node }}
steps:
- uses: actions/checkout@v4
Expand All @@ -38,5 +38,5 @@ jobs:
with:
node-version: ${{ matrix.node }}
cache: 'npm'
- run: npm install
- run: npm ci
- run: npm run test
5 changes: 4 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
# Trusted publishing requires Node >= 22.14 and npm >= 11.5.1
# changesets/action@v2 requires Changesets CLI v3, which needs Node >= 22.11
node-version: 24

- name: Install dependencies
Expand Down Expand Up @@ -115,6 +115,9 @@ jobs:
node-version: 24
registry-url: https://registry.npmjs.org

- name: Ensure npm 11.5.1+ for trusted publishing
run: npm install -g npm@^11.5.1

- name: Install dependencies
run: npm ci

Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
# crossref utilities

[![crossref-utils on npm](https://img.shields.io/npm/v/crossref-utils.svg)](https://www.npmjs.com/package/crossref-utils)
[![crossref-utils-sdk on npm](https://img.shields.io/npm/v/crossref-utils-sdk.svg)](https://www.npmjs.com/package/crossref-utils-sdk)
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/continuous-foundation/crossref-utils/blob/main/LICENSE)
[![CI](https://github.com/continuous-foundation/crossref-utils/workflows/CI/badge.svg)](https://github.com/continuous-foundation/crossref-utils/actions)

Utilities for creating crossref.org deposit metadata from Node or the command line.

This repository is a monorepo:

| Package | Role |
|---------|------|
| [`crossref-utils`](./packages/crossref-utils) | In-memory library (Crossref XML builders, MyST adapters, `validateDeposit`) |
| [`crossref-cli`](./packages/crossref-cli) | `crossref` CLI (filesystem, myst-cli, prompts) |
| Package | Role |
| ----------------------------------------------------- | --------------------------------------------------------------------------- |
| [`crossref-utils`](./packages/crossref-utils) | `crossref` CLI (filesystem, myst-cli, prompts) |
| [`crossref-utils-sdk`](./packages/crossref-utils-sdk) | In-memory library (Crossref XML builders, MyST adapters, `validateDeposit`) |

Library API details: [`SDK.md`](./SDK.md). Implementation notes: [`plan-sdk.md`](./plan-sdk.md). Validation / xerces-wasm: [`docs/validation.md`](./docs/validation.md).
CLI e2e fixtures and golden XML: [`docs/e2e-fixtures.md`](./docs/e2e-fixtures.md).

```bash
# Library (serverless / headless)
npm install crossref-utils

# CLI
npm install -g crossref-cli
# (during transition, `crossref` bin ships from crossref-cli)
npm install -g crossref-utils

# Library (serverless / headless)
npm install crossref-utils-sdk
```

To use from the command line after a global install:

```
npm install -g crossref-cli
npm install -g crossref-utils
```

## Creating a deposit
Expand Down
38 changes: 18 additions & 20 deletions SDK.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# crossref-utils (library API)
# crossref-utils-sdk (library API)

Developer-facing docs for the **in-memory** Crossref library after the planned monorepo split. See [`plan-sdk.md`](./plan-sdk.md) for the implementation plan.

Expand All @@ -17,10 +17,10 @@ import {
generateDoi,
suggestDois,
validateDeposit,
} from 'crossref-utils';
} from 'crossref-utils-sdk';
```

CLI (filesystem, myst-cli, prompts) lives in a separate package (`crossref-cli`) and depends on this library. Prefer importing **`crossref-utils` only** from serverless / headless code.
The `crossref` CLI (filesystem, myst-cli, prompts) lives in a separate package (`crossref-utils`) and depends on this library. Prefer importing **`crossref-utils-sdk` only** from serverless / headless code.

## Architecture

Expand All @@ -40,7 +40,7 @@ CLI (filesystem, myst-cli, prompts) lives in a separate package (`crossref-cli`)
└─────────────────────────┘
```

**Important separation:** MyST (or any other) *content processing* stays outside the Crossref core. Adapters only map already-structured frontmatter (and helpers like `abstractFromMdast` for processed mdast) into Crossref shapes. That leaves room for other X→Crossref parsers without bloating the core.
**Important separation:** MyST (or any other) _content processing_ stays outside the Crossref core. Adapters only map already-structured frontmatter (and helpers like `abstractFromMdast` for processed mdast) into Crossref shapes. That leaves room for other X→Crossref parsers without bloating the core.

There is **no** separate `buildDeposit` facade or new deposit DTO layer — use the existing Crossref types + `*Xml`, and/or `*FromMyst`.

Expand Down Expand Up @@ -109,9 +109,7 @@ function suggestDois(count: number, prefix: string): string[];
```ts
function validateDeposit(xml: string, schema: DepositSchema): Promise<ValidationResult>;

type DepositSchema =
| string
| { entry: string; imports?: Record<string, string> };
type DepositSchema = string | { entry: string; imports?: Record<string, string> };

type ValidationResult = {
ok: boolean;
Expand All @@ -136,7 +134,7 @@ import {
abstractFromMdast,
generateDoi,
validateDeposit,
} from 'crossref-utils';
} from 'crossref-utils-sdk';

const doi = generateDoi(process.env.DOI_PREFIX!); // review before use
const abstract = abstractFromMdast(abstractMdast);
Expand All @@ -162,23 +160,23 @@ Multi-article journal/conference deposits: build venue/issue XML with existing h

---

## What belongs in `crossref-cli` (not this library)
## What belongs in `crossref-utils` (the CLI, not this library)

- Path discovery, reading `myst.yml` / pages from disk
- myst-cli `Session`, `getFileContent`, part extraction from projects
- `parseMyst` for frontmatter abstract strings
- inquirer prompts (deposit type, depositor, DOI checkbox selection)
- Writing DOIs back into config files
- Path discovery, reading `myst.yml` / pages from disk
- myst-cli `Session`, `getFileContent`, part extraction from projects
- `parseMyst` for frontmatter abstract strings
- inquirer prompts (deposit type, depositor, DOI checkbox selection)
- Writing DOIs back into config files

The CLI should call into `crossref-utils` for XML build, abstract mdast→JATS, DOI string generation, and validation.
The CLI should call into `crossref-utils-sdk` for XML build, abstract mdast→JATS, DOI string generation, and validation.

---

## Package relationship

| Package | Role |
|---------|------|
| `crossref-utils` | In-memory Crossref core + MyST adapter + validate |
| `crossref-cli` | `crossref` binary; FS + interactive workflows |
| Package | Role |
| -------------------- | ------------------------------------------------- |
| `crossref-utils-sdk` | In-memory Crossref core + MyST adapter + validate |
| `crossref-utils` | `crossref` binary; FS + interactive workflows |

Root import of `crossref-utils` is the supported library surface (no `/sdk` subpath required).
Root import of `crossref-utils-sdk` is the supported library surface (no `/sdk` subpath required).
5 changes: 2 additions & 3 deletions docs/e2e-fixtures.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Regression fixtures for `crossref deposit` (and later `validate`). Kept **compac
## Layout

```
packages/crossref-utils/tests/fixtures/
packages/crossref-utils-sdk/tests/fixtures/
shared/
proceedings.yml # SciPy-like venue / volume / editors (synthetic)
conference/
Expand Down Expand Up @@ -52,10 +52,9 @@ packages/crossref-utils/tests/fixtures/
npm test # unit + e2e (builds CLI for e2e)
npm run test:unit # unit only
npm run test:e2e # e2e only (builds CLI first)
npm run test:e2e:record # regenerates packages/crossref-utils/tests/fixtures/golden/*.xml
npm run test:e2e:record # regenerates packages/crossref-utils-sdk/tests/fixtures/golden/*.xml
```


`test:e2e:record` should only be used intentionally (e.g. when deposit XML shape changes on purpose).

## Out of scope (v1)
Expand Down
24 changes: 12 additions & 12 deletions docs/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@

## Responsibility split

| Layer | Role |
|-------|------|
| **`crossref-utils` (SDK)** | `validateDeposit(xml, schema)` — in-process XSD check via xerces-wasm. **No network, no schema download.** Caller must pass schema text / bundle. |
| **`crossref-cli` (or your app)** | Obtain schemas (download, vendor, or cache), pick version, pass a `DepositSchema` into the SDK. |
| Layer | Role |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`crossref-utils-sdk` (SDK)** | `validateDeposit(xml, schema)` — in-process XSD check via xerces-wasm. **No network, no schema download.** Caller must pass schema text / bundle. |
| **`crossref-utils` (the CLI, or your app)** | Obtain schemas (download, vendor, or cache), pick version, pass a `DepositSchema` into the SDK. |

That lets the CLI keep **multi-version** support (resolve version from deposit `xmlns`, load matching files from a cached Crossref `schemas/` tree), while another app can **vendor a single bundle** (e.g. 5.5.0) for the XML it produces.

## SDK API

```ts
import { validateDeposit, schemaVersionFromXml, type DepositSchema } from 'crossref-utils';
import { validateDeposit, schemaVersionFromXml, type DepositSchema } from 'crossref-utils-sdk';

// Prefer a bundle so includes/imports resolve (common*.xsd, fundref, JATS, …)
const schema: DepositSchema = {
entry: crossrefXsdText, // e.g. contents of crossref5.3.1.xsd
imports: { 'common5.3.1.xsd': commonText, 'fundref.xsd': fundrefText, /* … */ },
entry: crossrefXsdText, // e.g. contents of crossref5.3.1.xsd
imports: { 'common5.3.1.xsd': commonText, 'fundref.xsd': fundrefText /* … */ },
};

const { ok, errors } = await validateDeposit(xml, schema);
Expand All @@ -31,9 +31,9 @@ A bare `string` entry is accepted but is usually **incomplete** for full Crossre

`crossref validate <file>`:

1. Reads the deposit XML
2. Downloads the Crossref GitLab `schemas/` zip **once** into `~/.cache/crossref-cli/schemas/` (if missing)
3. Builds a `DepositSchema` bundle for the XML’s schema version
1. Reads the deposit XML
2. Downloads the Crossref GitLab `schemas/` zip **once** into `~/.cache/crossref-utils/schemas/` (if missing)
3. Builds a `DepositSchema` bundle for the XML’s schema version
4. Calls `validateDeposit(xml, schema)`

## Why xerces-wasm?
Expand All @@ -42,8 +42,8 @@ Real XSD 1.0 validation without native `node-gyp` addons or shelling to `xmllint

### Serverless (e.g. Vercel)

- Pass a **vendored** `DepositSchema` (no GitLab download in the function).
- Ensure `xerces-wasm`’s `.wasm` asset is included in the function bundle.
- Pass a **vendored** `DepositSchema` (no GitLab download in the function).
- Ensure `xerces-wasm`’s `.wasm` asset is included in the function bundle.
- Cold start: first WASM + XSD compile is heavier; warm isolates help.

## Crossref schema versions
Expand Down
Loading
Loading