@norskvideo/moq-net 0.1.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/announce.d.ts +7 -0
- package/announce.d.ts.map +1 -0
- package/announce.js +8 -0
- package/announce.js.map +1 -0
- package/announced.d.ts +49 -91
- package/announced.d.ts.map +1 -1
- package/announced.js +21 -156
- package/announced.js.map +1 -1
- package/bandwidth.d.ts +163 -0
- package/bandwidth.d.ts.map +1 -0
- package/bandwidth.js +304 -0
- package/bandwidth.js.map +1 -0
- package/bandwidth_api.d.ts +7 -0
- package/bandwidth_api.d.ts.map +1 -0
- package/bandwidth_api.js +8 -0
- package/bandwidth_api.js.map +1 -0
- package/broadcast.d.ts +44 -35
- package/broadcast.d.ts.map +1 -1
- package/broadcast.js +104 -60
- package/broadcast.js.map +1 -1
- package/connection/accept.d.ts +16 -1
- package/connection/accept.d.ts.map +1 -1
- package/connection/accept.js +52 -28
- package/connection/accept.js.map +1 -1
- package/connection/browser.d.ts.map +1 -1
- package/connection/browser.js +9 -7
- package/connection/browser.js.map +1 -1
- package/connection/connect.d.ts +30 -6
- package/connection/connect.d.ts.map +1 -1
- package/connection/connect.js +110 -54
- package/connection/connect.js.map +1 -1
- package/connection/established.d.ts +17 -21
- package/connection/established.d.ts.map +1 -1
- package/connection/established.js.map +1 -1
- package/connection/forward.d.ts +2 -0
- package/connection/forward.d.ts.map +1 -0
- package/connection/forward.js +173 -0
- package/connection/forward.js.map +1 -0
- package/connection/handshake.d.ts +1 -0
- package/connection/handshake.d.ts.map +1 -1
- package/connection/handshake.js +5 -2
- package/connection/handshake.js.map +1 -1
- package/connection/index.d.ts +5 -5
- package/connection/index.d.ts.map +1 -1
- package/connection/index.js +4 -5
- package/connection/index.js.map +1 -1
- package/connection/pool.d.ts +186 -0
- package/connection/pool.d.ts.map +1 -0
- package/connection/pool.js +361 -0
- package/connection/pool.js.map +1 -0
- package/connection/reload.d.ts +14 -93
- package/connection/reload.d.ts.map +1 -1
- package/connection/reload.js +217 -81
- package/connection/reload.js.map +1 -1
- package/connection/stats.d.ts +3 -26
- package/connection/stats.d.ts.map +1 -1
- package/connection/stats.js.map +1 -1
- package/connection/transport.d.ts +0 -7
- package/connection/transport.d.ts.map +1 -1
- package/consume.d.ts +1 -43
- package/consume.d.ts.map +1 -1
- package/consume.js +1 -1
- package/consume.js.map +1 -1
- package/error.d.ts +180 -29
- package/error.d.ts.map +1 -1
- package/error.js +331 -16
- package/error.js.map +1 -1
- package/errors.d.ts +7 -0
- package/errors.d.ts.map +1 -0
- package/errors.js +8 -0
- package/errors.js.map +1 -0
- package/group.d.ts +9 -43
- package/group.d.ts.map +1 -1
- package/group.js +284 -69
- package/group.js.map +1 -1
- package/hop.d.ts +115 -0
- package/hop.d.ts.map +1 -0
- package/hop.js +119 -0
- package/hop.js.map +1 -0
- package/ietf/adapter.d.ts +5 -1
- package/ietf/adapter.d.ts.map +1 -1
- package/ietf/adapter.js +105 -60
- package/ietf/adapter.js.map +1 -1
- package/ietf/aliases.d.ts +1 -78
- package/ietf/aliases.d.ts.map +1 -1
- package/ietf/cluster.d.ts +9 -123
- package/ietf/cluster.d.ts.map +1 -1
- package/ietf/cluster.js +84 -44
- package/ietf/cluster.js.map +1 -1
- package/ietf/connection.d.ts +6 -72
- package/ietf/connection.d.ts.map +1 -1
- package/ietf/connection.js +62 -56
- package/ietf/connection.js.map +1 -1
- package/ietf/error.d.ts +11 -0
- package/ietf/error.d.ts.map +1 -0
- package/ietf/error.js +193 -0
- package/ietf/error.js.map +1 -0
- package/ietf/fetch.d.ts +7 -20
- package/ietf/fetch.d.ts.map +1 -1
- package/ietf/fetch.js +52 -22
- package/ietf/fetch.js.map +1 -1
- package/ietf/filter.d.ts +2 -0
- package/ietf/filter.d.ts.map +1 -1
- package/ietf/filter.js +10 -1
- package/ietf/filter.js.map +1 -1
- package/ietf/goaway.d.ts.map +1 -1
- package/ietf/goaway.js +22 -5
- package/ietf/goaway.js.map +1 -1
- package/ietf/hidden.d.ts +2 -0
- package/ietf/hidden.d.ts.map +1 -0
- package/ietf/hidden.js +30 -0
- package/ietf/hidden.js.map +1 -0
- package/ietf/index.d.ts +2 -0
- package/ietf/index.d.ts.map +1 -1
- package/ietf/index.js +2 -0
- package/ietf/index.js.map +1 -1
- package/ietf/object.d.ts +15 -8
- package/ietf/object.d.ts.map +1 -1
- package/ietf/object.js +51 -36
- package/ietf/object.js.map +1 -1
- package/ietf/parameters.d.ts +14 -2
- package/ietf/parameters.d.ts.map +1 -1
- package/ietf/parameters.js +97 -29
- package/ietf/parameters.js.map +1 -1
- package/ietf/properties.d.ts +1 -0
- package/ietf/properties.d.ts.map +1 -1
- package/ietf/properties.js +14 -0
- package/ietf/properties.js.map +1 -1
- package/ietf/publish.d.ts +19 -2
- package/ietf/publish.d.ts.map +1 -1
- package/ietf/publish.js +40 -6
- package/ietf/publish.js.map +1 -1
- package/ietf/publish_namespace.d.ts +25 -0
- package/ietf/publish_namespace.d.ts.map +1 -1
- package/ietf/publish_namespace.js +63 -0
- package/ietf/publish_namespace.js.map +1 -1
- package/ietf/publisher.d.ts +1 -82
- package/ietf/publisher.d.ts.map +1 -1
- package/ietf/publisher.js +483 -235
- package/ietf/publisher.js.map +1 -1
- package/ietf/solicit.d.ts +1 -40
- package/ietf/solicit.d.ts.map +1 -1
- package/ietf/subscribe.d.ts +8 -6
- package/ietf/subscribe.d.ts.map +1 -1
- package/ietf/subscribe.js +33 -27
- package/ietf/subscribe.js.map +1 -1
- package/ietf/subscribe_namespace.d.ts +8 -2
- package/ietf/subscribe_namespace.d.ts.map +1 -1
- package/ietf/subscribe_namespace.js +18 -8
- package/ietf/subscribe_namespace.js.map +1 -1
- package/ietf/subscriber.d.ts +1 -65
- package/ietf/subscriber.d.ts.map +1 -1
- package/ietf/subscriber.js +337 -123
- package/ietf/subscriber.js.map +1 -1
- package/ietf/token.d.ts +2 -0
- package/ietf/token.d.ts.map +1 -0
- package/ietf/token.js +99 -0
- package/ietf/token.js.map +1 -0
- package/ietf/track.d.ts +4 -0
- package/ietf/track.d.ts.map +1 -1
- package/ietf/track.js +6 -20
- package/ietf/track.js.map +1 -1
- package/ietf/version.d.ts +12 -1
- package/ietf/version.d.ts.map +1 -1
- package/ietf/version.js +13 -0
- package/ietf/version.js.map +1 -1
- package/index.d.ts +12 -7
- package/index.d.ts.map +1 -1
- package/index.js +10 -5
- package/index.js.map +1 -1
- package/internal.d.ts +115 -1
- package/internal.d.ts.map +1 -1
- package/internal.js +108 -0
- package/internal.js.map +1 -1
- package/lite/announce.d.ts +60 -10
- package/lite/announce.d.ts.map +1 -1
- package/lite/announce.js +176 -31
- package/lite/announce.js.map +1 -1
- package/lite/connection.d.ts +9 -59
- package/lite/connection.d.ts.map +1 -1
- package/lite/connection.js +34 -35
- package/lite/connection.js.map +1 -1
- package/lite/datagram.d.ts +3 -2
- package/lite/datagram.d.ts.map +1 -1
- package/lite/datagram.js +7 -8
- package/lite/datagram.js.map +1 -1
- package/lite/fetch.d.ts +15 -1
- package/lite/fetch.d.ts.map +1 -1
- package/lite/fetch.js +39 -7
- package/lite/fetch.js.map +1 -1
- package/lite/goaway.d.ts.map +1 -1
- package/lite/goaway.js +7 -1
- package/lite/goaway.js.map +1 -1
- package/lite/group.d.ts +30 -12
- package/lite/group.d.ts.map +1 -1
- package/lite/group.js +68 -26
- package/lite/group.js.map +1 -1
- package/lite/message.d.ts +2 -2
- package/lite/message.d.ts.map +1 -1
- package/lite/message.js +14 -5
- package/lite/message.js.map +1 -1
- package/lite/priority.d.ts +1 -61
- package/lite/priority.d.ts.map +1 -1
- package/lite/priority.js +4 -5
- package/lite/priority.js.map +1 -1
- package/lite/publisher.d.ts +1 -69
- package/lite/publisher.d.ts.map +1 -1
- package/lite/publisher.js +630 -262
- package/lite/publisher.js.map +1 -1
- package/lite/setup.d.ts +8 -8
- package/lite/setup.d.ts.map +1 -1
- package/lite/setup.js +33 -30
- package/lite/setup.js.map +1 -1
- package/lite/subscribe.d.ts +71 -17
- package/lite/subscribe.d.ts.map +1 -1
- package/lite/subscribe.js +205 -53
- package/lite/subscribe.js.map +1 -1
- package/lite/subscriber.d.ts +15 -56
- package/lite/subscriber.d.ts.map +1 -1
- package/lite/subscriber.js +451 -247
- package/lite/subscriber.js.map +1 -1
- package/lite/track.d.ts +4 -10
- package/lite/track.d.ts.map +1 -1
- package/lite/track.js +34 -29
- package/lite/track.js.map +1 -1
- package/lite/version.d.ts +42 -6
- package/lite/version.d.ts.map +1 -1
- package/lite/version.js +126 -10
- package/lite/version.js.map +1 -1
- package/origin.d.ts +256 -29
- package/origin.d.ts.map +1 -1
- package/origin.js +1427 -37
- package/origin.js.map +1 -1
- package/package.json +8 -3
- package/path.d.ts +25 -7
- package/path.d.ts.map +1 -1
- package/path.js +5 -3
- package/path.js.map +1 -1
- package/stream.d.ts +73 -14
- package/stream.d.ts.map +1 -1
- package/stream.js +372 -141
- package/stream.js.map +1 -1
- package/tail.d.ts +18 -0
- package/tail.d.ts.map +1 -0
- package/tail.js +167 -0
- package/tail.js.map +1 -0
- package/time.d.ts +15 -2
- package/time.d.ts.map +1 -1
- package/time.js +28 -9
- package/time.js.map +1 -1
- package/track.d.ts +211 -83
- package/track.d.ts.map +1 -1
- package/track.js +816 -205
- package/track.js.map +1 -1
- package/util/abort.d.ts +2 -0
- package/util/abort.d.ts.map +1 -0
- package/util/abort.js +20 -0
- package/util/abort.js.map +1 -0
- package/util/log.d.ts +5 -0
- package/util/log.d.ts.map +1 -0
- package/util/log.js +17 -0
- package/util/log.js.map +1 -0
- package/util/u64.d.ts +39 -0
- package/util/u64.d.ts.map +1 -0
- package/util/u64.js +83 -0
- package/util/u64.js.map +1 -0
- package/util/varint.d.ts +29 -0
- package/util/varint.d.ts.map +1 -0
- package/util/varint.js +198 -0
- package/util/varint.js.map +1 -0
- package/varint.d.ts +10 -6
- package/varint.d.ts.map +1 -1
- package/varint.js +40 -237
- package/varint.js.map +1 -1
- package/wire.d.ts +80 -0
- package/wire.d.ts.map +1 -0
- package/wire.js +32 -0
- package/wire.js.map +1 -0
- package/zod.d.ts +1 -1
- package/zod.d.ts.map +1 -1
- package/zod.js.map +1 -1
- package/mock.d.ts +0 -66
- package/mock.d.ts.map +0 -1
- package/mock.js +0 -243
- package/mock.js.map +0 -1
package/origin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"origin.js","sourceRoot":"","sources":["../src/origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAE9B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC;KAC3B,MAAM,EAAE;KACR,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,8CAA8C,CAAC,CAAC;KAC5G,KAAK,CAAC,QAAQ,CAAC,CAAC;AAIlB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAW,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,CAAC;AAE3B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY;IAC3B,MAAM,GAAG,GAAG,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC5B,mBAAmB;IACnB,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,iBAAoB,CAAC;IAC1C,yDAAyD;IACzD,OAAO,YAAY,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAClD,CAAC","sourcesContent":["/**\n * Endpoint identity within a hop chain, shared by both wire protocols.\n *\n * moq-lite carries these natively on every announcement; moq-transport carries them\n * via the MoQ Cluster extension (see `ietf/cluster.ts`). Mirrors `Origin` in\n * `rs/moq-net`.\n *\n * @module\n */\nimport * as z from \"zod/mini\";\n\n/**\n * A relay origin id, encoded as a 62-bit varint on the wire.\n *\n * The {@link OriginSchema} validates any incoming value and brands it so the\n * type system enforces \"only validated origins flow into hop lists.\" Internal\n * code that synthesizes an id (e.g. {@link randomOrigin}) uses\n * `OriginSchema.parse(...)` to produce a branded value from the raw bigint.\n */\nexport const OriginSchema = z\n\t.bigint()\n\t.check(z.refine((value) => value >= 0n && value < 1n << 62n, \"Origin must be a non-negative 62-bit integer\"))\n\t.brand(\"Origin\");\n\nexport type Origin = z.infer<typeof OriginSchema>;\n\n/**\n * The reserved id 0, meaning \"no identity\".\n *\n * It stands in for an endpoint that never declared one, and any number of endpoints can\n * be 0, so it identifies nothing: it is never a loop, never a publisher two chains have\n * in common, and never excluded from an advertisement.\n */\nexport const UNKNOWN_ORIGIN: Origin = OriginSchema.parse(0n);\n\n/**\n * Maximum length of a hop chain. Must match `MAX_HOPS` in Rust's `model/origin.rs`.\n *\n * Broadcasts with longer chains are rejected, which bounds loop detection and rejects\n * pathological announcements across clusters with unbounded forwarding.\n */\nexport const MAX_HOPS = 32;\n\n/**\n * Generate a fresh origin with a random non-zero id.\n *\n * `crypto.getRandomValues` is overkill for best-effort loop detection, but\n * used for slightly better distribution than `Math.random` at negligible cost.\n *\n * TEMPORARY: the wire format allows 62 bits, but older `@moq/lite` JS clients\n * decode `AnnounceInterest.exclude_hop` as a u53 (number) and throw on anything\n * > 2^53-1. To keep those clients alive against fresh peers, we cap the random\n * id at 53 bits. Restore to 62 bits once the u62 fix has propagated to deployed\n * bundles. Mirrors `Origin::random` in rs/moq-net.\n */\nexport function randomOrigin(): Origin {\n\tconst buf = new BigUint64Array(1);\n\tcrypto.getRandomValues(buf);\n\t// Mask to 53 bits.\n\tconst raw = buf[0] & 0x1f_ffff_ffff_ffffn;\n\t// Guard against the (astronomically unlikely) zero draw.\n\treturn OriginSchema.parse(raw === 0n ? 1n : raw);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"origin.js","sourceRoot":"","sources":["../src/origin.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A broadcast routing table, independent of any connection.\n *\n * Publish broadcasts into an origin and hand the origin to one or more connections to\n * serve them; the broadcasts outlive any single session. Hand the same (or another)\n * origin to a connection's `consume` option and the peer's announced routes appear\n * in the table too: each route covers a path prefix, and a request for a path under\n * it resolves through the session that announced it. Mirrors the `origin` module in\n * `rs/moq-net`.\n *\n * @module\n */\nimport { Derived, type Dispose, type GetPromise, type Getter, getter, Once, Signal } from \"@moq/signals\";\nimport * as announce from \"./announced.ts\";\nimport * as broadcast from \"./broadcast.ts\";\nimport { StreamCode, StreamError } from \"./error.ts\";\nimport { isAnonymous, Route, routesEqual } from \"./hop.ts\";\nimport { hiddenBelow, hooks, scopeCaptures, scopeHead, scopeOverlaps } from \"./internal.ts\";\nimport * as Path from \"./path.ts\";\nimport { type Advertised, type Advertisements, registerWire, wireOf } from \"./wire.ts\";\n\nexport type { Cost, Hop, Route } from \"./hop.ts\";\nexport { isAnonymous } from \"./hop.ts\";\n\n/** The rooted permissions shared by a handle and every route it inserts. */\nclass Scope {\n\tstatic readonly all = new Scope(Path.empty());\n\n\treadonly root: Path.Valid;\n\treadonly allowed?: Path.Patterns;\n\n\tconstructor(root: Path.Valid, allowed?: Path.Patterns) {\n\t\tthis.root = root;\n\t\tthis.allowed = allowed;\n\t}\n\n\tnarrow(root: Path.Valid, patterns: Path.Patterns): Scope {\n\t\tconst joined = Path.encode(Path.join(this.root, root));\n\t\tconst rooted = patterns.rooted(joined);\n\t\tconst allowed = this.allowed?.intersect(rooted) ?? rooted;\n\t\tif (allowed.size === 0) throw new Error(\"origin scopes do not overlap\");\n\t\treturn new Scope(joined, allowed);\n\t}\n\n\tmatches(path: Path.Valid): boolean {\n\t\treturn this.allowed?.matches(path) ?? true;\n\t}\n\n\tpath(path: Path.Valid): Path.Valid {\n\t\tconst joined = Path.encode(Path.join(this.root, path));\n\t\tif (!this.matches(joined)) throw new Error(\"path is outside the origin scope\");\n\t\treturn joined;\n\t}\n\n\tprefix(prefix: Path.Valid): Path.Valid {\n\t\tconst joined = Path.encode(Path.join(this.root, prefix));\n\t\tif (this.allowed && !this.allowed.overlaps(Path.Pattern.subtree(joined))) {\n\t\t\tthrow new Error(\"prefix is outside the origin scope\");\n\t\t}\n\t\treturn joined;\n\t}\n\n\tpatterns(pattern: Path.Pattern = Path.Pattern.all()): Path.Patterns {\n\t\tconst rooted = new Path.Patterns([pattern.rooted(this.root)]);\n\t\treturn this.allowed?.intersect(rooted) ?? rooted;\n\t}\n\n\t/** Omit nested heads because the outer subscription already carries their routes. */\n\theads(): Path.Valid[] {\n\t\tif (!this.allowed) return [Path.empty()];\n\t\tconst heads = [...new Set([...this.allowed.rebase(this.root)].map(scopeHead))].sort();\n\t\treturn heads.filter((head) => !heads.some((other) => other !== head && Path.hasPrefix(other, head)));\n\t}\n\n\t/** The exact paths within this scope, relative to its root. */\n\tprojectPaths<T>(values: ReadonlyMap<Path.Valid, T> | undefined): ReadonlyMap<Path.Valid, T> | undefined {\n\t\tif (!values || this === Scope.all) return values;\n\t\tconst out = new Map<Path.Valid, T>();\n\t\tfor (const [path, value] of values) {\n\t\t\tif (!this.matches(path)) continue;\n\t\t\tconst relative = Path.stripPrefix(this.root, path);\n\t\t\tif (relative !== null) out.set(relative, value);\n\t\t}\n\t\treturn out;\n\t}\n\n\t/**\n\t * The advertisements that may serve this scope, relative to its root. Every prefix at or\n\t * above the root presents as the empty path, most specific first, since that is the order\n\t * a request beneath the root resolves in.\n\t */\n\tprojectRoutes(values: Advertisements | undefined): Advertisements | undefined {\n\t\tif (!values || this === Scope.all) return values;\n\t\tconst out = new Map<Path.Valid, readonly Advertised[]>();\n\t\tconst covering: [Path.Valid, Advertised[]][] = [];\n\t\tconst allowed = this.allowed && [...this.allowed];\n\t\tfor (const [path, candidates] of values) {\n\t\t\tconst relative = Path.stripPrefix(this.root, path);\n\t\t\tconst above = relative === null || relative === Path.empty();\n\t\t\tif (above && !Path.hasPrefix(path, this.root)) continue;\n\t\t\tconst visible = candidates\n\t\t\t\t.filter((value) => !allowed || allowed.some((pattern) => advertOverlaps(value, path, pattern)))\n\t\t\t\t// The claim moves with the key, so it compares against root-relative requests.\n\t\t\t\t.map((value) => (value.claim ? { ...value, claim: value.claim.rebase(this.root) } : value));\n\t\t\tif (visible.length === 0) continue;\n\t\t\tif (!above) {\n\t\t\t\tout.set(relative, visible);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Hold the empty path's place in the order until every covering prefix is known.\n\t\t\tif (covering.length === 0) out.set(Path.empty(), []);\n\t\t\tcovering.push([path, visible]);\n\t\t}\n\t\tif (covering.length > 0) {\n\t\t\tcovering.sort(([a], [b]) => b.length - a.length);\n\t\t\tout.set(\n\t\t\t\tPath.empty(),\n\t\t\t\tcovering.flatMap(([, visible]) => visible),\n\t\t\t);\n\t\t}\n\t\treturn out;\n\t}\n}\n\n/** Whether the route advertised at `prefix` may serve any path `pattern` admits. */\nfunction advertOverlaps(advert: Advertised, prefix: Path.Valid, pattern: Path.Pattern): boolean {\n\treturn advert.claim ? advert.claim.overlaps(pattern) : scopeOverlaps(pattern, prefix);\n}\n\n/**\n * Presents advertised prefixes relative to a root. Every prefix at or above the root\n * collapses to the empty path, where the most specific one wins, since that is the route\n * a request beneath the root resolves through.\n */\nclass CoveringRoot {\n\treadonly #root: Path.Valid;\n\t#covering?: Path.Valid;\n\n\tconstructor(root: Path.Valid) {\n\t\tthis.#root = root;\n\t}\n\n\t/** The presented path for `path`, or undefined when it is outside the root or a broader cover. */\n\trelative(path: Path.Valid): Path.Valid | undefined {\n\t\tconst relative = Path.stripPrefix(this.#root, path);\n\t\tif (relative !== null && relative !== Path.empty()) return relative;\n\t\tif (relative === null && !Path.hasPrefix(path, this.#root)) return undefined;\n\t\tif (this.#covering !== undefined && !Path.hasPrefix(this.#covering, path)) return undefined;\n\t\tthis.#covering = path;\n\t\treturn Path.empty();\n\t}\n}\n\n/**\n * One requested path: the notify node for everything watching it.\n *\n * `route` is the only reactive part, and the only thing a {@link Request} subscribes to, so\n * a publish or retraction anywhere else in the table cannot wake it. The origin's tables stay\n * the storage; this is a per-path view onto them, refreshed by whichever mutator touched the\n * path. The alternative, deriving each request over the whole `local`/`remote` maps, wakes\n * every open request on every unrelated change.\n *\n * `answer` outlives a session: the answering session clears it when it dies and the next one\n * answers again, which is what makes a request span reconnects.\n *\n * `handles` holds the `closed` of each open {@link Requesting} on the path.\n *\n * A refusal is terminal. With nothing serving, the slot ends: every handle closes with the\n * handler's error and the slot leaves the table, so the next request asks afresh. While\n * another source still serves (a better route was asked and said no), the refuser joins\n * `refused` and is skipped for as long as it stands (a reconnect is a fresh entry), so the\n * current source carries on. A refusal never falls through to a broader prefix or another\n * advertiser.\n *\n * @internal\n */\nexport interface RequestSlot {\n\tblind: number;\n\tanswer?: broadcast.Consumer;\n\treadonly handles: Set<Once<Error | null>>;\n\treadonly refused: Set<RouteEntry>;\n\treadonly route: Signal<broadcast.Consumer | undefined>;\n}\n\n/**\n * One advertised prefix: hops and cost, plus an optional server that answers\n * requests beneath it.\n *\n * The preferred entry per prefix is the one requests resolve through. An originated\n * entry is forwarded by sessions; a received one is not, so a shared origin\n * cannot echo a peer's announcements back to it.\n *\n * @internal\n */\nexport interface RouteEntry {\n\treadonly identity: object;\n\treadonly scope: Scope;\n\t/** The paths the entry may serve beneath its prefix, when its producer is scoped. */\n\treadonly claim?: Path.Patterns;\n\treadonly route: Signal<Route>;\n\treadonly originated: boolean;\n\treadonly server?: ServeState;\n}\n\n/** One advertisement at a prefix. `exact` marks an announced local broadcast, which is only its own path. */\ninterface Candidate extends Advertised {\n\treadonly exact: boolean;\n}\n\n/** Orders advertisements at one prefix: the better route, then a local broadcast on a tie, then fewer hops. */\nfunction compareCandidates(a: Candidate, b: Candidate): number {\n\treturn (\n\t\tcompareRoutes(a.route, b.route) ||\n\t\tNumber(b.exact) - Number(a.exact) ||\n\t\ta.route.hops.length - b.route.hops.length\n\t);\n}\n\n/** Orders two routes by preference: identified before anonymous, then lower warm cost, then lower cold cost. */\nfunction compareRoutes(a: Route, b: Route): number {\n\tconst anonymous = Number(isAnonymous(a)) - Number(isAnonymous(b));\n\tif (anonymous !== 0) return anonymous;\n\tif (a.cost.warm !== b.cost.warm) return a.cost.warm < b.cost.warm ? -1 : 1;\n\tif (a.cost.cold !== b.cost.cold) return a.cost.cold < b.cost.cold ? -1 : 1;\n\treturn 0;\n}\n\n/** The preferred of `entries` (newest first) not skipped: the best route, then fewest hops, then newest. */\nfunction preferredEntry(entries: readonly RouteEntry[], skip?: (entry: RouteEntry) => boolean): RouteEntry | undefined {\n\tlet best: RouteEntry | undefined;\n\tfor (const entry of entries) {\n\t\tif (skip?.(entry)) continue;\n\t\tif (!best) {\n\t\t\tbest = entry;\n\t\t\tcontinue;\n\t\t}\n\t\tconst a = entry.route.peek();\n\t\tconst b = best.route.peek();\n\t\tconst order = compareRoutes(a, b) || a.hops.length - b.hops.length;\n\t\tif (order < 0) best = entry;\n\t}\n\treturn best;\n}\n\n/** Whether a session received `entry`, so it is never forwarded to a peer. */\nfunction received(entry: RouteEntry): boolean {\n\treturn !entry.originated;\n}\n\nfunction noCapacity(): StreamError {\n\treturn new StreamError(StreamCode.NoCapacity, { message: \"no capacity\" });\n}\n\n/** A served route from {@link Producer.dynamic}: the queue a handler drains. */\nclass ServeState {\n\treadonly root: Path.Valid;\n\n\tconstructor(root: Path.Valid) {\n\t\tthis.root = root;\n\t}\n\n\tqueue = new Signal<Request[]>([]);\n\tpending = new Map<Path.Valid, Request>();\n\tserved = new Map<Path.Valid, broadcast.Consumer>();\n\trejected = new Map<Path.Valid, Error>();\n\t// demand() is the only reader of `rejected`. A Consumer.request refusal never\n\t// re-enqueues, so storing the error without a waiter would pin every unique\n\t// path until the route dies.\n\tdemanding = new Map<Path.Valid, number>();\n\tclosed = new Once<Error | null>();\n\tsettled = new Signal(0);\n\tonChange: (path: Path.Valid) => void = () => {};\n\tonReject: (path: Path.Valid, err: Error) => void = () => {};\n\n\tenqueue(path: Path.Valid): void {\n\t\tif (this.closed.peek() !== undefined) return;\n\t\tthis.rejected.delete(path);\n\t\tif (this.pending.has(path)) return;\n\t\tconst live = this.served.get(path);\n\t\tif (live && live.closed.peek() === undefined) return;\n\t\tconst request = makeRequest(Path.stripPrefix(this.root, path) ?? Path.empty(), this);\n\t\tthis.pending.set(path, request);\n\t\tthis.queue.mutate((queue) => {\n\t\t\tqueue.push(request);\n\t\t});\n\t}\n\n\taccept(request: Request, front: broadcast.Consumer): void {\n\t\tconst path = Path.join(this.root, request.path);\n\t\tif (this.closed.peek() !== undefined || this.pending.get(path) !== request) {\n\t\t\tfront.close();\n\t\t\treturn;\n\t\t}\n\t\tthis.pending.delete(path);\n\t\tconst existing = this.served.get(path);\n\t\tif (existing && existing.closed.peek() === undefined) {\n\t\t\tfront.close();\n\t\t\tthis.onChange(path);\n\t\t\tthis.settled.update((n) => n + 1);\n\t\t\treturn;\n\t\t}\n\t\tthis.served.set(path, front);\n\t\tvoid front.closed.then(() => {\n\t\t\tif (this.served.get(path) !== front) return;\n\t\t\tthis.served.delete(path);\n\t\t\tthis.onChange(path);\n\t\t});\n\t\tthis.onChange(path);\n\t\tthis.settled.update((n) => n + 1);\n\t}\n\n\treject(request: Request, err: Error): void {\n\t\tconst path = Path.join(this.root, request.path);\n\t\tif (this.pending.get(path) !== request) return;\n\t\tthis.pending.delete(path);\n\t\tif (this.demanding.has(path)) this.rejected.set(path, err);\n\t\tthis.onReject(path, err);\n\t\tthis.settled.update((n) => n + 1);\n\t}\n\n\tclose(abort?: Error): void {\n\t\tif (this.closed.peek() !== undefined) return;\n\t\tconst err = abort ?? noCapacity();\n\t\tthis.closed.set(err);\n\t\tconst queued = [...this.pending.values()];\n\t\tthis.pending.clear();\n\t\tthis.queue.mutate((queue) => {\n\t\t\tqueue.length = 0;\n\t\t});\n\t\tfor (const request of queued) {\n\t\t\tfinishRequest(request, err);\n\t\t}\n\t\tfor (const [path, front] of this.served) {\n\t\t\tfront.close();\n\t\t\tthis.onChange(path);\n\t\t}\n\t\tthis.served.clear();\n\t\tthis.rejected.clear();\n\t\tthis.demanding.clear();\n\t\tthis.settled.update((n) => n + 1);\n\t}\n}\n\ninterface Presented extends Advertised {\n\treadonly captures: Path.Pattern[] | undefined;\n}\n\n/** A table mutation invalidates the shared route snapshot before its async notification. */\nclass VersionedSignal<T> extends Signal<T> {\n\tversion = 0;\n\n\toverride set(value: T, notify?: boolean): void {\n\t\tthis.version++;\n\t\tsuper.set(value, notify);\n\t}\n}\n\n/** Reactive backing state shared by origin producers and consumers. */\nclass OriginState {\n\t// Both tables decouple the application producing into the origin from the\n\t// connections serving or feeding it. Undefined once the origin closes, so late\n\t// writes fail loudly.\n\t//\n\t// Created is what this endpoint publishes, keyed by exact path, announced or not.\n\t// Local is the announced subset, with its route in advertisedLocal: a broadcast\n\t// exists for nobody, here or at a peer, until it announces. Routes is the\n\t// advertisement table: prefixes a dynamic handle or a received session covers,\n\t// newest first. Local and routes stay separate so a session can never announce a\n\t// received entry back to a peer, which is what makes an origin shared by both\n\t// directions echo-free.\n\tcreated: Map<Path.Valid, broadcast.Consumer> | undefined = new Map();\n\tlocal = new VersionedSignal<Map<Path.Valid, broadcast.Consumer> | undefined>(new Map());\n\tadvertisedLocal = new VersionedSignal<Map<Path.Valid, Route> | undefined>(new Map());\n\troutes = new VersionedSignal<Map<Path.Valid, RouteEntry[]> | undefined>(new Map());\n\n\t#snapshotVersion = \"\";\n\t#snapshot: {\n\t\tcandidates: ReadonlyMap<Path.Valid, readonly Candidate[]>;\n\t\troutes: ReadonlyMap<Path.Valid, Route>;\n\t\tvisible: ReadonlyMap<Path.Valid, Route>;\n\t} = { candidates: new Map(), routes: new Map(), visible: new Map() };\n\n\t/** The full route table is built once per mutation, regardless of observer count. */\n\tavailable = new Derived([this.local, this.advertisedLocal, this.routes], () => this.snapshot().routes);\n\t/** {@link available} without hidden routes, for unscoped readers that did not opt in. */\n\tvisible = new Derived([this.local, this.advertisedLocal, this.routes], () => this.snapshot().visible);\n\n\tsnapshot(): {\n\t\tcandidates: ReadonlyMap<Path.Valid, readonly Candidate[]>;\n\t\troutes: ReadonlyMap<Path.Valid, Route>;\n\t\tvisible: ReadonlyMap<Path.Valid, Route>;\n\t} {\n\t\tconst version = `${this.local.version}/${this.advertisedLocal.version}/${this.routes.version}`;\n\t\tif (version === this.#snapshotVersion) return this.#snapshot;\n\t\tconst candidates = this.candidates();\n\t\tconst available = new Map<Path.Valid, Route>();\n\t\tconst visible = new Map<Path.Valid, Route>();\n\t\tfor (const [path, [best]] of candidates) {\n\t\t\tavailable.set(path, best.route);\n\t\t\tif (!hiddenBelow(Path.empty(), path)) visible.set(path, best.route);\n\t\t}\n\t\tthis.#snapshot = { candidates, routes: available, visible };\n\t\tthis.#snapshotVersion = version;\n\t\treturn this.#snapshot;\n\t}\n\n\t/**\n\t * Every advertisement per prefix, most preferred first, without the `skip`ped entries.\n\t * Readers select after filtering by their scope, so a cheaper route they cannot see\n\t * never hides one they can.\n\t */\n\tcandidates(skip?: (entry: RouteEntry) => boolean): Map<Path.Valid, Candidate[]> {\n\t\tconst out = new Map<Path.Valid, Candidate[]>();\n\t\tfor (const [path, entries] of this.routes.peek() ?? []) {\n\t\t\tconst list: Candidate[] = [];\n\t\t\tfor (const entry of entries) {\n\t\t\t\tif (skip?.(entry)) continue;\n\t\t\t\tlist.push({ identity: entry.identity, route: entry.route.peek(), claim: entry.claim, exact: false });\n\t\t\t}\n\t\t\tif (list.length > 0) out.set(path, list);\n\t\t}\n\t\tconst advertised = this.advertisedLocal.peek();\n\t\tfor (const [path, front] of this.local.peek() ?? []) {\n\t\t\tconst local = { identity: front, route: advertised?.get(path) ?? Route.default, exact: true };\n\t\t\tconst list = out.get(path);\n\t\t\tif (list) list.push(local);\n\t\t\telse out.set(path, [local]);\n\t\t}\n\t\tfor (const list of out.values()) {\n\t\t\t// Stable, so equal routes keep the table's newest-first order.\n\t\t\tif (list.length > 1) list.sort(compareCandidates);\n\t\t}\n\t\treturn out;\n\t}\n\n\t// Originated advertisements sessions should forward: exact-path announces plus\n\t// originated dynamics. Identity is the local front or the route entry, so a\n\t// republish diffs as retract-then-announce and a re-price as another active.\n\toriginated = new Signal<Advertisements | undefined>(new Map());\n\n\t// Broadcasts materialized from a served route, keyed by exact path. Shared by every\n\t// request for the path so repeats reuse one accept; dropped (and closed) when the\n\t// providing route goes away or the last request releases it.\n\tmaterialized = new Map<Path.Valid, { entry: RouteEntry; front: broadcast.Consumer }>();\n\n\t// Paths consumers asked for without waiting for an announcement; attached sessions\n\t// answer them with blind subscriptions. Never announced: an answered request is assumed\n\t// present, not known live, so it must not read as an availability claim.\n\trequests = new Signal<Map<Path.Valid, RequestSlot> | undefined>(new Map());\n\n\t// How many sessions are attached, and how many of those support broadcast discovery.\n\t// What backs the public `discovery` getter.\n\tsessions = new Signal({ total: 0, discovery: 0 });\n\n\t// How many things are prepared to answer a request: attached sessions, plus reconnecting\n\t// connections that have no session right now but will. Zero means an unrouted path is\n\t// unroutable rather than merely unanswered, which is the whole difference between \"wait,\n\t// this is coming\" and \"nothing here can ever serve you\".\n\tanswerers = new Signal(0);\n\n\tclosed = new Once<Error | null>();\n\n\t/**\n\t * Recompute what `path` resolves to, waking only the requests watching that path.\n\t *\n\t * A no-op for a path nobody requested, so the common case (publishing into a table\n\t * nobody is asking about) costs a map lookup. Call after any write that could change\n\t * the answer for a single path.\n\t */\n\trefresh(path: Path.Valid): void {\n\t\tconst slot = this.requests.peek()?.get(path);\n\t\tif (!slot) return;\n\t\tslot.route.set(this.route(path, slot));\n\t}\n\n\t/**\n\t * `entry` refused `path` with `err`. A request still serving another source skips the\n\t * refuser; one with nothing serving ends with `err`.\n\t */\n\trefuse(path: Path.Valid, entry: RouteEntry, err: Error): void {\n\t\tconst slot = this.requests.peek()?.get(path);\n\t\tif (!slot) return;\n\t\t// Only the route the request is waiting on speaks for it; a superseded one's answer is moot.\n\t\tif (this.bestEntry(path, (candidate) => slot.refused.has(candidate)) !== entry) return;\n\n\t\tconst serving = slot.route.peek();\n\t\tif (serving && serving.closed.peek() === undefined) {\n\t\t\tslot.refused.add(entry);\n\t\t\tslot.route.set(this.route(path, slot));\n\t\t\treturn;\n\t\t}\n\n\t\tthis.requests.mutate((map) => {\n\t\t\tif (map?.get(path) === slot) map.delete(path);\n\t\t});\n\t\tslot.answer?.close();\n\t\tslot.answer = undefined;\n\t\tslot.route.set(undefined);\n\t\tthis.releaseMaterialized(path);\n\t\tfor (const closed of slot.handles) closed.set(err);\n\t\tslot.handles.clear();\n\t}\n\n\t/**\n\t * Recompute every open request covered by `prefix`, after a route was inserted or\n\t * removed there: a route covers many paths, so a single-path refresh is not enough.\n\t * Every materialized broadcast belongs to an open request, so rerouting them also\n\t * releases a retracted route's session subscription even when nothing reads it again.\n\t */\n\trefreshPrefix(prefix: Path.Valid): void {\n\t\tfor (const [path, slot] of this.requests.peek() ?? []) {\n\t\t\tif (Path.hasPrefix(prefix, path)) slot.route.set(this.route(path, slot));\n\t\t}\n\t}\n\n\t/** Rebuild the publisher-facing originated table after an advertisement write. */\n\trebuildOriginated(): void {\n\t\tif (!this.local.peek() && !this.advertisedLocal.peek() && !this.routes.peek()) {\n\t\t\tthis.originated.set(undefined);\n\t\t\treturn;\n\t\t}\n\t\t// A local broadcast and an originated dynamic at one path compete on cost, as they do for requests.\n\t\tthis.originated.set(this.candidates(received));\n\t}\n\n\t/**\n\t * Release the materialized broadcast for `path`, once its last request is gone: the\n\t * cache exists to share one session subscription between requests, not to outlive\n\t * them.\n\t */\n\treleaseMaterialized(path: Path.Valid): void {\n\t\tconst cached = this.materialized.get(path);\n\t\tif (!cached) return;\n\t\tthis.materialized.delete(path);\n\t\tcached.front.close();\n\t}\n\n\t/** The preferred entry on the most specific route covering `path`, ignoring skipped entries, if any. */\n\tbestEntry(path: Path.Valid, skip?: (entry: RouteEntry) => boolean): RouteEntry | undefined {\n\t\tlet bestPrefix: Path.Valid | undefined;\n\t\tlet best: RouteEntry | undefined;\n\t\tfor (const [prefix, entries] of this.routes.peek() ?? []) {\n\t\t\tif (!Path.hasPrefix(prefix, path)) continue;\n\t\t\tconst entry = preferredEntry(\n\t\t\t\tentries,\n\t\t\t\t(candidate) => !candidate.scope.matches(path) || (skip?.(candidate) ?? false),\n\t\t\t);\n\t\t\tif (!entry) continue;\n\t\t\tif (bestPrefix === undefined || prefix.length > bestPrefix.length) {\n\t\t\t\tbestPrefix = prefix;\n\t\t\t\tbest = entry;\n\t\t\t}\n\t\t}\n\t\treturn best;\n\t}\n\n\t/**\n\t * Whether the announced local broadcast at `path` wins over `entry`, the best route a\n\t * session or dynamic handle announced there. Cost decides, as for any two routes: an\n\t * identified route strictly cheaper than the local one wins, and the local broadcast\n\t * wins a tie. A route at a shorter prefix never competes, since the most specific\n\t * prefix wins outright. False when nothing is announced locally at `path`.\n\t */\n\tlocalWins(path: Path.Valid, entry: RouteEntry | undefined): boolean {\n\t\tconst local = this.advertisedLocal.peek()?.get(path);\n\t\tif (!local || !this.local.peek()?.has(path)) return false;\n\t\tif (!entry || !this.routes.peek()?.get(path)?.includes(entry)) return true;\n\t\treturn compareRoutes(local, entry.route.peek()) <= 0;\n\t}\n\n\t/**\n\t * What `path` resolves to: an announced local publish, a broadcast materialized from\n\t * the best covering route, or the blind answer.\n\t *\n\t * Materialization is lazy and cached per path: the first request under a route opens\n\t * the providing session's subscription and repeats share it. A better route is made\n\t * before the old one breaks: the current front keeps serving until the new route\n\t * answers (then swaps) or refuses (then is skipped). A retracted route swaps at once.\n\t */\n\troute(path: Path.Valid, slot: Pick<RequestSlot, \"answer\" | \"refused\">): broadcast.Consumer | undefined {\n\t\tconst entry = this.bestEntry(path, (candidate) => slot.refused.has(candidate));\n\t\tconst local = this.local.peek()?.get(path);\n\t\tif (local && this.localWins(path, entry)) {\n\t\t\t// Nothing reads a remote front the local broadcast replaced, so close its session subscription.\n\t\t\tthis.releaseMaterialized(path);\n\t\t\treturn local;\n\t\t}\n\n\t\tlet cached = this.materialized.get(path);\n\t\tif (cached && cached.front.closed.peek() !== undefined) {\n\t\t\tthis.materialized.delete(path);\n\t\t\tcached = undefined;\n\t\t}\n\t\tif (cached && cached.entry === entry) return cached.front;\n\t\tif (!entry?.server) {\n\t\t\tthis.releaseMaterialized(path);\n\t\t\treturn slot.answer;\n\t\t}\n\n\t\tconst served = entry.server.served.get(path);\n\t\tif (served && served.closed.peek() === undefined) {\n\t\t\tcached?.front.close();\n\t\t\tthis.materialized.set(path, { entry, front: served });\n\t\t\treturn served;\n\t\t}\n\n\t\tentry.server.enqueue(path);\n\t\treturn cached?.front;\n\t}\n}\n\n/**\n * A non-owning handle on an origin: publish into it and read it, without its lifecycle.\n *\n * What a shared connection lends out. {@link Producer} implements it, so code that is\n * handed an origin rather than owning one should accept this type: closing the origin\n * stays the owner's alone, and a borrower cannot express it.\n *\n * @public\n */\nexport interface Table {\n\t/** Settles once the origin closes; see {@link Producer.closed}. */\n\treadonly closed: GetPromise<Error | null>;\n\n\t/** Whether every attached session announces into the table; see {@link Consumer.discovery}. */\n\treadonly discovery: Getter<boolean | undefined>;\n\n\t/** Create an unannounced broadcast at `path`; see {@link Producer.createBroadcast}. */\n\tcreateBroadcast(path: Path.Valid): broadcast.Producer;\n\n\t/** Resolve `path`, optionally waiting for an announcement; see {@link Consumer.request}. */\n\trequest(path: Path.Valid, options?: RequestOptions): Requesting;\n\n\t/** The available announcements under `scope`, as a live map; see {@link Consumer.broadcasts}. */\n\tbroadcasts(scope?: Path.Pattern, options?: announce.Options): Getter<ReadonlyMap<Path.Valid, Route>>;\n\n\t/** The available broadcasts under `scope`, as a live stream; see {@link Consumer.announced}. */\n\tannounced(scope?: Path.Pattern, options?: announce.Options): announce.Consumer;\n\n\t/** Advertise a prefix and serve requests under it; see {@link Producer.dynamic}. */\n\tdynamic(prefix: Path.Valid, route?: Route | { hops?: Route[\"hops\"]; cost?: Route[\"cost\"] | bigint }): Dynamic;\n}\n\n/** Options for resolving a broadcast path. */\nexport interface RequestOptions {\n\t/** Wait for a routed announcement when discovery is supported; otherwise subscribe blindly. */\n\tannounced?: boolean;\n}\n\n/**\n * The write side of an origin: create broadcasts by path and advertise them.\n *\n * Independent of any connection. A connection given this origin (via its `publish` option)\n * announces and serves the table's originated advertisements for as long as the session\n * lasts; the broadcasts themselves live until their producer closes or {@link close} tears\n * the origin down. A reconnecting session re-announces the table on each attach, so\n * advertisements made while offline surface on the next connection.\n *\n * Create, attach {@link dynamic} for tracks served on demand, populate, then\n * {@link broadcast.Producer.announce}: an exact-path subscribe before the tracks exist is\n * refused, and nobody can see or reach a broadcast until it announces.\n *\n * @public\n */\nexport class Producer implements Table {\n\t#state = new OriginState();\n\t#scope = Scope.all;\n\t#requests?: Getter<ReadonlyMap<Path.Valid, RequestSlot> | undefined>;\n\n\t// The reader backing the passthroughs, so holding a Producer never requires the\n\t// consume().x() stutter for everyday reads. One instance, so `discovery` keeps its\n\t// identity across reads.\n\t#reader = makeConsumer(this.#state, this.#scope);\n\n\tconstructor() {\n\t\tconst thisProducer = this;\n\t\tregisterWire(this, {\n\t\t\treceive: (prefix, route) => this.#receive(prefix, route),\n\t\t\tinterests: () => this.#scope.heads(),\n\t\t\taccepts: (prefix) =>\n\t\t\t\t!this.#scope.allowed ||\n\t\t\t\tthis.#scope.allowed.overlaps(Path.Pattern.subtree(Path.join(this.#scope.root, prefix))),\n\t\t\tattach: (discovery) => this.#attach(discovery),\n\t\t\texpect: () => this.#expect(),\n\t\t\tget requests() {\n\t\t\t\tif (thisProducer.#scope === Scope.all) return thisProducer.#state.requests;\n\t\t\t\tthisProducer.#requests ??= new Derived([thisProducer.#state.requests], (requests) =>\n\t\t\t\t\tthisProducer.#scope.projectPaths(requests),\n\t\t\t\t);\n\t\t\t\treturn thisProducer.#requests;\n\t\t\t},\n\t\t\tchanged: () => this.#changed(),\n\t\t\tanswer: (path, front) => this.#answer(this.#scope.path(path), front),\n\t\t\troutes: (path) => wireOf(this.#reader).routes(path),\n\t\t});\n\t}\n\n\t/** Narrow this handle to patterns beneath root, presenting paths relative to that root. */\n\tscope(root: Path.Valid, patterns: Path.Patterns): Producer {\n\t\tconst scope = this.#scope.narrow(root, patterns);\n\t\tconst producer = new Producer();\n\t\tproducer.#state = this.#state;\n\t\tproducer.#scope = scope;\n\t\tproducer.#reader = makeConsumer(this.#state, scope);\n\t\treturn producer;\n\t}\n\n\t/**\n\t * Settles once the origin closes: `null` on a clean close, or the abort {@link Error}.\n\t * Peek it synchronously (`undefined` while open), observe it reactively, or `await` it.\n\t */\n\tget closed(): GetPromise<Error | null> {\n\t\treturn this.#state.closed;\n\t}\n\n\t/**\n\t * Create a broadcast at `path`, returning its producer.\n\t *\n\t * The broadcast exists for nobody until {@link broadcast.Producer.announce}: announce\n\t * streams skip it and requests for its path find nothing, on this origin exactly as at\n\t * a peer. Announce once its tracks exist; {@link broadcast.Producer.unannounce}\n\t * withdraws it from everyone again.\n\t *\n\t * Close the producer to drop it. Creating a path again supersedes the previous\n\t * broadcast: the origin drops its handle on the old one, which closes it unless the\n\t * application still holds a consumer clone. An announced local broadcast competes with\n\t * a remote route at the same path on cost, winning ties.\n\t */\n\tcreateBroadcast(path: Path.Valid): broadcast.Producer {\n\t\tpath = this.#scope.path(path);\n\t\tconst created = this.#state.created;\n\t\tif (!created) throw new Error(\"origin is closed\");\n\n\t\tconst producer = new broadcast.Producer();\n\t\thooks.stampPath(producer, path);\n\t\tconst front = producer.consume();\n\n\t\thooks.attachAnnouncer(producer, {\n\t\t\tannounce: (route) => this.#advertiseExact(path, front, route),\n\t\t\tunannounce: () => this.#retractExact(path, front),\n\t\t});\n\n\t\tconst previous = created.get(path);\n\t\tcreated.set(path, front);\n\t\tif (previous) {\n\t\t\tthis.#retractExact(path, previous);\n\t\t\tprevious.close();\n\t\t}\n\n\t\t// Drop it when the broadcast closes, unless a recreate already replaced it: a\n\t\t// stale broadcast closing must not unpublish the live one.\n\t\tvoid front.closed.then(() => {\n\t\t\tthis.#retractExact(path, front);\n\t\t\tif (this.#state.created?.get(path) === front) this.#state.created.delete(path);\n\t\t});\n\n\t\treturn producer;\n\t}\n\n\t#advertiseExact(path: Path.Valid, front: broadcast.Consumer, route: Route): void {\n\t\tif (!this.#state.local.peek()) throw new Error(\"origin is closed\");\n\t\tif (this.#state.created?.get(path) !== front) throw new Error(\"broadcast is closed\");\n\t\t// Both maps move together, so every reader sees the broadcast and its route at once.\n\t\tthis.#state.local.mutate((broadcasts) => {\n\t\t\tbroadcasts?.set(path, front);\n\t\t});\n\t\tthis.#state.advertisedLocal.mutate((advertised) => {\n\t\t\tadvertised?.set(path, route);\n\t\t});\n\t\tthis.#state.rebuildOriginated();\n\t\tthis.#state.refresh(path);\n\t}\n\n\t#retractExact(path: Path.Valid, front: broadcast.Consumer): void {\n\t\tif (this.#state.local.peek()?.get(path) !== front) return;\n\t\tthis.#state.local.mutate((broadcasts) => {\n\t\t\tbroadcasts?.delete(path);\n\t\t});\n\t\tthis.#state.advertisedLocal.mutate((advertised) => {\n\t\t\tadvertised?.delete(path);\n\t\t});\n\t\tthis.#state.rebuildOriginated();\n\t\tthis.#state.refresh(path);\n\t}\n\n\t/**\n\t * Advertise `prefix` and serve the requests beneath it.\n\t *\n\t * A route is always a prefix: it claims `prefix` and every path beneath it (the\n\t * empty prefix claims every path). A service that only serves some of them\n\t * advertises the covering prefix and rejects the rest as they are requested;\n\t * consumers narrow with a {@link Path.Pattern} locally. The advertisement is\n\t * visible to {@link Consumer.announced} and forwarded by sessions for as long as\n\t * the returned {@link Dynamic} lives. A consumer resolving a path under it that\n\t * no announced local broadcast wins is handed to the handle as a {@link Request}.\n\t */\n\tdynamic(\n\t\tprefix: Path.Valid,\n\t\troute: Route | { hops?: Route[\"hops\"]; cost?: Route[\"cost\"] | bigint } = Route.default,\n\t): Dynamic {\n\t\treturn this.#insertRoute(prefix, Route.normalize(route), true);\n\t}\n\n\t/**\n\t * Land a route a peer announced, served through the returned handle. Same as\n\t * {@link dynamic} but not originated, so a session never announces it back.\n\t *\n\t * @internal\n\t */\n\t#receive(\n\t\tprefix: Path.Valid,\n\t\troute: Route | { hops?: Route[\"hops\"]; cost?: Route[\"cost\"] | bigint } = Route.default,\n\t): Dynamic {\n\t\treturn this.#insertRoute(prefix, Route.normalize(route), false);\n\t}\n\n\t#insertRoute(prefix: Path.Valid, route: Route, originated: boolean): Dynamic {\n\t\tprefix = this.#scope.prefix(prefix);\n\t\tconst server = new ServeState(this.#scope.root);\n\t\tserver.onChange = (path) => this.#state.refresh(path);\n\t\tconst entry: RouteEntry = {\n\t\t\tidentity: {},\n\t\t\tscope: this.#scope,\n\t\t\tclaim: this.#scope.allowed?.intersect(new Path.Patterns([Path.Pattern.subtree(prefix)])),\n\t\t\troute: new Signal(route),\n\t\t\toriginated,\n\t\t\tserver,\n\t\t};\n\t\tserver.onReject = (path, err) => this.#state.refuse(path, entry, err);\n\n\t\tlet closed = false;\n\t\tthis.#state.routes.mutate((routes) => {\n\t\t\tif (!routes) {\n\t\t\t\tclosed = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst entries = routes.get(prefix);\n\t\t\tif (entries) entries.unshift(entry);\n\t\t\telse routes.set(prefix, [entry]);\n\t\t});\n\t\tif (closed) {\n\t\t\tserver.close();\n\t\t\treturn makeDynamic(prefix, entry, this.#state, () => {});\n\t\t}\n\t\tthis.#state.rebuildOriginated();\n\t\tthis.#state.refreshPrefix(prefix);\n\n\t\tconst retract = () => {\n\t\t\tthis.#state.routes.mutate((routes) => {\n\t\t\t\tconst entries = routes?.get(prefix);\n\t\t\t\tif (!entries) return;\n\t\t\t\tconst index = entries.indexOf(entry);\n\t\t\t\tif (index < 0) return;\n\t\t\t\tentries.splice(index, 1);\n\t\t\t\tif (entries.length === 0) routes?.delete(prefix);\n\t\t\t});\n\t\t\t// A retracted entry can never be picked again, so the refusals pinned to it are dead weight.\n\t\t\tfor (const slot of this.#state.requests.peek()?.values() ?? []) slot.refused.delete(entry);\n\t\t\tserver.close();\n\t\t\tthis.#state.rebuildOriginated();\n\t\t\tthis.#state.refreshPrefix(prefix);\n\t\t};\n\n\t\treturn makeDynamic(prefix, entry, this.#state, retract);\n\t}\n\n\t/**\n\t * Register an attached session, counting it toward the `discovery` state. Returns the\n\t * detach; call it exactly once when the session dies.\n\t *\n\t * @internal\n\t */\n\t#attach(discovery: boolean): Dispose {\n\t\tthis.#sessions(1, discovery);\n\t\tconst release = this.#expect();\n\t\tlet detached = false;\n\t\treturn () => {\n\t\t\tif (detached) return;\n\t\t\tdetached = true;\n\t\t\tthis.#sessions(-1, discovery);\n\t\t\trelease();\n\t\t};\n\t}\n\n\t#sessions(delta: number, discovery: boolean): void {\n\t\tthis.#state.sessions.update(({ total, discovery: d }) => ({\n\t\t\ttotal: total + delta,\n\t\t\tdiscovery: d + (discovery ? delta : 0),\n\t\t}));\n\t}\n\n\t/**\n\t * Declare that something will answer requests on this origin, even with no session\n\t * attached right now.\n\t *\n\t * A reconnecting connection holds one for its whole life, so a request made during a\n\t * reconnect (or before the first session establishes) stays pending instead of reading as\n\t * unroutable. Without it, {@link Request.unroutable} would fire on every page load, in the\n\t * window between wiring the origin up and the handshake completing. Call the returned\n\t * dispose when the connection is done for good.\n\t *\n\t * @internal\n\t */\n\t#expect(): Dispose {\n\t\tthis.#state.answerers.update((count) => count + 1);\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\t// Clamped because closing the origin zeroes the count, and the sessions attached at\n\t\t\t// the time still release afterwards.\n\t\t\tthis.#state.answerers.update((count) => Math.max(0, count - 1));\n\t\t};\n\t}\n\n\t/**\n\t * Resolves once anything a serving session scans changes: the open requests, or either\n\t * side of the routing table.\n\t *\n\t * @internal\n\t */\n\t#changed(): Promise<unknown> {\n\t\treturn Signal.race(this.#state.requests, this.#state.local, this.#state.routes, this.#state.advertisedLocal);\n\t}\n\n\t/**\n\t * Provide `front` as the answer for the open request on `path`, taking ownership of it.\n\t *\n\t * Returns undefined (releasing the front) when the request is gone or already answered;\n\t * first session in wins, and a loser must stay eligible to answer later. The returned\n\t * withdraw releases the front and, if it was the standing answer, vacates the slot and\n\t * wakes the other serving loops so a standby session answers immediately; call it when\n\t * the session dies.\n\t *\n\t * @internal\n\t */\n\t#answer(path: Path.Valid, front: broadcast.Consumer): Dispose | undefined {\n\t\tconst slot = this.#state.requests.peek()?.get(path);\n\t\tif (!slot || slot.answer !== undefined) {\n\t\t\tfront.close();\n\t\t\treturn undefined;\n\t\t}\n\t\tslot.answer = front;\n\t\tthis.#state.refresh(path);\n\n\t\treturn () => {\n\t\t\tif (slot.answer === front) {\n\t\t\t\tslot.answer = undefined;\n\t\t\t\tthis.#state.refresh(path);\n\t\t\t\t// The route signal only reaches this path's requesters; poke the map so every\n\t\t\t\t// serving loop re-scans and one of them re-answers.\n\t\t\t\tthis.#state.requests.mutate(() => {});\n\t\t\t}\n\t\t\tfront.close();\n\t\t};\n\t}\n\n\t/** A read handle for this origin, the side a connection's `publish` option borrows. */\n\tconsume(): Consumer {\n\t\treturn makeConsumer(this.#state, this.#scope);\n\t}\n\n\t/** Whether every attached session announces into the table; see {@link Consumer.discovery}. */\n\tget discovery(): Getter<boolean | undefined> {\n\t\treturn this.#reader.discovery;\n\t}\n\n\t/** Resolve `path`, optionally waiting for an announcement; see {@link Consumer.request}. */\n\trequest(path: Path.Valid, options?: RequestOptions): Requesting {\n\t\treturn this.#reader.request(path, options);\n\t}\n\n\t/** The available announcements under `scope`, as a live map; see {@link Consumer.broadcasts}. */\n\tbroadcasts(scope?: Path.Pattern, options?: announce.Options): Getter<ReadonlyMap<Path.Valid, Route>> {\n\t\treturn this.#reader.broadcasts(scope, options);\n\t}\n\n\t/** The available broadcasts under `scope`, as a live stream; see {@link Consumer.announced}. */\n\tannounced(scope?: Path.Pattern, options?: announce.Options): announce.Consumer {\n\t\treturn this.#reader.announced(scope, options);\n\t}\n\n\t/** Close the origin, every broadcast it still routes, and its announcement streams. Idempotent. */\n\tclose(abort?: Error) {\n\t\tif (this.#state.closed.peek() !== undefined) return;\n\t\tthis.#state.closed.set(abort ?? null);\n\t\tfor (const front of this.#state.created?.values() ?? []) {\n\t\t\tfront.close();\n\t\t}\n\t\tthis.#state.created = undefined;\n\t\tthis.#state.local.update(() => undefined);\n\t\tthis.#state.advertisedLocal.update(() => undefined);\n\t\tthis.#state.routes.update((routes) => {\n\t\t\tfor (const entries of routes?.values() ?? []) {\n\t\t\t\tfor (const entry of entries) entry.server?.close(abort);\n\t\t\t}\n\t\t\treturn undefined;\n\t\t});\n\t\tthis.#state.originated.update(() => undefined);\n\t\t// Materialized broadcasts are handles we opened; release them.\n\t\tfor (const cached of this.#state.materialized.values()) {\n\t\t\tcached.front.close();\n\t\t}\n\t\tthis.#state.materialized.clear();\n\t\t// Nothing will answer a request on a closed origin, whatever is still attached, so\n\t\t// existing requests report unroutable rather than waiting on a corpse.\n\t\tthis.#state.answerers.set(0);\n\t\tthis.#state.requests.update((requests) => {\n\t\t\tfor (const slot of requests?.values() ?? []) {\n\t\t\t\tslot.answer?.close();\n\t\t\t\tslot.answer = undefined;\n\t\t\t\tslot.route.set(undefined);\n\t\t\t}\n\t\t\treturn undefined;\n\t\t});\n\t}\n}\n\n// Constructs a Consumer from within this module without exposing a public constructor\n// that would leak the unexported OriginState. Assigned in the class's static block.\nlet makeConsumer: (state: OriginState, scope: Scope) => Consumer;\n\n// Same for Requesting: a public constructor would let a caller forge a handle that no origin\n// ever registered, whose lifecycle guarantees are then false. `@internal` alone would not\n// stop it, since the declaration emit keeps the constructor.\nlet makeRequesting: (\n\tpath: Path.Valid,\n\tactive: Getter<broadcast.Consumer | undefined>,\n\tunroutable: Getter<boolean>,\n\tclosed: Once<Error | null>,\n\tdispose: Dispose,\n) => Requesting;\n\nlet makeDynamic: (prefix: Path.Valid, entry: RouteEntry, state: OriginState, retract: Dispose) => Dynamic;\n\nlet makeRequest: (path: Path.Valid, server: ServeState) => Request;\nlet finishRequest: (request: Request, err: Error) => void;\n\n/**\n * An open request for a path nothing announced; see {@link Consumer.request}.\n *\n * @public\n */\nexport class Requesting {\n\t/** The requested path. */\n\treadonly path: Path.Valid;\n\n\t/**\n\t * The resolved broadcast, or undefined while nothing provides the path.\n\t *\n\t * The table's route when it has one: a local publish (no round trip) or an announced\n\t * broadcast, swapping when a republish takes the path. Otherwise a session's blind\n\t * answer, which is assumed present rather than known live: a missing broadcast\n\t * surfaces as a reset on the first track subscription, not here. Drops back to\n\t * undefined when the providing route dies and resolves again when another appears.\n\t *\n\t * Yours for as long as the request is open: it is a handle of this request's own, so\n\t * closing it ends your view of the path rather than the route everyone else reads.\n\t * {@link close} releases whatever is current.\n\t */\n\treadonly active: Getter<broadcast.Consumer | undefined>;\n\n\t/**\n\t * Whether nothing can serve this path, as opposed to not having served it yet.\n\t *\n\t * True when the origin routes nothing here and nothing is prepared to answer: no session\n\t * attached and no connection reconnecting toward one. False whenever {@link active} is\n\t * set, and false while a connection is still coming up, so the ordinary page-load window\n\t * before the first handshake reads as pending rather than as a missing broadcast. Waiting\n\t * on this is futile by definition; wait for an announcement instead, via the origin's\n\t * `announced`. True once the request is refused.\n\t */\n\treadonly unroutable: Getter<boolean>;\n\n\t/**\n\t * Settles with the error a route's handler refused the path with, or `null` once you\n\t * {@link close} the request. A refusal is final: no other route is asked, and a fresh\n\t * request is needed to try again.\n\t */\n\treadonly closed: GetPromise<Error | null>;\n\n\t#dispose: Dispose;\n\t#disposed = false;\n\n\tprivate constructor(\n\t\tpath: Path.Valid,\n\t\tactive: Getter<broadcast.Consumer | undefined>,\n\t\tunroutable: Getter<boolean>,\n\t\tclosed: GetPromise<Error | null>,\n\t\tdispose: Dispose,\n\t) {\n\t\tthis.path = path;\n\t\tthis.active = active;\n\t\tthis.unroutable = unroutable;\n\t\tthis.closed = closed;\n\t\tthis.#dispose = dispose;\n\t}\n\n\tstatic {\n\t\tmakeRequesting = (path, active, unroutable, closed, dispose) =>\n\t\t\tnew Requesting(path, active, unroutable, closed, dispose);\n\t}\n\n\t/** Withdraw the request. The path stays routed for any other open request. Idempotent. */\n\tclose(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tthis.#dispose();\n\t}\n}\n\n/**\n * The read side of an origin: resolve broadcasts by path and watch what is available.\n *\n * Obtain one from {@link Producer.consume}. Pass it to a connection's `publish` option to\n * serve the origin's local broadcasts to that peer; read it directly to consume anything\n * the origin routes, locally published or discovered by a session.\n *\n * @public\n */\nexport class Consumer {\n\t#state: OriginState;\n\t#scope: Scope;\n\n\tprivate constructor(state: OriginState, scope: Scope) {\n\t\tthis.#state = state;\n\t\tthis.#scope = scope;\n\t\t// True only when every attached session announces. One session that cannot means the\n\t\t// table is an incomplete picture, so a consumer gated on it has to keep its blind\n\t\t// fallback: the paths only that session carries never reach the table at all.\n\t\tthis.#discovery = new Derived([state.sessions], ({ total, discovery }) =>\n\t\t\ttotal === 0 ? undefined : discovery === total,\n\t\t);\n\t\tregisterWire(this, {\n\t\t\troutes: (path) => this.#routes(scope.path(path)),\n\t\t\tbroadcasts:\n\t\t\t\tscope === Scope.all ? state.local : new Derived([state.local], (local) => scope.projectPaths(local)),\n\t\t\tadvertised:\n\t\t\t\tscope === Scope.all\n\t\t\t\t\t? state.originated\n\t\t\t\t\t: new Derived([state.originated], (routes) => scope.projectRoutes(routes)),\n\t\t\tlocal: (path) => this.#local(scope.path(path)),\n\t\t\tdemand: (path) => this.#demand(scope.path(path)),\n\t\t});\n\t}\n\n\tstatic {\n\t\tmakeConsumer = (state, scope) => new Consumer(state, scope);\n\t}\n\n\t/** Settles once the origin closes; see {@link Producer.closed}. */\n\tget closed(): GetPromise<Error | null> {\n\t\treturn this.#state.closed;\n\t}\n\n\t/**\n\t * Whether the announcement table sees everything the attached sessions can serve.\n\t *\n\t * Undefined while no session is attached (nothing is known yet), true when every attached\n\t * session announces into the table, and false as soon as one does not, where\n\t * {@link announced} cannot be complete and consumers should {@link request} paths instead\n\t * of waiting. One blind session among several is still false: the paths only it carries\n\t * never reach the table, so a consumer that trusted the gate would never see them.\n\t */\n\tget discovery(): Getter<boolean | undefined> {\n\t\treturn this.#discovery;\n\t}\n\n\t// Derived per access rather than cached: a lightweight mapped view over the session\n\t// counts, avoiding a Computed's lifecycle.\n\treadonly #discovery: Getter<boolean | undefined>;\n\n\t/**\n\t * Whether the table routes `path`, by an announced local publish or an announced\n\t * route covering it.\n\t *\n\t * Availability, not a handle: {@link request} is the only way to consume by path. A\n\t * request on a routed path resolves to that route and never to a blind answer, which is\n\t * why a serving session leaves it alone.\n\t *\n\t * @internal\n\t */\n\t#routes(path: Path.Valid): boolean {\n\t\tif (this.#state.local.peek()?.has(path)) return true;\n\t\treturn this.#state.bestEntry(path) !== undefined;\n\t}\n\n\t/**\n\t * Resolve `path`, optionally waiting for an announcement.\n\t *\n\t * The one way to consume by path. {@link Requesting.active} follows whatever the table\n\t * routes (an announced local publish, or any feeding session's announcement, swapping\n\t * on a republish or a retraction); when nothing does, the request stands and whichever\n\t * attached session answers first provides a blind subscription instead, re-answered\n\t * across reconnects.\n\t * With `announced: true`, an unrouted request waits while discovery is supported and\n\t * falls back to that blind behavior only when discovery is unavailable. Close the request\n\t * when done. On a closed origin it never resolves.\n\t *\n\t * With several sessions on one origin the first to answer wins, and it may be one that\n\t * does not carry the path. Nothing corrects that: a missing broadcast surfaces as a reset\n\t * on the first track and deliberately leaves the handle open, since the wire cannot tell\n\t * \"not here\" from \"not yet\" and a blind handle is expected to survive until a publisher\n\t * arrives. It matters only on an origin mixing sessions that announce with sessions that\n\t * cannot, where a path only the silent session carries may sit behind another session's\n\t * answer. Prefer {@link unroutable} and announcements over blind requests when the origin\n\t * feeds from more than one connection.\n\t */\n\trequest(path: Path.Valid, options: RequestOptions = {}): Requesting {\n\t\tconst relative = path;\n\t\tpath = this.#scope.path(path);\n\t\tconst requests = this.#state.requests.peek();\n\t\tif (!requests) {\n\t\t\t// Closed origin: a request that can never resolve, and says so.\n\t\t\tconst closed = new Once<Error | null>();\n\t\t\treturn makeRequesting(\n\t\t\t\trelative,\n\t\t\t\tnew Signal<broadcast.Consumer | undefined>(undefined),\n\t\t\t\tgetter(true),\n\t\t\t\tclosed,\n\t\t\t\t() => closed.set(null),\n\t\t\t);\n\t\t}\n\n\t\tlet slot = requests.get(path);\n\t\tif (!slot) {\n\t\t\t// Seeded through the constructor, so a path the table already routes resolves on the\n\t\t\t// first read. It must not go through a silent set: that still captures the pre-seed\n\t\t\t// value as the baseline the next change is compared against, and never flushes to\n\t\t\t// clear it, so a seeded route retracting to undefined would look like no change and\n\t\t\t// notify nobody.\n\t\t\tconst refused = new Set<RouteEntry>();\n\t\t\tconst created: RequestSlot = {\n\t\t\t\tblind: 0,\n\t\t\t\thandles: new Set(),\n\t\t\t\trefused,\n\t\t\t\troute: new Signal(this.#state.route(path, { refused })),\n\t\t\t};\n\t\t\tslot = created;\n\t\t\tthis.#state.requests.mutate((map) => {\n\t\t\t\tmap?.set(path, created);\n\t\t\t});\n\t\t}\n\t\tconst closed = new Once<Error | null>();\n\t\tslot.handles.add(closed);\n\t\tlet blind = !options.announced || this.#discovery.peek() === false;\n\t\tif (blind) slot.blind += 1;\n\t\tthis.#state.requests.mutate(() => {});\n\n\t\t// An announcement-gated request falls back to a blind subscription only while at\n\t\t// least one attached session cannot announce. It returns to the gate if discovery\n\t\t// becomes complete again, and remains gated with no session attached.\n\t\tconst unsubscribeDiscovery = options.announced\n\t\t\t? this.#discovery.subscribe((discovery) => {\n\t\t\t\t\tconst next = discovery === false;\n\t\t\t\t\tif (next === blind) return;\n\t\t\t\t\tblind = next;\n\t\t\t\t\tslot.blind += next ? 1 : -1;\n\t\t\t\t\tthis.#state.requests.mutate(() => {});\n\t\t\t\t})\n\t\t\t: () => {};\n\n\t\t// Hand out a handle of the request's own rather than the table's. Closing a consumer\n\t\t// closes the broadcast once it was the last one, and the table often holds the only\n\t\t// other handle, so lending its front out means an ordinary close() by one requester\n\t\t// can unpublish the path for everybody else.\n\t\tconst taken = slot;\n\n\t\t// Memoized on the route's identity: the same front resolving again returns the handle\n\t\t// we already made, and only a real swap clones a new one (cloning before closing the\n\t\t// old, so a broadcast that both routes share never briefly loses its last handle).\n\t\tlet released = false;\n\t\tlet source: broadcast.Consumer | undefined;\n\t\tlet handle: broadcast.Consumer | undefined;\n\t\tconst own = (front: broadcast.Consumer | undefined): broadcast.Consumer | undefined => {\n\t\t\tif (released) return undefined;\n\t\t\tif (front !== source) {\n\t\t\t\tconst previous = handle;\n\t\t\t\tsource = front;\n\t\t\t\thandle = front?.clone();\n\t\t\t\tif (handle) hooks.stampPath(handle, relative);\n\t\t\t\tprevious?.close();\n\t\t\t}\n\t\t\treturn handle;\n\t\t};\n\n\t\tconst route = taken.route;\n\t\tconst active = new Derived([route], own);\n\n\t\t// Swapping on the read is what keeps a routed path resolving synchronously, but a\n\t\t// holder that only ever peeked would then pin a route that has already been retracted\n\t\t// until it happened to read again. Following the route as well retires it promptly,\n\t\t// and the memo makes the two paths agree: whichever runs first does the swap.\n\t\tconst unsubscribe = route.subscribe(own);\n\n\t\t// Only meaningful while nothing is routed, so it reads the route rather than `active`:\n\t\t// the two cannot disagree, since a routed path always has an answerer-independent\n\t\t// answer.\n\t\tconst unroutable = new Derived(\n\t\t\t[route, this.#state.answerers, closed],\n\t\t\t(front, answerers, ended) => ended !== undefined || (!front && answerers === 0),\n\t\t);\n\n\t\treturn makeRequesting(relative, active, unroutable, closed, () => {\n\t\t\t// Releases this request's handle; the route itself belongs to the table.\n\t\t\treleased = true;\n\t\t\tunsubscribeDiscovery();\n\t\t\tunsubscribe();\n\t\t\thandle?.close();\n\t\t\thandle = undefined;\n\t\t\tsource = undefined;\n\n\t\t\ttaken.handles.delete(closed);\n\t\t\tif (closed.peek() === undefined) closed.set(null);\n\t\t\tif (blind) taken.blind -= 1;\n\t\t\tthis.#state.requests.mutate(() => {});\n\t\t\tif (taken.handles.size > 0) return;\n\n\t\t\t// Defer the teardown a microtask: an effect whose rerun was triggered by the\n\t\t\t// answer resolving closes its old request and takes a new one in the same tick,\n\t\t\t// and tearing down in between would drop the answer it is about to read.\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tif (taken.handles.size > 0) return;\n\t\t\t\t// A refused slot already tore itself down, and the path may hold a newer one.\n\t\t\t\tif (this.#state.requests.peek()?.get(path) !== taken) return;\n\t\t\t\tthis.#state.requests.mutate((map) => {\n\t\t\t\t\tmap?.delete(path);\n\t\t\t\t});\n\t\t\t\ttaken.answer?.close();\n\t\t\t\ttaken.answer = undefined;\n\t\t\t\ttaken.route.set(undefined);\n\t\t\t\tthis.#state.releaseMaterialized(path);\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * The announced routes matching `scope`, as a live map from covered prefix to route.\n\t * Local broadcasts appear once announced; received and dynamic routes retain their\n\t * advertised prefixes. Reads are synchronous, and the getter needs no teardown.\n\t * Hidden routes are left out unless `options.hidden` opts in (see {@link announce.Options}).\n\t * Unscoped readers share one snapshot; each distinct scope filters the table on changes.\n\t */\n\tbroadcasts(scope?: Path.Pattern, options?: announce.Options): Getter<ReadonlyMap<Path.Valid, Route>> {\n\t\tconst hidden = options?.hidden ?? false;\n\t\tif (!scope && this.#scope === Scope.all) return hidden ? this.#state.available : this.#state.visible;\n\t\tconst patterns = this.#scope.patterns(scope);\n\t\treturn new Derived([this.#state.available], () => {\n\t\t\tconst routes = new Map<Path.Valid, Route>();\n\t\t\tfor (const [path, entry] of this.#listed(patterns, hidden)) routes.set(path, entry.route);\n\t\t\treturn routes;\n\t\t});\n\t}\n\n\t/**\n\t * The announced routes matching `scope`, as a live stream: every currently advertised\n\t * route arrives first as active, then additions and retractions as they happen.\n\t * Any pattern is accepted. A local broadcast appears once it announces, exactly as a\n\t * peer sees it. A dynamic or received route announces the prefix it covers when its\n\t * subtree overlaps the scope. The stream ends when the origin closes or the consumer is\n\t * closed. Hidden routes are left out unless `options.hidden` opts in (see {@link announce.Options}).\n\t */\n\tannounced(scope: Path.Pattern = Path.Pattern.all(), options?: announce.Options): announce.Consumer {\n\t\tconst producer = new announce.Producer();\n\t\tvoid this.#runAnnounced(producer, this.#scope.patterns(scope), options?.hidden ?? false);\n\t\treturn producer.consume();\n\t}\n\n\t/** One snapshot shared by map readers and announcement-stream diffing. */\n\t#listed(patterns: Path.Patterns, hidden: boolean): Map<Path.Valid, Presented> {\n\t\tconst next = new Map<Path.Valid, Presented>();\n\t\tconst covering = new CoveringRoot(this.#scope.root);\n\t\tconst scopes = [...patterns]\n\t\t\t.sort((a, b) => Path.compareSpecificity(b.specificity(), a.specificity()))\n\t\t\t.map((pattern) => ({ pattern, head: scopeHead(pattern) }));\n\t\tfor (const [path, candidates] of this.#state.snapshot().candidates) {\n\t\t\t// The first candidate this reader can see wins, since the preferred one overall may not be.\n\t\t\tlet entry: Candidate | undefined;\n\t\t\tlet scope: (typeof scopes)[number] | undefined;\n\t\t\tfor (const candidate of candidates) {\n\t\t\t\tscope = scopes.find(\n\t\t\t\t\t({ pattern, head }) =>\n\t\t\t\t\t\t(candidate.exact ? pattern.matches(path) : advertOverlaps(candidate, path, pattern)) &&\n\t\t\t\t\t\t(hidden || !hiddenBelow(head, path)),\n\t\t\t\t);\n\t\t\t\tif (scope) {\n\t\t\t\t\tentry = candidate;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!entry || !scope) continue;\n\t\t\tconst relative = covering.relative(path);\n\t\t\tif (relative === undefined) continue;\n\t\t\tnext.set(relative, {\n\t\t\t\tidentity: entry.identity,\n\t\t\t\troute: entry.route,\n\t\t\t\tcaptures: scopeCaptures(scope.pattern, path),\n\t\t\t});\n\t\t}\n\t\treturn next;\n\t}\n\n\tasync #runAnnounced(producer: announce.Producer, patterns: Path.Patterns, hidden: boolean): Promise<void> {\n\t\t// Keyed by the presented path (from the origin, not the scope), valued by identity\n\t\t// plus route. Diffing identity rather than mere presence means a republish emits a\n\t\t// retraction then a fresh announcement; a re-price of the same identity emits an\n\t\t// update.\n\t\tlet active = new Map<Path.Valid, Presented>();\n\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst local = this.#state.local.peek();\n\t\t\t\tconst advertisedLocal = this.#state.advertisedLocal.peek();\n\t\t\t\tconst routes = this.#state.routes.peek();\n\t\t\t\tif (local === undefined && advertisedLocal === undefined && routes === undefined) break;\n\n\t\t\t\tconst next = this.#listed(patterns, hidden);\n\n\t\t\t\tfor (const [path, snap] of active) {\n\t\t\t\t\tconst cur = next.get(path);\n\t\t\t\t\tif (!cur || cur.identity !== snap.identity)\n\t\t\t\t\t\tproducer.append({\n\t\t\t\t\t\t\tprefix: path,\n\t\t\t\t\t\t\tcaptures: snap.captures,\n\t\t\t\t\t\t\tkind: \"retracted\",\n\t\t\t\t\t\t\troute: snap.route,\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tfor (const [path, snap] of next) {\n\t\t\t\t\tconst prev = active.get(path);\n\t\t\t\t\tif (!prev || prev.identity !== snap.identity) {\n\t\t\t\t\t\tproducer.append({\n\t\t\t\t\t\t\tprefix: path,\n\t\t\t\t\t\t\tcaptures: snap.captures,\n\t\t\t\t\t\t\tkind: \"announced\",\n\t\t\t\t\t\t\troute: snap.route,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (!routesEqual(prev.route, snap.route)) {\n\t\t\t\t\t\tproducer.append({ prefix: path, captures: snap.captures, kind: \"updated\", route: snap.route });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tactive = next;\n\n\t\t\t\tawait Signal.race(this.#state.local, this.#state.advertisedLocal, this.#state.routes, producer.closed);\n\t\t\t\tif (producer.closed.peek() !== undefined) return;\n\t\t\t}\n\t\t} catch {\n\t\t\t// The reader closed between the check and an append; nothing left to do.\n\t\t}\n\t\tproducer.close();\n\t}\n\n\t/**\n\t * The local table, borrowed by the wire publishers to answer subscribes.\n\t *\n\t * Deliberately excludes received routes: a session never re-announces what a peer\n\t * told it, so an origin wired to both directions of a connection cannot echo.\n\t * Borrowed, not owned: do not close the fronts. Undefined once the origin closes.\n\t *\n\t * @internal\n\t */\n\t/**\n\t * Originated advertisements a session should forward: exact-path announces plus\n\t * originated dynamics. Undefined once the origin closes.\n\t *\n\t * @internal\n\t */\n\t/**\n\t * The announced local broadcast at `path`, when it beats the originated routes there.\n\t * Resolves through what rebuildOriginated advertised: a peer never sees received routes.\n\t */\n\t#local(path: Path.Valid): broadcast.Consumer | undefined {\n\t\tconst local = this.#state.local.peek()?.get(path);\n\t\tif (local && this.#state.localWins(path, this.#state.bestEntry(path, received))) return local;\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Resolve `path` for serving: an announced local broadcast, or wait for an originated\n\t * dynamic to accept it. Undefined when nothing here can serve the path.\n\t *\n\t * @internal\n\t */\n\tasync #demand(path: Path.Valid): Promise<broadcast.Consumer | undefined> {\n\t\tconst local = this.#local(path);\n\t\tif (local) return local;\n\t\tconst entry = this.#state.bestEntry(path, received);\n\t\tif (!entry?.server) return undefined;\n\n\t\tconst server = entry.server;\n\t\tconst live = server.served.get(path);\n\t\tif (live && live.closed.peek() === undefined) return live;\n\n\t\tserver.enqueue(path);\n\t\tserver.demanding.set(path, (server.demanding.get(path) ?? 0) + 1);\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst served = server.served.get(path);\n\t\t\t\tif (served && served.closed.peek() === undefined) return served;\n\t\t\t\tconst rejected = server.rejected.get(path);\n\t\t\t\tif (rejected) {\n\t\t\t\t\tserver.rejected.delete(path);\n\t\t\t\t\tthrow rejected;\n\t\t\t\t}\n\t\t\t\tconst closed = server.closed.peek();\n\t\t\t\tif (closed !== undefined) {\n\t\t\t\t\tif (closed) throw closed;\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tif (!server.pending.has(path)) return undefined;\n\t\t\t\tawait Signal.race(server.settled, server.closed);\n\t\t\t}\n\t\t} finally {\n\t\t\tconst n = (server.demanding.get(path) ?? 1) - 1;\n\t\t\tif (n <= 0) server.demanding.delete(path);\n\t\t\telse server.demanding.set(path, n);\n\t\t}\n\t}\n}\n\n/**\n * A served route from {@link Producer.dynamic}: advertises a prefix and answers the\n * requests beneath it.\n *\n * Drop it (or {@link close}) to retract the route and reject anything still waiting\n * with {@link StreamCode.NoCapacity}. {@link update} re-prices it in place.\n *\n * @public\n */\nexport class Dynamic {\n\t/** The prefix this handle advertises. */\n\treadonly prefix: Path.Valid;\n\n\t#entry: RouteEntry;\n\t#state: OriginState;\n\t#retract: Dispose;\n\t#closed = false;\n\n\tprivate constructor(prefix: Path.Valid, entry: RouteEntry, state: OriginState, retract: Dispose) {\n\t\tthis.prefix = Path.stripPrefix(entry.scope.root, prefix) ?? Path.empty();\n\t\tthis.#entry = entry;\n\t\tthis.#state = state;\n\t\tthis.#retract = retract;\n\t}\n\n\tstatic {\n\t\tmakeDynamic = (prefix, entry, state, retract) => new Dynamic(prefix, entry, state, retract);\n\t}\n\n\t/** Re-price the route in place. The prefix is fixed at announce time. */\n\tupdate(route: Route | { hops?: Route[\"hops\"]; cost?: Route[\"cost\"] | bigint }): void {\n\t\tif (this.#closed) throw new Error(\"dynamic is closed\");\n\t\tthis.#entry.route.set(Route.normalize(route));\n\t\tthis.#state.rebuildOriginated();\n\t\tthis.#state.refreshPrefix(Path.join(this.#entry.scope.root, this.prefix));\n\t\tthis.#state.routes.mutate(() => {});\n\t}\n\n\t/** Retract the route and reject anything still waiting. Idempotent. */\n\tclose(): void {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tthis.#retract();\n\t}\n\n\t/** Requests under this prefix, as they arrive, each to {@link Request.accept} or reject. */\n\tasync *requested(): AsyncIterableIterator<Request> {\n\t\tconst server = this.#entry.server;\n\t\tif (!server) return;\n\t\tlet current: Request | undefined;\n\t\tconst drop = () => {\n\t\t\tcurrent?.reject(noCapacity());\n\t\t\tcurrent = undefined;\n\t\t};\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst next = server.queue.peek()[0];\n\t\t\t\tif (next) {\n\t\t\t\t\tdrop();\n\t\t\t\t\tserver.queue.mutate((queue) => {\n\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t});\n\t\t\t\t\tcurrent = next;\n\t\t\t\t\tyield next;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (server.closed.peek() !== undefined) return;\n\t\t\t\tawait Signal.race(server.queue, server.closed);\n\t\t\t}\n\t\t} finally {\n\t\t\tdrop();\n\t\t}\n\t}\n}\n\n/**\n * A pending request for a broadcast to be served on demand.\n *\n * Yielded by {@link Dynamic.requested}. {@link accept} resolves it with a live\n * broadcast; {@link reject} resolves it with an error. Advancing the iterator or\n * closing it without either rejects the request.\n *\n * @public\n */\nexport class Request {\n\t/** The path that was requested. */\n\treadonly path: Path.Valid;\n\n\t#server: ServeState;\n\t#done = false;\n\n\tprivate constructor(path: Path.Valid, server: ServeState) {\n\t\tthis.path = path;\n\t\tthis.#server = server;\n\t}\n\n\tstatic {\n\t\tmakeRequest = (path, server) => new Request(path, server);\n\t\tfinishRequest = (request, err) => {\n\t\t\trequest.#done = true;\n\t\t\tvoid err;\n\t\t};\n\t}\n\n\t/**\n\t * Accept the request, resolving every awaiting requester with `broadcast`.\n\t *\n\t * The caller keeps producing into `broadcast`; repeat requests for the path share\n\t * it for as long as it stays live.\n\t */\n\taccept(source: broadcast.Producer | broadcast.Consumer): void {\n\t\tif (this.#done) return;\n\t\tthis.#done = true;\n\t\tconst front = source instanceof broadcast.Producer ? source.consume() : source;\n\t\tthis.#server.accept(this, front);\n\t}\n\n\t/** Reject the request, resolving every awaiting requester with `err`. */\n\treject(err: Error): void {\n\t\tif (this.#done) return;\n\t\tthis.#done = true;\n\t\tthis.#server.reject(this, err);\n\t}\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@norskvideo/moq-net",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"description": "The networking layer for Media over QUIC: real-time pub/sub with built-in caching, fan-out, and prioritization.",
|
|
6
6
|
"license": "(MIT OR Apache-2.0)",
|
|
7
|
-
"repository":
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/moq-dev/moq.git",
|
|
10
|
+
"directory": "js/net"
|
|
11
|
+
},
|
|
8
12
|
"sideEffects": false,
|
|
9
13
|
"exports": {
|
|
10
14
|
".": {
|
|
@@ -20,7 +24,8 @@
|
|
|
20
24
|
"@moq/qmux": "^0.3.3",
|
|
21
25
|
"async-mutex": "^0.5.0",
|
|
22
26
|
"bowser": "^2.14.1",
|
|
23
|
-
"@norskvideo/moq-
|
|
27
|
+
"@norskvideo/moq-pattern": "^0.2.1",
|
|
28
|
+
"@norskvideo/moq-signals": "^0.2.1"
|
|
24
29
|
},
|
|
25
30
|
"peerDependencies": {
|
|
26
31
|
"zod": "^4.4.3"
|
package/path.d.ts
CHANGED
|
@@ -5,8 +5,14 @@
|
|
|
5
5
|
* preventing issues like "foo" matching "foobar".
|
|
6
6
|
*
|
|
7
7
|
* Paths are automatically trimmed of leading and trailing slashes on creation,
|
|
8
|
-
* making all slashes implicit at boundaries.
|
|
9
|
-
*
|
|
8
|
+
* making all slashes implicit at boundaries. A path names a point in the origin's
|
|
9
|
+
* tree from its root; a leading slash never escapes that root. The same type names
|
|
10
|
+
* an exact broadcast and the prefix a route or announcement covers, so a broadcast's
|
|
11
|
+
* own path is the prefix it announces. See {@link Relative} for `..`-style references.
|
|
12
|
+
*
|
|
13
|
+
* {@link Pattern} and {@link Patterns} are re-exported from `@norskvideo/moq-pattern`, the owner of
|
|
14
|
+
* the v1 grammar and algebra. Literal path construction and wire decoding retain
|
|
15
|
+
* their existing behavior.
|
|
10
16
|
*
|
|
11
17
|
* @example
|
|
12
18
|
* ```typescript
|
|
@@ -31,6 +37,16 @@
|
|
|
31
37
|
export type Valid = string & {
|
|
32
38
|
__brand: "Name";
|
|
33
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* A relative reference from one broadcast to another, as a hang catalog carries it.
|
|
42
|
+
*
|
|
43
|
+
* It may contain `..` and is meaningful only once {@link resolve}d against a base
|
|
44
|
+
* {@link Valid} path. It never crosses the wire on its own. Build one with
|
|
45
|
+
* {@link normalizeRelative} or {@link relative}.
|
|
46
|
+
*/
|
|
47
|
+
export type Relative = string & {
|
|
48
|
+
__brand: "Relative";
|
|
49
|
+
};
|
|
34
50
|
/**
|
|
35
51
|
* Maximum number of slash-separated parts in a path.
|
|
36
52
|
*
|
|
@@ -114,11 +130,11 @@ export declare function empty(): Valid;
|
|
|
114
130
|
* normalizes to `.` because it names the base's parent, while empty names the base.
|
|
115
131
|
* `..` is preserved and only interpreted by {@link resolve}.
|
|
116
132
|
*
|
|
117
|
-
* Mirrors the Rust `
|
|
133
|
+
* Mirrors the Rust `path::Relative::new` normalization, so JS and Rust agree
|
|
118
134
|
* byte-for-byte on the stored form. Two callers comparing normalized strings can
|
|
119
135
|
* detect equivalent references while preserving the distinction between `""` and `"."`.
|
|
120
136
|
*/
|
|
121
|
-
export declare function normalizeRelative(rel: string):
|
|
137
|
+
export declare function normalizeRelative(rel: string): Relative;
|
|
122
138
|
/**
|
|
123
139
|
* Resolve a relative path reference against a base path.
|
|
124
140
|
*
|
|
@@ -137,7 +153,7 @@ export declare function normalizeRelative(rel: string): string;
|
|
|
137
153
|
* Path.resolve(Path.from("a/b/c"), "../source"); // "a/source"
|
|
138
154
|
* ```
|
|
139
155
|
*/
|
|
140
|
-
export declare function resolve(base: Valid, rel:
|
|
156
|
+
export declare function resolve(base: Valid, rel: Relative): Valid;
|
|
141
157
|
/**
|
|
142
158
|
* Resolve a relative path, returning `undefined` if it escapes above the root.
|
|
143
159
|
*
|
|
@@ -145,7 +161,7 @@ export declare function resolve(base: Valid, rel: string): Valid;
|
|
|
145
161
|
* path from excess `..` segments. Use it for untrusted catalog references that
|
|
146
162
|
* must not be clamped to the root.
|
|
147
163
|
*/
|
|
148
|
-
export declare function tryResolve(base: Valid, rel:
|
|
164
|
+
export declare function tryResolve(base: Valid, rel: Relative): Valid | undefined;
|
|
149
165
|
/**
|
|
150
166
|
* Express `target` relative to `base`: the inverse of {@link resolve}.
|
|
151
167
|
*
|
|
@@ -174,5 +190,7 @@ export declare function tryResolve(base: Valid, rel: string): Valid | undefined;
|
|
|
174
190
|
* Path.relative(Path.from("a/.."), Path.from("a/b")); // undefined
|
|
175
191
|
* ```
|
|
176
192
|
*/
|
|
177
|
-
export declare function relative(target: Valid, base: Valid):
|
|
193
|
+
export declare function relative(target: Valid, base: Valid): Relative | undefined;
|
|
194
|
+
/** Path patterns: grammar and algebra owned by `@norskvideo/moq-pattern`. */
|
|
195
|
+
export { compareSpecificity, InvalidPattern, Pattern, Patterns, type Segment, type Specificity, } from "@norskvideo/moq-pattern";
|
|
178
196
|
//# sourceMappingURL=path.d.ts.map
|
package/path.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,UAAU,CAAA;CAAE,CAAC;AAExD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B,iGAAiG;AACjG,wBAAgB,IAAI,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,CAI9C;AAED,gFAAgF;AAChF,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,EAAE,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAGzC;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,KAAK,CAKzC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,GAAG,OAAO,CAgB7D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,IAAI,CAiBpE;AAED;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CASrD;AAED,uDAAuD;AACvD,wBAAgB,KAAK,IAAI,KAAK,CAE7B;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAKvD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,GAAG,KAAK,CAkBzD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,GAAG,KAAK,GAAG,SAAS,CAkBxE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CA0BzE;AAED,kEAAkE;AAClE,OAAO,EACN,kBAAkB,EAClB,cAAc,EACd,OAAO,EACP,QAAQ,EACR,KAAK,OAAO,EACZ,KAAK,WAAW,GAChB,MAAM,cAAc,CAAC"}
|
package/path.js
CHANGED
|
@@ -136,14 +136,14 @@ export function empty() {
|
|
|
136
136
|
* normalizes to `.` because it names the base's parent, while empty names the base.
|
|
137
137
|
* `..` is preserved and only interpreted by {@link resolve}.
|
|
138
138
|
*
|
|
139
|
-
* Mirrors the Rust `
|
|
139
|
+
* Mirrors the Rust `path::Relative::new` normalization, so JS and Rust agree
|
|
140
140
|
* byte-for-byte on the stored form. Two callers comparing normalized strings can
|
|
141
141
|
* detect equivalent references while preserving the distinction between `""` and `"."`.
|
|
142
142
|
*/
|
|
143
143
|
export function normalizeRelative(rel) {
|
|
144
144
|
const raw = rel.split("/");
|
|
145
145
|
const normalized = raw.filter((s) => s !== "" && s !== ".").join("/");
|
|
146
|
-
return normalized === "" && raw.includes(".") ? "." : normalized;
|
|
146
|
+
return (normalized === "" && raw.includes(".") ? "." : normalized);
|
|
147
147
|
}
|
|
148
148
|
/**
|
|
149
149
|
* Resolve a relative path reference against a base path.
|
|
@@ -256,6 +256,8 @@ export function relative(target, base) {
|
|
|
256
256
|
.fill("..")
|
|
257
257
|
.concat(down);
|
|
258
258
|
// An empty reference resolves to the base itself, so name the parent explicitly.
|
|
259
|
-
return rel.length === 0 ? "." : rel.join("/");
|
|
259
|
+
return (rel.length === 0 ? "." : rel.join("/"));
|
|
260
260
|
}
|
|
261
|
+
/** Path patterns: grammar and algebra owned by `@norskvideo/moq-pattern`. */
|
|
262
|
+
export { compareSpecificity, InvalidPattern, Pattern, Patterns, } from "@norskvideo/moq-pattern";
|
|
261
263
|
//# sourceMappingURL=path.js.map
|
package/path.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.js","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAgCA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAE5B,iGAAiG;AACjG,MAAM,UAAU,IAAI,CAAC,GAAG,KAAe;IACtC,4GAA4G;IAC5G,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAU,CAAC;AACrF,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,KAAK,CAAC,IAAW;IAChC,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,GAAW;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,IAAW;IACjC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,gBAAgB,SAAS,QAAQ,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,SAAS,CAAC,MAAa,EAAE,IAAW;IACnD,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,yCAAyC;IACzC,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,kEAAkE;IAClE,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,WAAW,CAAC,MAAa,EAAE,IAAW;IACrD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACb,CAAC;IAED,2BAA2B;IAC3B,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,0CAA0C;IAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACnC,OAAO,EAAW,CAAC;IACpB,CAAC;IAED,+EAA+E;IAC/E,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAU,CAAC;AAC/C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,IAAI,CAAC,IAAW,EAAE,KAAY;IAC7C,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC;IACd,CAAC;SAAM,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACb,CAAC;SAAM,CAAC;QACP,yDAAyD;QACzD,OAAO,GAAG,IAAI,IAAI,KAAK,EAAW,CAAC;IACpC,CAAC;AACF,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,KAAK;IACpB,OAAO,EAAW,CAAC;AACpB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC5C,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEtE,OAAO,UAAU,KAAK,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,OAAO,CAAC,IAAW,EAAE,GAAW;IAC/C,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAE5B,MAAM,QAAQ,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpD,QAAQ,CAAC,GAAG,EAAE,CAAC;IAEf,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAC/B,SAAS;QACV,CAAC;QACD,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAClB,QAAQ,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;aAAM,CAAC;YACP,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACF,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAU,CAAC;AACpC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,IAAW,EAAE,GAAW;IAClD,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAE5B,MAAM,QAAQ,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpD,QAAQ,CAAC,GAAG,EAAE,CAAC;IAEf,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAC/B,SAAS;QACV,CAAC;QACD,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAClB,IAAI,QAAQ,CAAC,GAAG,EAAE,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;QACpD,CAAC;aAAM,CAAC;YACP,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACF,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAU,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAa,EAAE,IAAW;IAClD,qFAAqF;IACrF,kEAAkE;IAClE,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAE/B,wEAAwE;IACxE,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,GAAG,CAAC,GAAG,EAAE,CAAC;IAEV,MAAM,KAAK,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAErD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,OAAO,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACtF,MAAM,IAAI,CAAC,CAAC;IACb,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACjC,yDAAyD;IACzD,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAEzE,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;SACpC,IAAI,CAAC,IAAI,CAAC;SACV,MAAM,CAAC,IAAI,CAAC,CAAC;IAEf,iFAAiF;IACjF,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,CAAC","sourcesContent":["/**\n * A broadcast path that provides safe prefix matching operations.\n *\n * This module provides path-aware operations that respect delimiter boundaries,\n * preventing issues like \"foo\" matching \"foobar\".\n *\n * Paths are automatically trimmed of leading and trailing slashes on creation,\n * making all slashes implicit at boundaries.\n * All paths are RELATIVE; you cannot join with a leading slash to make an absolute path.\n *\n * @example\n * ```typescript\n * // Creation automatically trims slashes\n * const path1 = Path.from(\"/foo/bar/\");\n * const path2 = Path.from(\"foo/bar\");\n * console.log(path1 === path2); // true\n *\n * // Multiple arguments are joined with \"/\"\n * const path3 = Path.from(\"api\", \"v1\", \"users\");\n * console.log(path3); // \"api/v1/users\"\n *\n * // Safe prefix matching\n * const base = Path.from(\"api/v1\");\n * console.log(Path.hasPrefix(Path.from(\"api\"), base)); // true\n * console.log(Path.hasPrefix(Path.from(\"api/v1\"), base)); // true\n *\n * const joined = Path.join(base, Path.from(\"users\"));\n * console.log(joined); // \"api/v1/users\"\n * ```\n */\nexport type Valid = string & { __brand: \"Name\" };\n\n/**\n * Maximum number of slash-separated parts in a path.\n *\n * Matches the IETF moq-transport limit of 32 fields in a namespace tuple.\n * moq-lite enforces the same bound when decoding paths off the wire.\n */\nexport const MAX_PARTS = 32;\n\n/** Build a path from one or more components, joining with \"/\" and trimming redundant slashes. */\nexport function from(...paths: string[]): Valid {\n\t// Join paths with \"/\" and then remove leading and trailing slashes, and collapse multiple slashes into one.\n\tconst joined = paths.join(\"/\");\n\treturn joined.replace(/\\/+/g, \"/\").replace(/^\\/+/, \"\").replace(/\\/+$/, \"\") as Valid;\n}\n\n/** Split a path into its slash-separated parts. The empty path has no parts. */\nexport function parts(path: Valid): string[] {\n\treturn path === \"\" ? [] : path.split(\"/\");\n}\n\n/**\n * Validate an untrusted wire string as a path, enforcing {@link MAX_PARTS}.\n *\n * Throws when the path has too many parts; use at wire decode sites.\n */\nexport function decode(raw: string): Valid {\n\tconst path = from(raw);\n\treturn encode(path);\n}\n\n/**\n * Validate a path before writing it to the wire, enforcing {@link MAX_PARTS}.\n *\n * Throws when the path has too many parts; use at wire encode sites so we never\n * emit a path the remote side is required to reject.\n */\nexport function encode(path: Valid): Valid {\n\tif (parts(path).length > MAX_PARTS) {\n\t\tthrow new Error(`path exceeds ${MAX_PARTS} parts`);\n\t}\n\treturn path;\n}\n\n/**\n * Check if a path has the given prefix, respecting path boundaries.\n *\n * Unlike String.startsWith, this ensures that \"foo\" does not match \"foobar\".\n * The prefix must either:\n * - Be exactly equal to the path\n * - Be followed by a '/' delimiter in the original path\n * - Be empty (matches everything)\n *\n * @example\n * ```typescript\n * const path = Path.from(\"foo/bar\");\n * console.log(Path.hasPrefix(Path.from(\"foo\"), path)); // true\n * console.log(Path.hasPrefix(Path.from(\"foo/\"), path)); // true (trailing slash ignored)\n * console.log(Path.hasPrefix(Path.from(\"fo\"), path)); // false\n *\n * const path2 = Path.from(\"foobar\");\n * console.log(Path.hasPrefix(Path.from(\"foo\"), path2)); // false\n * ```\n */\nexport function hasPrefix(prefix: Valid, path: Valid): boolean {\n\tif (prefix === \"\") {\n\t\treturn true;\n\t}\n\n\tif (!path.startsWith(prefix)) {\n\t\treturn false;\n\t}\n\n\t// Check if the prefix is the exact match\n\tif (path.length === prefix.length) {\n\t\treturn true;\n\t}\n\n\t// Otherwise, ensure the character after the prefix is a delimiter\n\treturn path[prefix.length] === \"/\";\n}\n\n/**\n * Strip the given prefix from a path, returning the suffix.\n *\n * Returns null if the prefix doesn't match according to hasPrefix rules.\n *\n * @example\n * ```typescript\n * const path = Path.from(\"foo/bar/baz\");\n * const suffix = Path.stripPrefix(Path.from(\"foo\"), path);\n * console.log(suffix); // \"bar/baz\"\n *\n * const suffix2 = Path.stripPrefix(Path.from(\"foo/\"), path);\n * console.log(suffix2); // \"bar/baz\"\n *\n * const noMatch = Path.stripPrefix(Path.from(\"notfound\"), path);\n * console.log(noMatch); // null\n * ```\n */\nexport function stripPrefix(prefix: Valid, path: Valid): Valid | null {\n\tif (!hasPrefix(prefix, path)) {\n\t\treturn null;\n\t}\n\n\t// Handle empty prefix case\n\tif (prefix === \"\") {\n\t\treturn path;\n\t}\n\n\t// If prefix matches exactly, return empty\n\tif (path.length === prefix.length) {\n\t\treturn \"\" as Valid;\n\t}\n\n\t// For non-empty prefix that's shorter, skip the prefix and the following slash\n\treturn path.slice(prefix.length + 1) as Valid;\n}\n\n/**\n * Join two path components together.\n *\n * @example\n * ```typescript\n * const base = Path.from(\"foo\");\n * const joined = Path.join(base, Path.from(\"bar\"));\n * console.log(joined); // \"foo/bar\"\n * ```\n */\nexport function join(path: Valid, other: Valid): Valid {\n\tif (path === \"\") {\n\t\treturn other;\n\t} else if (other === \"\") {\n\t\treturn path;\n\t} else {\n\t\t// Since paths are trimmed, we always need to add a slash\n\t\treturn `${path}/${other}` as Valid;\n\t}\n}\n\n/** The empty path, which is a prefix of every path. */\nexport function empty(): Valid {\n\treturn \"\" as Valid;\n}\n\n/**\n * Normalize a relative path reference: trim leading/trailing slashes, drop empty\n * segments, and drop redundant `.` segments. A reference made only of `.` segments\n * normalizes to `.` because it names the base's parent, while empty names the base.\n * `..` is preserved and only interpreted by {@link resolve}.\n *\n * Mirrors the Rust `PathRelative::new` normalization, so JS and Rust agree\n * byte-for-byte on the stored form. Two callers comparing normalized strings can\n * detect equivalent references while preserving the distinction between `\"\"` and `\".\"`.\n */\nexport function normalizeRelative(rel: string): string {\n\tconst raw = rel.split(\"/\");\n\tconst normalized = raw.filter((s) => s !== \"\" && s !== \".\").join(\"/\");\n\n\treturn normalized === \"\" && raw.includes(\".\") ? \".\" : normalized;\n}\n\n/**\n * Resolve a relative path reference against a base path.\n *\n * A non-empty reference replaces the last segment of the base, matching relative URL\n * resolution. `..` segments then pop another segment; other segments are appended.\n * `.` and empty segments are no-ops. Excess `..` once the base is empty is also a no-op\n * (subsequent named segments still append). An empty `rel` returns the base unchanged.\n *\n * Mirrors the Rust `Path::resolve`, used by hang catalogs to express\n * cross-broadcast track references (a rendition's `broadcast` field).\n *\n * @example\n * ```typescript\n * Path.resolve(Path.from(\"a/b/c\"), \"./source\"); // \"a/b/source\"\n * Path.resolve(Path.from(\"a/b\"), \".\"); // \"a\"\n * Path.resolve(Path.from(\"a/b/c\"), \"../source\"); // \"a/source\"\n * ```\n */\nexport function resolve(base: Valid, rel: string): Valid {\n\tif (rel === \"\") return base;\n\n\tconst segments = base === \"\" ? [] : base.split(\"/\");\n\tsegments.pop();\n\n\tfor (const seg of rel.split(\"/\")) {\n\t\tif (seg === \"\" || seg === \".\") {\n\t\t\tcontinue;\n\t\t}\n\t\tif (seg === \"..\") {\n\t\t\tsegments.pop();\n\t\t} else {\n\t\t\tsegments.push(seg);\n\t\t}\n\t}\n\n\treturn segments.join(\"/\") as Valid;\n}\n\n/**\n * Resolve a relative path, returning `undefined` if it escapes above the root.\n *\n * Unlike {@link resolve}, this distinguishes a valid reference to the empty root\n * path from excess `..` segments. Use it for untrusted catalog references that\n * must not be clamped to the root.\n */\nexport function tryResolve(base: Valid, rel: string): Valid | undefined {\n\tif (rel === \"\") return base;\n\n\tconst segments = base === \"\" ? [] : base.split(\"/\");\n\tsegments.pop();\n\n\tfor (const seg of rel.split(\"/\")) {\n\t\tif (seg === \"\" || seg === \".\") {\n\t\t\tcontinue;\n\t\t}\n\t\tif (seg === \"..\") {\n\t\t\tif (segments.pop() === undefined) return undefined;\n\t\t} else {\n\t\t\tsegments.push(seg);\n\t\t}\n\t}\n\n\treturn segments.join(\"/\") as Valid;\n}\n\n/**\n * Express `target` relative to `base`: the inverse of {@link resolve}.\n *\n * The result round-trips (`resolve(base, relative(target, base)) === target`) and never\n * walks above the root, so {@link tryResolve} accepts it too.\n *\n * A relative reference replaces the last segment of the base, matching relative URL\n * resolution, so a target nested under the base repeats the base's own last segment.\n *\n * The empty reference names the base itself, so that is what a self-reference returns.\n *\n * Returns `undefined` for a target no reference can name: a path segment may literally be\n * `.` or `..`, which resolution reads as navigation instead of as a name. Only the segments\n * past the shared prefix matter, since the rest are never emitted.\n *\n * Mirrors the Rust `Path::relative`, used to author the cross-broadcast track\n * references a hang catalog carries. Note the argument order: the target comes first,\n * the opposite of Node's `path.relative(from, to)`.\n *\n * @example\n * ```typescript\n * Path.relative(Path.from(\"a/b/c\"), Path.from(\"a/b\")); // \"b/c\"\n * Path.relative(Path.from(\"a/c\"), Path.from(\"a/b\")); // \"c\"\n * Path.relative(Path.from(\"a\"), Path.from(\"a/b\")); // \".\"\n * Path.relative(Path.from(\"a/b\"), Path.from(\"a/b\")); // \"\"\n * Path.relative(Path.from(\"a/..\"), Path.from(\"a/b\")); // undefined\n * ```\n */\nexport function relative(target: Valid, base: Valid): string | undefined {\n\t// Only the empty reference can name a base whose last segment is itself `.` or `..`,\n\t// since resolution replaces that segment rather than emitting it.\n\tif (target === base) return \"\";\n\n\t// Resolution replaces the base's last segment, so walk from its parent.\n\tconst dir = base === \"\" ? [] : base.split(\"/\");\n\tdir.pop();\n\n\tconst parts = target === \"\" ? [] : target.split(\"/\");\n\n\tlet common = 0;\n\twhile (common < dir.length && common < parts.length && dir[common] === parts[common]) {\n\t\tcommon += 1;\n\t}\n\n\tconst down = parts.slice(common);\n\t// Resolution would walk on these instead of naming them.\n\tif (down.some((part) => part === \".\" || part === \"..\")) return undefined;\n\n\tconst rel = Array(dir.length - common)\n\t\t.fill(\"..\")\n\t\t.concat(down);\n\n\t// An empty reference resolves to the base itself, so name the parent explicitly.\n\treturn rel.length === 0 ? \".\" : rel.join(\"/\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A broadcast path that provides safe prefix matching operations.\n *\n * This module provides path-aware operations that respect delimiter boundaries,\n * preventing issues like \"foo\" matching \"foobar\".\n *\n * Paths are automatically trimmed of leading and trailing slashes on creation,\n * making all slashes implicit at boundaries. A path names a point in the origin's\n * tree from its root; a leading slash never escapes that root. The same type names\n * an exact broadcast and the prefix a route or announcement covers, so a broadcast's\n * own path is the prefix it announces. See {@link Relative} for `..`-style references.\n *\n * {@link Pattern} and {@link Patterns} are re-exported from `@moq/pattern`, the owner of\n * the v1 grammar and algebra. Literal path construction and wire decoding retain\n * their existing behavior.\n *\n * @example\n * ```typescript\n * // Creation automatically trims slashes\n * const path1 = Path.from(\"/foo/bar/\");\n * const path2 = Path.from(\"foo/bar\");\n * console.log(path1 === path2); // true\n *\n * // Multiple arguments are joined with \"/\"\n * const path3 = Path.from(\"api\", \"v1\", \"users\");\n * console.log(path3); // \"api/v1/users\"\n *\n * // Safe prefix matching\n * const base = Path.from(\"api/v1\");\n * console.log(Path.hasPrefix(Path.from(\"api\"), base)); // true\n * console.log(Path.hasPrefix(Path.from(\"api/v1\"), base)); // true\n *\n * const joined = Path.join(base, Path.from(\"users\"));\n * console.log(joined); // \"api/v1/users\"\n * ```\n */\nexport type Valid = string & { __brand: \"Name\" };\n\n/**\n * A relative reference from one broadcast to another, as a hang catalog carries it.\n *\n * It may contain `..` and is meaningful only once {@link resolve}d against a base\n * {@link Valid} path. It never crosses the wire on its own. Build one with\n * {@link normalizeRelative} or {@link relative}.\n */\nexport type Relative = string & { __brand: \"Relative\" };\n\n/**\n * Maximum number of slash-separated parts in a path.\n *\n * Matches the IETF moq-transport limit of 32 fields in a namespace tuple.\n * moq-lite enforces the same bound when decoding paths off the wire.\n */\nexport const MAX_PARTS = 32;\n\n/** Build a path from one or more components, joining with \"/\" and trimming redundant slashes. */\nexport function from(...paths: string[]): Valid {\n\t// Join paths with \"/\" and then remove leading and trailing slashes, and collapse multiple slashes into one.\n\tconst joined = paths.join(\"/\");\n\treturn joined.replace(/\\/+/g, \"/\").replace(/^\\/+/, \"\").replace(/\\/+$/, \"\") as Valid;\n}\n\n/** Split a path into its slash-separated parts. The empty path has no parts. */\nexport function parts(path: Valid): string[] {\n\treturn path === \"\" ? [] : path.split(\"/\");\n}\n\n/**\n * Validate an untrusted wire string as a path, enforcing {@link MAX_PARTS}.\n *\n * Throws when the path has too many parts; use at wire decode sites.\n */\nexport function decode(raw: string): Valid {\n\tconst path = from(raw);\n\treturn encode(path);\n}\n\n/**\n * Validate a path before writing it to the wire, enforcing {@link MAX_PARTS}.\n *\n * Throws when the path has too many parts; use at wire encode sites so we never\n * emit a path the remote side is required to reject.\n */\nexport function encode(path: Valid): Valid {\n\tif (parts(path).length > MAX_PARTS) {\n\t\tthrow new Error(`path exceeds ${MAX_PARTS} parts`);\n\t}\n\treturn path;\n}\n\n/**\n * Check if a path has the given prefix, respecting path boundaries.\n *\n * Unlike String.startsWith, this ensures that \"foo\" does not match \"foobar\".\n * The prefix must either:\n * - Be exactly equal to the path\n * - Be followed by a '/' delimiter in the original path\n * - Be empty (matches everything)\n *\n * @example\n * ```typescript\n * const path = Path.from(\"foo/bar\");\n * console.log(Path.hasPrefix(Path.from(\"foo\"), path)); // true\n * console.log(Path.hasPrefix(Path.from(\"foo/\"), path)); // true (trailing slash ignored)\n * console.log(Path.hasPrefix(Path.from(\"fo\"), path)); // false\n *\n * const path2 = Path.from(\"foobar\");\n * console.log(Path.hasPrefix(Path.from(\"foo\"), path2)); // false\n * ```\n */\nexport function hasPrefix(prefix: Valid, path: Valid): boolean {\n\tif (prefix === \"\") {\n\t\treturn true;\n\t}\n\n\tif (!path.startsWith(prefix)) {\n\t\treturn false;\n\t}\n\n\t// Check if the prefix is the exact match\n\tif (path.length === prefix.length) {\n\t\treturn true;\n\t}\n\n\t// Otherwise, ensure the character after the prefix is a delimiter\n\treturn path[prefix.length] === \"/\";\n}\n\n/**\n * Strip the given prefix from a path, returning the suffix.\n *\n * Returns null if the prefix doesn't match according to hasPrefix rules.\n *\n * @example\n * ```typescript\n * const path = Path.from(\"foo/bar/baz\");\n * const suffix = Path.stripPrefix(Path.from(\"foo\"), path);\n * console.log(suffix); // \"bar/baz\"\n *\n * const suffix2 = Path.stripPrefix(Path.from(\"foo/\"), path);\n * console.log(suffix2); // \"bar/baz\"\n *\n * const noMatch = Path.stripPrefix(Path.from(\"notfound\"), path);\n * console.log(noMatch); // null\n * ```\n */\nexport function stripPrefix(prefix: Valid, path: Valid): Valid | null {\n\tif (!hasPrefix(prefix, path)) {\n\t\treturn null;\n\t}\n\n\t// Handle empty prefix case\n\tif (prefix === \"\") {\n\t\treturn path;\n\t}\n\n\t// If prefix matches exactly, return empty\n\tif (path.length === prefix.length) {\n\t\treturn \"\" as Valid;\n\t}\n\n\t// For non-empty prefix that's shorter, skip the prefix and the following slash\n\treturn path.slice(prefix.length + 1) as Valid;\n}\n\n/**\n * Join two path components together.\n *\n * @example\n * ```typescript\n * const base = Path.from(\"foo\");\n * const joined = Path.join(base, Path.from(\"bar\"));\n * console.log(joined); // \"foo/bar\"\n * ```\n */\nexport function join(path: Valid, other: Valid): Valid {\n\tif (path === \"\") {\n\t\treturn other;\n\t} else if (other === \"\") {\n\t\treturn path;\n\t} else {\n\t\t// Since paths are trimmed, we always need to add a slash\n\t\treturn `${path}/${other}` as Valid;\n\t}\n}\n\n/** The empty path, which is a prefix of every path. */\nexport function empty(): Valid {\n\treturn \"\" as Valid;\n}\n\n/**\n * Normalize a relative path reference: trim leading/trailing slashes, drop empty\n * segments, and drop redundant `.` segments. A reference made only of `.` segments\n * normalizes to `.` because it names the base's parent, while empty names the base.\n * `..` is preserved and only interpreted by {@link resolve}.\n *\n * Mirrors the Rust `path::Relative::new` normalization, so JS and Rust agree\n * byte-for-byte on the stored form. Two callers comparing normalized strings can\n * detect equivalent references while preserving the distinction between `\"\"` and `\".\"`.\n */\nexport function normalizeRelative(rel: string): Relative {\n\tconst raw = rel.split(\"/\");\n\tconst normalized = raw.filter((s) => s !== \"\" && s !== \".\").join(\"/\");\n\n\treturn (normalized === \"\" && raw.includes(\".\") ? \".\" : normalized) as Relative;\n}\n\n/**\n * Resolve a relative path reference against a base path.\n *\n * A non-empty reference replaces the last segment of the base, matching relative URL\n * resolution. `..` segments then pop another segment; other segments are appended.\n * `.` and empty segments are no-ops. Excess `..` once the base is empty is also a no-op\n * (subsequent named segments still append). An empty `rel` returns the base unchanged.\n *\n * Mirrors the Rust `Path::resolve`, used by hang catalogs to express\n * cross-broadcast track references (a rendition's `broadcast` field).\n *\n * @example\n * ```typescript\n * Path.resolve(Path.from(\"a/b/c\"), \"./source\"); // \"a/b/source\"\n * Path.resolve(Path.from(\"a/b\"), \".\"); // \"a\"\n * Path.resolve(Path.from(\"a/b/c\"), \"../source\"); // \"a/source\"\n * ```\n */\nexport function resolve(base: Valid, rel: Relative): Valid {\n\tif (rel === \"\") return base;\n\n\tconst segments = base === \"\" ? [] : base.split(\"/\");\n\tsegments.pop();\n\n\tfor (const seg of rel.split(\"/\")) {\n\t\tif (seg === \"\" || seg === \".\") {\n\t\t\tcontinue;\n\t\t}\n\t\tif (seg === \"..\") {\n\t\t\tsegments.pop();\n\t\t} else {\n\t\t\tsegments.push(seg);\n\t\t}\n\t}\n\n\treturn segments.join(\"/\") as Valid;\n}\n\n/**\n * Resolve a relative path, returning `undefined` if it escapes above the root.\n *\n * Unlike {@link resolve}, this distinguishes a valid reference to the empty root\n * path from excess `..` segments. Use it for untrusted catalog references that\n * must not be clamped to the root.\n */\nexport function tryResolve(base: Valid, rel: Relative): Valid | undefined {\n\tif (rel === \"\") return base;\n\n\tconst segments = base === \"\" ? [] : base.split(\"/\");\n\tsegments.pop();\n\n\tfor (const seg of rel.split(\"/\")) {\n\t\tif (seg === \"\" || seg === \".\") {\n\t\t\tcontinue;\n\t\t}\n\t\tif (seg === \"..\") {\n\t\t\tif (segments.pop() === undefined) return undefined;\n\t\t} else {\n\t\t\tsegments.push(seg);\n\t\t}\n\t}\n\n\treturn segments.join(\"/\") as Valid;\n}\n\n/**\n * Express `target` relative to `base`: the inverse of {@link resolve}.\n *\n * The result round-trips (`resolve(base, relative(target, base)) === target`) and never\n * walks above the root, so {@link tryResolve} accepts it too.\n *\n * A relative reference replaces the last segment of the base, matching relative URL\n * resolution, so a target nested under the base repeats the base's own last segment.\n *\n * The empty reference names the base itself, so that is what a self-reference returns.\n *\n * Returns `undefined` for a target no reference can name: a path segment may literally be\n * `.` or `..`, which resolution reads as navigation instead of as a name. Only the segments\n * past the shared prefix matter, since the rest are never emitted.\n *\n * Mirrors the Rust `Path::relative`, used to author the cross-broadcast track\n * references a hang catalog carries. Note the argument order: the target comes first,\n * the opposite of Node's `path.relative(from, to)`.\n *\n * @example\n * ```typescript\n * Path.relative(Path.from(\"a/b/c\"), Path.from(\"a/b\")); // \"b/c\"\n * Path.relative(Path.from(\"a/c\"), Path.from(\"a/b\")); // \"c\"\n * Path.relative(Path.from(\"a\"), Path.from(\"a/b\")); // \".\"\n * Path.relative(Path.from(\"a/b\"), Path.from(\"a/b\")); // \"\"\n * Path.relative(Path.from(\"a/..\"), Path.from(\"a/b\")); // undefined\n * ```\n */\nexport function relative(target: Valid, base: Valid): Relative | undefined {\n\t// Only the empty reference can name a base whose last segment is itself `.` or `..`,\n\t// since resolution replaces that segment rather than emitting it.\n\tif (target === base) return \"\" as Relative;\n\n\t// Resolution replaces the base's last segment, so walk from its parent.\n\tconst dir = base === \"\" ? [] : base.split(\"/\");\n\tdir.pop();\n\n\tconst parts = target === \"\" ? [] : target.split(\"/\");\n\n\tlet common = 0;\n\twhile (common < dir.length && common < parts.length && dir[common] === parts[common]) {\n\t\tcommon += 1;\n\t}\n\n\tconst down = parts.slice(common);\n\t// Resolution would walk on these instead of naming them.\n\tif (down.some((part) => part === \".\" || part === \"..\")) return undefined;\n\n\tconst rel = Array(dir.length - common)\n\t\t.fill(\"..\")\n\t\t.concat(down);\n\n\t// An empty reference resolves to the base itself, so name the parent explicitly.\n\treturn (rel.length === 0 ? \".\" : rel.join(\"/\")) as Relative;\n}\n\n/** Path patterns: grammar and algebra owned by `@moq/pattern`. */\nexport {\n\tcompareSpecificity,\n\tInvalidPattern,\n\tPattern,\n\tPatterns,\n\ttype Segment,\n\ttype Specificity,\n} from \"@moq/pattern\";\n"]}
|