Skip to content

v1.0.0-beta.1

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 19 Oct 18:34
· 30 commits to 1.0-beta since this release
f0de337

1.0.0-beta.1 (2026-10-19)

  • feat!: naturalize without proxies, with the 1.0 VM rule (11dd755)

Bug Fixes

  • advance the concat write position by only the copied bytes (b1e10d2), closes #512
  • anonymizer: correct the 103 non-resolving names in tagNamesToEmpty (a034e37), closes #345 #512
  • classify only 0x0010-0x00FF odd-group elements as private creators (d67b109), closes #512
  • core: strip trailing NUL padding from CS values (6baba9d)
  • count view spans, not backing ArrayBuffers, in getBufferMemoryInfo (558a2dc)
  • derive 2.25 UIDs from RFC 4122 UUIDs, and document the intentional 1.0 changes (fd3827a), closes #512
  • eventStream: propagate source errors and unblock the deflate relay (472c8a0)
  • fall back to a structural meta-group walk when (0002,0000) is overstated (92925e4), closes #512
  • make registerTag symmetric without mutating the shared nameMap (b957d68), closes #512 #215
  • parse typed-array and Node Buffer views by their exact byte range (faea45b), closes #512 #311
  • parser: declare the temporary dependency on legacy (fe432f4)
  • preserve private elements through denaturalize in a writable shape (d881f0b), closes #512 388/#215
  • readFile allowMissingHeader opt-in accepts preamble-less and bare datasets (3ac2a24)
  • resolve high-severity audit advisories via pnpm workspace overrides (183859d), closes hi#severity
  • resolve the xs meta-VR in the async reader via the shared PixelRepresentation contract (9081d59), closes #368
  • resolve the xs meta-VR via PixelRepresentation and quiet the unknown-VR fallback (3d451bc)
  • scope the semver override pin to the 6.x range (17f2b64)
  • tag publishes by channel and keep the unscoped root private during the beta (a9d99a8)
  • test: fail fast on bad fixture downloads in downloadToFile (1dac07d)
  • test: make fixture downloads atomic so parallel workers never read a partial file (9dabfa5)
  • tolerate NUL-padded SpecificCharacterSet values (e94438d)
  • write a UV element with a null value instead of throwing (36f64bc), closes #512

Features

  • @dcmjs-org/dicomdir assembly — DICOMDIR reading and writing (#575) (f0de337), closes #589 #611
  • @dcmjs-org/schemas — the naturalized-rules catalog (#543) (27d9e4f)
  • add the async pull adapter with cancellation on early exit (b62a0c9)
  • add the bounded-memory streaming Part 10 reader, free of the vendored tokenizer (29d6689)
  • add the DICOMweb JSON and dataset event sources (53ce80e)
  • add the element-decode primitives and character-set decoders (3735b71)
  • add the event-stream contract and its reference collector (01df93f)
  • add the naturalized-model listener (710086c)
  • eventStream: collector-backed writer sinks — Part10Writer and DicomWebJsonWriter (91ea4fc)
  • eventStream: the DicomEventStream facade and namespace wiring (2023ae2)
  • eventStream: the streaming Part 10 writer (78fb1cd)
  • mark the engine packages publishable under the @dcmjs-org scope (cb65227)
  • scaffold the tests and validator packages (step 8) (12c5be6)
  • write the deflated transfer syntax (f55e2fb)

BREAKING CHANGES

  • envelope.sequences changes from datasetArray to
    datasetArrayOrItem, and the generated SQ property types widen.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • fix(schemas): declare the package as ESM with an exports map

main points at a file that uses export, but the package had no type
field, so Node before 22.7 fails with a SyntaxError and newer Node warns
MODULE_TYPELESS_PACKAGE_JSON. The package now declares type module, an
exports map with the types entry and the JSON Schema path, and a files
list that ships only the generated artifacts.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • fix(schemas): share the sequence shape through one $defs entry

Inlining the two-branch sequence shape into every SQ property made the
compiled ajv validator exceed the call stack, at compile time without
allErrors and at validation time with it. Every SQ property now refs
#/$defs/sequenceValue, which ajv compiles once.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • test(schemas): validate naturalized fixtures against the published schema

Naturalize the three committed DICOM files and validate the result with
ajv against schema/naturalized.schema.json. The structural contract
holds with no exceptions; the three known value-space divergences
(zero-length DA as "", a noncompliant AS value passed through, a
zero-length DS list element as null) are pinned in the test until the
value-format contract is decided.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • feat(schemas)!: derive the attribute rules from the dictionary on demand

The committed 642 KB catalog repeated the packed dictionary that dcmjs
already ships. src/schema/naturalizedRules.js is now a hand-written
module: the hand-decided data stays (envelope, vrFormats, MULTI_VR, the
exclusion lists), and the per-attribute rules derive lazily from
getAllStandardTagEntries through the same isMultiVM rule the runtime
uses, so the two cannot drift. Each rule carries multi, and BINARY_VRS
moves to a shared core utility that DicomMetaDictionary and the schemas
package both import. parseVm loses its competing multi field and keeps
only the VM bounds for the JSON Schema. The generator consumes the src
module and writes only the two artifacts that must be static for ajv
and tsc: the JSON Schema and the .d.ts. The jest determinism gate now
compares those two projections to the committed files.

The envelope gains values: "asReturned" — the schema describes what
dcmjs returns, and vrFormats documents the Part 5 value formats
separately (DS and IS are absent there, because they naturalize as
numbers). The vrFormats stop being applied with the nullability fix,
which lands next.

  • naturalizedRules.attributes is a derived, cached
    getter instead of committed data; entries carry a multi flag;
    dictionaryHash lives only on the generated artifacts.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • fix(schemas)!: encode the as-returned value space

The schema now describes what naturalizeDataset returns (envelope.values
"asReturned"):

  • A present-but-empty element is null, so every property type carries
    null, and list entries can be null (a DS list holds null for an empty
    entry).
  • A binary value is a frame list OR one bulk reference object
    ({BulkDataURI} | {InlineBinary}), through a shared $defs/binaryValue.
  • A PN value is the component object, enforced through $defs/personName.
  • UV and SV are bigint — the readers store readBigUint64/readBigInt64
    values. JSON.stringify throws on them; the type now says so.
  • The Part 5 value formats move from validation keywords to the
    x-dicom-format annotation; vrFormats documents them separately.

The fixture validation test now expects zero divergences for all three
files and adds the two shapes from the review: a present-but-empty
PatientID and PixelData as a bulk reference, plus a null DS list entry.

  • generated property types are nullable; binary and PN
    properties validate through $defs; the JSON Schema no longer enforces
    Part 5 patterns or lengths.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • fix(schemas): close the consumer-facing gaps from the review
  • The generated .d.ts declares the module exports (naturalizedRules,
    getAttributeRule, envelope, vrFormats, the rule and format interfaces),
    so a TypeScript import of the package resolves without TS2305, and the
    tsc gate now imports them.
  • The exports map gains a default condition for require() users.
  • schema-freshness.yml watches the dictionary sources where they live
    now (packages/core/src), plus the isMultiVM and binaryVRs rules the
    derivation depends on.
  • A consumer-walk test reads each fixture file and checks every
    naturalized attribute against its derived rule: list vs scalar and the
    VR's JavaScript type, recursing through sequences.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • docs(schemas): explain the package, pin the tool versions

The README now answers what the package is for and who uses it, how the
rules differ from the raw dictionary (semantics derived on demand, not a
copy), why the package lives in this repository, which artifact serves
which task, and the as-returned value contract — with an ajv usage
example matching the validation test. ajv and typescript move to exact
pins like the other devDependencies, so a minor tsc release cannot
change an @ts-expect-error outcome.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • style: run prettier on the projection test

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • a value with a VM above 1 stays a list when it has one
    value (for example ImageType, OperatorsName, SpecificCharacterSet). An
    empty VM-1 value is null instead of []. A single-item sequence is not an
    array, so forEach, map and push do not work on it; [0], length and
    for...of work. A PN value that a caller assigns gets its accessors when
    the dataset is denaturalized, not on assignment.

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com

  • dcmjs 1.0 replaces the single monolithic package with
    the @dcmjs-org scoped package set (core, legacy, parser, generator,
    schemas). The legacy package preserves today's reader and writer
    surfaces; the event-stream engines are new. See RELEASE_PLAN.md and
    docs/BREAKING_CHANGES.md for the behavior changes.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com