@relayfile/sdk 0.10.52 → 0.10.53
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/dist/client.js +46 -1
- package/dist/types.d.ts +16 -0
- package/package.json +6 -6
package/dist/client.js
CHANGED
|
@@ -397,7 +397,13 @@ class RelayFileChangeSubscription {
|
|
|
397
397
|
this.onChange = onChange;
|
|
398
398
|
this.options = options;
|
|
399
399
|
this.globPatterns = globs.map((pattern) => normalizeChangePattern(pattern));
|
|
400
|
-
|
|
400
|
+
// A wildcard-free pathScope entry (e.g. "/ramp/transactions") is a DIRECTORY
|
|
401
|
+
// SUBTREE scope: expand it into the exact path plus its "/**" subtree filter
|
|
402
|
+
// so it matches the directory and everything under it. A bare path is never
|
|
403
|
+
// exact-file; use a glob for that. See expandDirectoryScope for the rule.
|
|
404
|
+
this.pathScopes = options?.pathScope?.length
|
|
405
|
+
? options.pathScope.flatMap((pattern) => expandDirectoryScope(normalizeChangePattern(pattern)))
|
|
406
|
+
: null;
|
|
401
407
|
this.shouldCoalesce = (options?.coalesce ?? "fire-once") !== "none";
|
|
402
408
|
this.coalesceMs = Math.max(0, Math.floor(options?.coalesceMs ?? DEFAULT_CHANGE_COALESCE_MS));
|
|
403
409
|
}
|
|
@@ -747,6 +753,45 @@ function normalizeChangePattern(pattern) {
|
|
|
747
753
|
}
|
|
748
754
|
return segments;
|
|
749
755
|
}
|
|
756
|
+
/**
|
|
757
|
+
* A wildcard-free `pathScope` entry is DEFINED as a DIRECTORY SUBTREE scope: it
|
|
758
|
+
* matches the path itself AND everything under it. To scope to an exact file,
|
|
759
|
+
* pass that exact path as a glob in the first `subscribe(globs, ...)` argument
|
|
760
|
+
* (the `globs` list is matched exactly unless an entry has a `*`/`**` wildcard);
|
|
761
|
+
* a bare `pathScope` path is never exact-file. This is a deliberate API-design
|
|
762
|
+
* choice (Option A), not an
|
|
763
|
+
* accident of the server matcher: it makes the common "watch this directory"
|
|
764
|
+
* intent Just Work and avoids a silent zero-event foot-gun.
|
|
765
|
+
*
|
|
766
|
+
* Why it MUST be subtree, and why "exact-file" is not a safe alternative:
|
|
767
|
+
* Relayfile creates descendants under file-looking paths (e.g.
|
|
768
|
+
* `/linear/issues/ENG-1.json/replies/draft.json`), so a bare path can never be
|
|
769
|
+
* assumed to name a leaf. Treating a wildcard-free entry as directory-scope is
|
|
770
|
+
* the only consistent rule.
|
|
771
|
+
*
|
|
772
|
+
* The data plane (see `webSocketPathMatches` in internal/httpapi/websocket.go)
|
|
773
|
+
* matches a `path=` filter against an event path with these semantics:
|
|
774
|
+
* - exact match: `path` == the event path, OR
|
|
775
|
+
* - trailing `**`: `/ramp/transactions/**` matches any STRICT descendant, OR
|
|
776
|
+
* - per-segment `*` wildcards, requiring equal segment counts otherwise.
|
|
777
|
+
* A bare directory prefix like `/ramp/transactions` (no wildcard) would
|
|
778
|
+
* therefore match ONLY an event whose path is exactly `/ramp/transactions` —
|
|
779
|
+
* ZERO children — so a caller scoping to `["/ramp/transactions"]` opens a WS
|
|
780
|
+
* that silently receives no events (proven: `path=/ramp/transactions` -> 0
|
|
781
|
+
* events; `/**` -> 6). The same count-must-match rule in `matchChangeSegments`
|
|
782
|
+
* makes the client-side filter agree, so the miss would be doubly silent.
|
|
783
|
+
*
|
|
784
|
+
* Implementation: for a wildcard-free entry, emit BOTH the exact path AND the
|
|
785
|
+
* `.../**` subtree filter — the union matches the directory node itself plus its
|
|
786
|
+
* entire subtree. Entries that already contain a `*`/`**` wildcard are honored
|
|
787
|
+
* verbatim — an intentionally precise glob is never broadened.
|
|
788
|
+
*/
|
|
789
|
+
function expandDirectoryScope(segments) {
|
|
790
|
+
if (segments.some((segment) => segment === "*" || segment === "**")) {
|
|
791
|
+
return [segments];
|
|
792
|
+
}
|
|
793
|
+
return [segments, [...segments, "**"]];
|
|
794
|
+
}
|
|
750
795
|
function normalizeChangePath(path) {
|
|
751
796
|
const normalized = path.startsWith("/") ? path : `/${path}`;
|
|
752
797
|
const trimmed = normalized.replace(/\/+$/, "");
|
package/dist/types.d.ts
CHANGED
|
@@ -416,6 +416,22 @@ export interface LayoutManifest {
|
|
|
416
416
|
export interface SubscribeOptions {
|
|
417
417
|
coalesce?: "none" | "fire-once";
|
|
418
418
|
coalesceMs?: number;
|
|
419
|
+
/**
|
|
420
|
+
* Narrow the server-side event stream to one or more path scopes.
|
|
421
|
+
*
|
|
422
|
+
* A **wildcard-free** entry is a DIRECTORY SUBTREE scope: `"/ramp/transactions"`
|
|
423
|
+
* matches that path AND everything under it. A bare path is NOT treated as an
|
|
424
|
+
* exact-file match — Relayfile creates descendants under file-looking paths
|
|
425
|
+
* (e.g. `/linear/issues/ENG-1.json/replies/draft.json`), so a wildcard-free
|
|
426
|
+
* scope always means "this directory and its subtree".
|
|
427
|
+
*
|
|
428
|
+
* To scope to something more precise, pass an explicit glob: a trailing `**`
|
|
429
|
+
* (`"/ramp/transactions/**"`) for a subtree, or per-segment `*` wildcards
|
|
430
|
+
* (`"/github/repos/acme/api/pulls/*"`); these are honored verbatim. For an
|
|
431
|
+
* exact single file, pass that exact path as a glob in the first `subscribe`
|
|
432
|
+
* argument (`subscribe(globs, ...)`, e.g. `["/linear/issues/ENG-1.json"]`) —
|
|
433
|
+
* the `globs` list is matched exactly unless it contains a `*`/`**` wildcard.
|
|
434
|
+
*/
|
|
419
435
|
pathScope?: string[];
|
|
420
436
|
from?: "now" | "legacy";
|
|
421
437
|
cursor?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relayfile/sdk",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.53",
|
|
4
4
|
"description": "TypeScript SDK for relayfile — real-time filesystem for humans and agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -59,15 +59,15 @@
|
|
|
59
59
|
"prepublishOnly": "npm run build"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@relayfile/core": "0.10.
|
|
62
|
+
"@relayfile/core": "0.10.53",
|
|
63
63
|
"ignore": "^7.0.5",
|
|
64
64
|
"tar": "^7.5.10"
|
|
65
65
|
},
|
|
66
66
|
"optionalDependencies": {
|
|
67
|
-
"@relayfile/mount-darwin-arm64": "0.10.
|
|
68
|
-
"@relayfile/mount-darwin-x64": "0.10.
|
|
69
|
-
"@relayfile/mount-linux-arm64": "0.10.
|
|
70
|
-
"@relayfile/mount-linux-x64": "0.10.
|
|
67
|
+
"@relayfile/mount-darwin-arm64": "0.10.53",
|
|
68
|
+
"@relayfile/mount-darwin-x64": "0.10.53",
|
|
69
|
+
"@relayfile/mount-linux-arm64": "0.10.53",
|
|
70
|
+
"@relayfile/mount-linux-x64": "0.10.53"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"typescript": "^5.7.3",
|