The pattern language and the paths a match yields are the reference's,
proven against a frozen pre-redesign bundle (tests/differential.test.ts,
14 501 golden vectors, every behaviour change a named tombstone) and
against bc-envelope-pattern-rust 0.14.0 (tests/rust-validation: 13 794
of 14 501 vectors byte-identical, the rest the documented classes in
RUST_DIVERGENCES.md). §0 lists the changes of the current tree; §1
onwards describes the earlier move from the Result-based API.
The pattern language and the paths a match yields are the reference's; the
matcher, the parser and the surface around them changed. The differential
suite (tests/differential.test.ts, 14 501 vectors against a frozen
bundle) records each change as a named row. Work through the list:
- Every pattern runs on the VM:
a & bis sequential composition (bcontinues whereaended and keeps its captures and extended paths),a | byields the paths of every matching alternative (* | *yields two paths), and(p){1}is a repeat that must move, so(*){1}never matches. A bare(p)is stillp. - Map patterns keep their contents:
{"a": 1}matches only maps with that entry and displays as written. -
tagged(tag, p)matches the envelope only; its paths and captures no longer extend into the tagged content.cbor(/tagged(…)/)still does. - The lexer rejects what it used to skip:
text $,-text,1.,.5,1e3,007,@(text)are errors (UnrecognizedToken,ExtraData).tagged(1),tagged(date)andtagged(/re/)parse astagged(…, *).'+5'is'5';-0.0displays as-0. -
parseEnvelopePatternPrefixandtryParseEnvelopePatternPrefixare gone. -
parseEnvelopePatternandtryParseEnvelopePatterntake an optional{ maxDepth }and reject deeper text withNestingTooDeep; there is no default limit, as in the reference. - Error spans follow the reference's extents, made absolute: a
date'…'error spans the body between the quotes, adigest(…)error points just after the hex or the UR, and[text(an unterminated array) isExpectedCloseBracketat the end of the source. Adate'…'body is read as written, without trimming. -
ParseResult<T>isDcborResult<T, EnvelopePatternError>. -
error.details.spaniserror.span;error.detailsis a discriminated union bycode(kindandtextforUnexpectedToken,causeforInvalidUr,nameforInvalidCaptureGroupName,maxDepthforNestingTooDeep).error.messageno longer carries positions; useerror.fullMessage(source).EnvelopePatternErrorhas no public constructor; theUnknownandDCBORPatternErrorcodes are gone. - The pattern object is plain frozen data:
pattern.kindis"Leaf","Structure"or"Meta"(it waspattern.type),pattern.pattern.typenames the form andpattern.pattern.pattern(or the form's own fields) holds the payload. There are no classes,new()or method accessors. Compare withpatternEquals. -
Pathisreadonly Envelope[],pathsWithCapturesreturns a frozenMatchResult. -
repeat(p, quantifier)takes aQuantifier;tagged(tag, p)takes aTag, a number, a bigint or a registered name;knownValuetakes aKnownValue, a number, a bigint or a name;datetakes aCborDate. - New constructors:
numberGreaterThanOrEqual,numberLessThanOrEqual,numberNaN,byteStringBinaryRegex,knownValueNamed,knownValueRegex,dateIso8601,taggedName,taggedRegex,digestBinaryRegex,arrayWithRange,arrayWithCount,mapWithRange,mapWithCount,nodeWithAssertionsRange,nodeWithAssertionsCount,patternEquals. - Wrong arguments throw: a non-
Patternor non-Envelopeargument topaths,matches,display,pathsWithCapturesorpatternEqualsis aTypeError;number(NaN),capture("a b", …),and(),or(), a digest prefix over 32 bytes and an inverted range areRangeErrors.traverse()is!*. -
/format: the option iselementFormat(it waselement); a malformed option is aRangeError, a non-path argument aTypeError. Known values format by their registered name onceregisterTags()has run;cbor([[1, 2]])displays on one line.
| Entry | Contents |
|---|---|
| root | parseEnvelopePattern/tryParseEnvelopePattern, the constructors, paths, matches, display, pathsWithCaptures, patternEquals, Interval/Quantifier/Reluctance, EnvelopePatternError |
/format |
formatPaths, formatPath, FormatPathsOptions, PathElementFormat, envelopeSummary |
The pattern classes, the VM, the dispatch registries and the per-kind
parsers are no longer exported; VERSION is gone.
| Before | After |
|---|---|
parse(src): Result<Pattern> |
parseEnvelopePattern(src) (throws EnvelopePatternError) or tryParseEnvelopePattern(src): DcborResult<Pattern, EnvelopePatternError> |
parsePartial(src): Result<[Pattern, number]> |
dropped: there is no partial parse |
Result, ok, err, isOk, isErr, unwrap, unwrapOr, map, formatError, the twenty error factories, the bare EnvelopePatternError union |
EnvelopePatternError { code, details, span, fullMessage(source) }, EnvelopePatternErrorCode, DcborResult<T, E> |
result.error.type / result.error.span |
result.error.code / result.error.span |
Spans stay UTF-16 code-unit offsets.
| Before | After |
|---|---|
patternPaths(p, e) / patternMatches(p, e) / patternToString(p) |
paths(p, e) / matches(p, e) / display(p) |
patternPathsWithCaptures(p, e) → [paths, captures] |
pathsWithCaptures(p, e) → { paths, captures } |
and([a, b]) / or([a, b]) / traverse([a, b]) |
and(a, b) / or(a, b) / traverse(a, b) (variadic) |
cborValue(v) / cborPattern(dcborPattern) |
cbor(v) / cbor(dcborPattern) |
unwrapEnvelope() / unwrapMatching(p) |
unwrap() / unwrap(p) |
nullPattern() |
nullValue() |
patternLeaf, patternStructure, patternMeta, patternCompile, patternIsComplex, patternCollectCaptureNames, XxxPattern.new(...) |
internal |
Every other constructor (text, textRegex, number…, date…,
knownValue, subject, predicate, object, anyAssertion,
assertionWithPredicate, wrapped, elided, search, capture,
repeat, group, …) keeps its name.
| Before | After |
|---|---|
formatPaths(paths) / formatPathsOpt(paths, opts) / formatPathsWithCaptures(paths, captures) / formatPathsWithCapturesOpt(paths, captures, opts) |
formatPaths(paths, { captures?, indent?, element?, maxLength?, lastElementOnly? }) |
formatPath(path) / formatPathOpt(path, opts) |
formatPath(path, options?) |
formatPathsOpts().indent(false).build(), defaultFormatPathsOpts(), FormatPathsOptsBuilder |
the options object; every field optional with the same defaults |
summaryFormat(max) / envelopeURFormat() / digestURFormat() |
element: "summary" | "envelopeUR" | "digestUR", maxLength |
- Structure patterns run on the VM:
subjon a node reports the path[node, subject](it reported[subject]), and a structure's alternatives come out in the reference's stack order. - Inherited from dcbor-pattern:
[]is any array, a parenthesised group outside an array matches, tag-1 leaves format as dates.
@blockchaincommons/dcbor-compat and rand are gone; dcbor and
uniform-resources are declared. The leaf patterns build on
@blockchaincommons/dcbor-pattern/internal.
@blockchaincommons/envelope-pattern is the canonical home of this library. It was extracted from the
paritytech/bcts monorepo, where it was
published as @bcts/envelope-pattern, into its own Blockchain Commons repository at
BlockchainCommons/bc-envelope-pattern-ts.
For the extraction release, 1.0.0-beta.1, the public API is unchanged. The
migration is a rename. @bcts/envelope-pattern remains published for one beta cycle as a
thin re-export of this package, so nothing breaks the moment you update.
- Replace the
@bcts/envelope-patterndependency with@blockchaincommons/envelope-pattern. - Rewrite import specifiers:
@bcts/envelope-patternbecomes@blockchaincommons/envelope-pattern. - Raise your Node floor to 22.12.
- Ensure TypeScript >= 5.7 to consume the published types.
- If you relied on the
browserfield or a global-script build, switch to the ESM or CJS entry point.
- import { /* ... */ } from "@bcts/envelope-pattern";
+ import { /* ... */ } from "@blockchaincommons/envelope-pattern"; "dependencies": {
- "@bcts/envelope-pattern": "^1.0.0-beta.6"
+ "@blockchaincommons/envelope-pattern": "^1.0.0-beta.1"
}