@rigxyz/tapd 0.3.0 → 0.4.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/dist/bin.js +236 -34
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-N3KRCOBG.js → chunk-JBX2ZRMD.js} +739 -190
- package/dist/chunk-JBX2ZRMD.js.map +1 -0
- package/dist/index.d.ts +318 -19
- package/dist/index.js +35 -3
- package/package.json +12 -12
- package/LICENSE +0 -21
- package/dist/chunk-N3KRCOBG.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -65,6 +65,12 @@ type WalkResult = {
|
|
|
65
65
|
};
|
|
66
66
|
declare function walk(rootDir: string, opts: {
|
|
67
67
|
ignore: Ignore;
|
|
68
|
+
/**
|
|
69
|
+
* Mount points (posix, relative to rootDir) to hard-exclude — import
|
|
70
|
+
* subdirectories materialized by mirror subscriptions. Never scanned,
|
|
71
|
+
* never uploaded into this binding. Non-overridable by .tapignore.
|
|
72
|
+
*/
|
|
73
|
+
excludePaths?: ReadonlyArray<string>;
|
|
68
74
|
}): WalkResult;
|
|
69
75
|
|
|
70
76
|
/**
|
|
@@ -121,7 +127,14 @@ declare class RelayClient {
|
|
|
121
127
|
prepareUpload(body: PrepareUploadRequest): Promise<PrepareUploadResponse>;
|
|
122
128
|
completeUpload(body: CompleteUploadRequest): Promise<CompleteUploadResponse>;
|
|
123
129
|
downloadUrl(hash: string): Promise<DownloadUrlResponse>;
|
|
124
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* PUT bytes to a presigned URL. Throws on non-2xx — except 409, which
|
|
132
|
+
* means the content-addressed object is already stored (same hash = same
|
|
133
|
+
* bytes). That's idempotent success, not a conflict: two files with
|
|
134
|
+
* identical content (e.g. several empty files), or an initial upload that
|
|
135
|
+
* overlaps the daemon's first scan, race to PUT the same key. Treating
|
|
136
|
+
* 409 as fatal aborts the whole push and wedges sync at "N pending".
|
|
137
|
+
*/
|
|
125
138
|
putObjectBytes(uploadUrl: string, bytes: Uint8Array | Buffer): Promise<void>;
|
|
126
139
|
/** GET bytes from a presigned URL. Throws on non-2xx. */
|
|
127
140
|
getObjectBytes(downloadUrl: string): Promise<Buffer>;
|
|
@@ -414,6 +427,19 @@ declare function conflictSidecarPath(path: string, ev: {
|
|
|
414
427
|
id: string;
|
|
415
428
|
actorDeviceId: string | null;
|
|
416
429
|
}): string;
|
|
430
|
+
/**
|
|
431
|
+
* Apply mode.
|
|
432
|
+
*
|
|
433
|
+
* - `primary`: the local copy has write authority. Local-divergence
|
|
434
|
+
* guards protect unpushed edits (sidecars, keep-on-delete, refuse to
|
|
435
|
+
* clobber a dir) on the assumption scanAndPush carries them upstream.
|
|
436
|
+
* - `mirror`: a read-only import of another binding. The mount has no
|
|
437
|
+
* local authority, so **remote always wins** across every event type —
|
|
438
|
+
* every divergence guard flips to remote-authoritative. There is no
|
|
439
|
+
* scanAndPush to drain sidecars or re-submit kept files, so the primary
|
|
440
|
+
* guards would instead let edited imported content linger forever.
|
|
441
|
+
*/
|
|
442
|
+
type ApplyMode = "primary" | "mirror";
|
|
417
443
|
type ApplyEventError = {
|
|
418
444
|
eventId: string;
|
|
419
445
|
path: string;
|
|
@@ -443,6 +469,8 @@ declare function applyOnce(opts: {
|
|
|
443
469
|
client: RelayClient;
|
|
444
470
|
stateDb: StateDb;
|
|
445
471
|
limit?: number;
|
|
472
|
+
/** Defaults to "primary". See ApplyMode. */
|
|
473
|
+
mode?: ApplyMode;
|
|
446
474
|
}): Promise<ApplyResult>;
|
|
447
475
|
|
|
448
476
|
/**
|
|
@@ -473,8 +501,260 @@ declare function scanAndPush(opts: {
|
|
|
473
501
|
client: RelayClient;
|
|
474
502
|
stateDb: StateDb;
|
|
475
503
|
ignore: Ignore;
|
|
504
|
+
/** Import mount points to hard-exclude from the scan. See walk(). */
|
|
505
|
+
excludePaths?: ReadonlyArray<string>;
|
|
476
506
|
}): Promise<ScanAndPushResult>;
|
|
477
507
|
|
|
508
|
+
/**
|
|
509
|
+
* Rig imports — read-only live mirrors of another binding into a
|
|
510
|
+
* subdirectory (see ~/Code/rig/docs/rig-imports.md).
|
|
511
|
+
*
|
|
512
|
+
* This module owns the *declaration* side: the ImportSpec shape, on-disk
|
|
513
|
+
* path helpers, and the security-critical validator. The daemon wiring
|
|
514
|
+
* (mirror subscriptions, orchestration) lives in start.ts; the
|
|
515
|
+
* apply-time behavior (remote-wins) lives in applier.ts (mode: "mirror").
|
|
516
|
+
*
|
|
517
|
+
* The validator is the single highest-risk part of the feature: a bad
|
|
518
|
+
* mount point is how an import could silently re-share — or, because
|
|
519
|
+
* mirror mode is remote-authoritative, destroy — primary content. Treat
|
|
520
|
+
* every rule here as security code, not input hygiene.
|
|
521
|
+
*/
|
|
522
|
+
type ImportSpec = {
|
|
523
|
+
/** Boring slug — becomes the token filename + state-db dir name. */
|
|
524
|
+
name: string;
|
|
525
|
+
bindingId: string;
|
|
526
|
+
relayUrl: string;
|
|
527
|
+
/** Per-import capability token (read + subscribe). Machine-local. */
|
|
528
|
+
token: string;
|
|
529
|
+
/** Mount point: subdirectory relative to the rig root (posix). */
|
|
530
|
+
path: string;
|
|
531
|
+
};
|
|
532
|
+
/**
|
|
533
|
+
* On-disk shape of a per-import mount file
|
|
534
|
+
* (`.rig/tap/imports/<name>.local.json`). Machine-local, gitignored,
|
|
535
|
+
* never synced — mirrors `tap-binding.local.json`. Carries the capability
|
|
536
|
+
* secret plus enough to start a mirror subscription without parsing
|
|
537
|
+
* `rig.toml` (tapd has no TOML parser; the daemon reads JSON like it does
|
|
538
|
+
* for the primary binding). `ops` is persisted from the accept-invite
|
|
539
|
+
* response so the daemon can refuse a token that lacks read+subscribe.
|
|
540
|
+
*/
|
|
541
|
+
type ImportMountFile = {
|
|
542
|
+
bindingId: string;
|
|
543
|
+
relayUrl: string;
|
|
544
|
+
token: string;
|
|
545
|
+
ops: ReadonlyArray<"read" | "write" | "subscribe">;
|
|
546
|
+
/** Mount point: subdirectory relative to the rig root (posix). */
|
|
547
|
+
path: string;
|
|
548
|
+
/** Import-edge id from the relay (inter-rig graph). Lets `rig import remove`
|
|
549
|
+
* tombstone the exact edge. Absent for anonymous imports / pre-edge mounts. */
|
|
550
|
+
edgeId?: string;
|
|
551
|
+
};
|
|
552
|
+
type ImportValidationError = {
|
|
553
|
+
name: string;
|
|
554
|
+
path: string;
|
|
555
|
+
reason: string;
|
|
556
|
+
};
|
|
557
|
+
declare function validateImportName(name: string): string | null;
|
|
558
|
+
/**
|
|
559
|
+
* Canonicalize a declared import path to a posix form with `.` and empty
|
|
560
|
+
* segments collapsed (`./sources/alex` and `sources/./alex` → `sources/alex`).
|
|
561
|
+
* `..` is deliberately preserved so validateImportPath can reject it. This
|
|
562
|
+
* canonical form is what the daemon uses for BOTH the mirror root and the
|
|
563
|
+
* primary writer's exclude set — they must be byte-identical or a mirror
|
|
564
|
+
* could materialize at `sources/alex` while the writer excludes
|
|
565
|
+
* `./sources/alex` (which never matches walker paths) and re-uploads it.
|
|
566
|
+
*/
|
|
567
|
+
declare function normalizeImportPath(p: string): string;
|
|
568
|
+
/**
|
|
569
|
+
* Static + symlink validation of a single mount point. Returns a reason
|
|
570
|
+
* string on rejection, or null if the path is a legal mount.
|
|
571
|
+
*
|
|
572
|
+
* The mount may not exist on disk yet (first materialization hasn't
|
|
573
|
+
* run), so we can't realpath the full path. Instead we realpath the
|
|
574
|
+
* nearest existing ancestor and re-attach the not-yet-created remainder,
|
|
575
|
+
* then assert the result stays inside the (realpathed) rig root. This
|
|
576
|
+
* catches a symlinked ancestor that escapes the root even before the
|
|
577
|
+
* mount dir exists.
|
|
578
|
+
*/
|
|
579
|
+
declare function validateImportPath(rootDir: string, importPath: string): string | null;
|
|
580
|
+
/**
|
|
581
|
+
* Validate a batch of imports against each other and against the
|
|
582
|
+
* primary's already-tracked content. Never throws — returns the imports
|
|
583
|
+
* that passed plus a structured error per rejection, so the orchestrator
|
|
584
|
+
* can degrade a bad mount without taking down the daemon.
|
|
585
|
+
*/
|
|
586
|
+
declare function validateImports(opts: {
|
|
587
|
+
rootDir: string;
|
|
588
|
+
imports: ReadonlyArray<ImportSpec>;
|
|
589
|
+
/** Paths the primary binding already tracks (state-db listPaths). */
|
|
590
|
+
primaryTrackedPaths: ReadonlyArray<string>;
|
|
591
|
+
}): {
|
|
592
|
+
valid: ImportSpec[];
|
|
593
|
+
errors: ImportValidationError[];
|
|
594
|
+
};
|
|
595
|
+
/** `.rig/tap/state.local.db` — the primary binding's cursor/state. */
|
|
596
|
+
declare function primaryStateDbPath(rootDir: string): string;
|
|
597
|
+
/** `.rig/tap/imports/<name>/state.local.db` — per-import cursor/state. */
|
|
598
|
+
declare function importStateDbPath(rootDir: string, name: string): string;
|
|
599
|
+
/** `.rig/tap/imports` — holds `<name>.local.json` token files + `<name>/` state dirs. */
|
|
600
|
+
declare function importsDir(rootDir: string): string;
|
|
601
|
+
/** `.rig/tap/imports/<name>.local.json` — per-import token file. */
|
|
602
|
+
declare function importMountFile(rootDir: string, name: string): string;
|
|
603
|
+
declare function writeImportMount(rootDir: string, name: string, mount: ImportMountFile): void;
|
|
604
|
+
/**
|
|
605
|
+
* Read + validate a single mount file. Returns the spec on success or a
|
|
606
|
+
* structured reason on failure — never throws, so one broken mount can be
|
|
607
|
+
* degraded without taking down the daemon (gotcha #7).
|
|
608
|
+
*/
|
|
609
|
+
declare function readImportMount(rootDir: string, name: string): {
|
|
610
|
+
ok: true;
|
|
611
|
+
spec: ImportSpec;
|
|
612
|
+
} | {
|
|
613
|
+
ok: false;
|
|
614
|
+
reason: string;
|
|
615
|
+
};
|
|
616
|
+
/**
|
|
617
|
+
* Enumerate `.rig/tap/imports/*.local.json` and resolve each to an
|
|
618
|
+
* ImportSpec. Broken mount files are reported, not thrown. This is the
|
|
619
|
+
* daemon's source of truth for which mirrors to run — read fresh at every
|
|
620
|
+
* `tapd start` (v1 "reload" = restart).
|
|
621
|
+
*/
|
|
622
|
+
declare function loadImportMounts(rootDir: string): {
|
|
623
|
+
ready: ImportSpec[];
|
|
624
|
+
broken: ImportValidationError[];
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* A single binding's apply loop: SSE subscriber + poll fallback +
|
|
629
|
+
* apply-mutex → applyOnce. This is the "download direction" of the
|
|
630
|
+
* daemon, extracted from start.ts so it can run N times — once for the
|
|
631
|
+
* primary binding (mode "primary") and once per import (mode "mirror").
|
|
632
|
+
*
|
|
633
|
+
* It does NOT own the watcher or scanAndPush — that "upload direction"
|
|
634
|
+
* stays attached only to the primary binding, in start.ts. A mirror is a
|
|
635
|
+
* degenerate daemon: apply-only, no uploader.
|
|
636
|
+
*
|
|
637
|
+
* Each subscription owns its own state DB (separate cursor per binding)
|
|
638
|
+
* and its own RelayClient. stop() closes the state DB, so the caller
|
|
639
|
+
* must stop any writer that shares it FIRST.
|
|
640
|
+
*/
|
|
641
|
+
|
|
642
|
+
/** Minimal connection config — the apply side never needs deviceId. */
|
|
643
|
+
type SubscriptionConfig = {
|
|
644
|
+
bindingId: string;
|
|
645
|
+
relayUrl: string;
|
|
646
|
+
token: string;
|
|
647
|
+
};
|
|
648
|
+
type SubscriptionHandle = {
|
|
649
|
+
/** Stop SSE + poll, drain the in-flight apply, then close the state DB. */
|
|
650
|
+
stop(): Promise<void>;
|
|
651
|
+
/** Force one apply cycle now (through the mutex). */
|
|
652
|
+
applyNow(): Promise<ApplyResult>;
|
|
653
|
+
/** Underlying state DB. Caller MUST NOT close it — stop() does. */
|
|
654
|
+
stateDb: StateDb;
|
|
655
|
+
};
|
|
656
|
+
type StartSubscriptionOptions = {
|
|
657
|
+
/** Directory this binding materializes into (primary root, or a mount subdir). */
|
|
658
|
+
rootDir: string;
|
|
659
|
+
config: SubscriptionConfig;
|
|
660
|
+
/** Separate db per binding → separate cursor. */
|
|
661
|
+
stateDbPath: string;
|
|
662
|
+
mode: ApplyMode;
|
|
663
|
+
fetch?: typeof fetch;
|
|
664
|
+
pollSeconds?: number;
|
|
665
|
+
/** Test seam — disable SSE (poll-only). */
|
|
666
|
+
noSse?: boolean;
|
|
667
|
+
sseHeartbeatTimeoutMs?: number;
|
|
668
|
+
};
|
|
669
|
+
declare function startSubscription(opts: StartSubscriptionOptions): Promise<SubscriptionHandle>;
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* `tapd import` — accept an invite to another binding and mount it
|
|
673
|
+
* read-only into a subdirectory of this rig (see rig-imports.md).
|
|
674
|
+
*
|
|
675
|
+
* Mirror of `join.ts`, but instead of making this folder a binding root
|
|
676
|
+
* it writes a per-import mount file (`.rig/tap/imports/<name>.local.json`)
|
|
677
|
+
* that the daemon picks up as a mirror subscription. Nothing about the
|
|
678
|
+
* primary binding (if any) changes.
|
|
679
|
+
*
|
|
680
|
+
* 1. Canonicalize + validate the mount (name slug, path, symlink/parent
|
|
681
|
+
* collisions, overlap with other mounts + primary content) BEFORE any
|
|
682
|
+
* network call — reusing validateImports so the rules can't drift.
|
|
683
|
+
* 2. Parse the invite URL → (baseUrl, secret).
|
|
684
|
+
* 3. acceptInvite → { bindingId, token: { secret, ops } }.
|
|
685
|
+
* 4. Refuse a token without read+subscribe (a mirror can't run on it).
|
|
686
|
+
* 5. Write the mount file (mode 0600). The daemon must be (re)started to
|
|
687
|
+
* pick it up — v1 "reload" = restart.
|
|
688
|
+
*/
|
|
689
|
+
declare class ImportValidationFailed extends Error {
|
|
690
|
+
readonly reason: string;
|
|
691
|
+
constructor(reason: string);
|
|
692
|
+
}
|
|
693
|
+
declare class ImportTokenScopeError extends Error {
|
|
694
|
+
readonly ops?: ReadonlyArray<string> | undefined;
|
|
695
|
+
constructor(ops?: ReadonlyArray<string> | undefined);
|
|
696
|
+
}
|
|
697
|
+
type AddImportOptions = {
|
|
698
|
+
rootDir: string;
|
|
699
|
+
inviteUrl: string;
|
|
700
|
+
/** Mount point (subdir, relative to the rig root). */
|
|
701
|
+
path: string;
|
|
702
|
+
/** Slug; defaults to the last path segment. */
|
|
703
|
+
name?: string;
|
|
704
|
+
accessToken?: string | null;
|
|
705
|
+
deviceLabel?: string;
|
|
706
|
+
fetch?: typeof fetch;
|
|
707
|
+
};
|
|
708
|
+
type AddImportResult = {
|
|
709
|
+
name: string;
|
|
710
|
+
path: string;
|
|
711
|
+
bindingId: string;
|
|
712
|
+
ops: ReadonlyArray<"read" | "write" | "subscribe">;
|
|
713
|
+
/** Import-edge id recorded by the relay (absent for anonymous imports). */
|
|
714
|
+
edgeId?: string;
|
|
715
|
+
/** False when we sent our binding as the importer but the relay couldn't
|
|
716
|
+
* verify membership — the edge was recorded as a personal import (you → S),
|
|
717
|
+
* not rig → S. The CLI surfaces this as a warning. Undefined when we sent no
|
|
718
|
+
* binding (import-only) or no edge was recorded. */
|
|
719
|
+
importerBindingVerified?: boolean;
|
|
720
|
+
};
|
|
721
|
+
declare function addImport(opts: AddImportOptions): Promise<AddImportResult>;
|
|
722
|
+
/**
|
|
723
|
+
* Outcome of the best-effort server-side revoke half of a remove:
|
|
724
|
+
* - revoked — edge tombstoned + token revoked on the relay
|
|
725
|
+
* - not-creator — 403: the grant belongs to another user; left active
|
|
726
|
+
* - gone — 404: already revoked/removed server-side
|
|
727
|
+
* - no-edge — anonymous / pre-edge mount; nothing to revoke
|
|
728
|
+
* - no-token — not logged in; can't reach the user plane (local-only)
|
|
729
|
+
* - offline — relay unreachable / unexpected error
|
|
730
|
+
*/
|
|
731
|
+
type RemoveImportRevoke = "revoked" | "not-creator" | "gone" | "no-edge" | "no-token" | "offline";
|
|
732
|
+
type RemoveImportResult = {
|
|
733
|
+
/** False if there was no mount file by that name. */
|
|
734
|
+
removed: boolean;
|
|
735
|
+
/** The mount point that was removed (for an optional purge), if known. */
|
|
736
|
+
path: string | null;
|
|
737
|
+
/** Whether the materialized subdir was deleted (--purge). */
|
|
738
|
+
purged: boolean;
|
|
739
|
+
/** What happened to the server-side grant. */
|
|
740
|
+
revoke: RemoveImportRevoke;
|
|
741
|
+
};
|
|
742
|
+
/**
|
|
743
|
+
* Remove a mount: relinquish the grant on the relay (best-effort), then delete
|
|
744
|
+
* the local token file + per-import state dir. With `purge`, also delete the
|
|
745
|
+
* materialized subdir. The local removal ALWAYS happens — even offline, even
|
|
746
|
+
* when the grant isn't ours — so the daemon stops mirroring locally. The
|
|
747
|
+
* caller restarts the daemon. See docs/inter-rig-graph.md §7.
|
|
748
|
+
*/
|
|
749
|
+
declare function removeImport(opts: {
|
|
750
|
+
rootDir: string;
|
|
751
|
+
name: string;
|
|
752
|
+
purge?: boolean;
|
|
753
|
+
/** Hub token for the self-revoke. Omit → local-only ("no-token"). */
|
|
754
|
+
accessToken?: string | null;
|
|
755
|
+
fetch?: typeof fetch;
|
|
756
|
+
}): Promise<RemoveImportResult>;
|
|
757
|
+
|
|
478
758
|
/**
|
|
479
759
|
* SSE consumer for the relay's /stream endpoint.
|
|
480
760
|
*
|
|
@@ -518,21 +798,24 @@ type SseSubscriber = {
|
|
|
518
798
|
declare function subscribe(opts: SseSubscriberOptions): SseSubscriber;
|
|
519
799
|
|
|
520
800
|
/**
|
|
521
|
-
* `tapd start` — the daemon
|
|
801
|
+
* `tapd start` — the daemon orchestrator.
|
|
802
|
+
*
|
|
803
|
+
* A daemon = N subscriptions (apply loops) + 1 writer (watcher + scan).
|
|
804
|
+
* - The **primary** binding gets a subscription (mode "primary") AND
|
|
805
|
+
* the writer: chokidar → debounced `scanAndPush` pushes local diffs
|
|
806
|
+
* upstream.
|
|
807
|
+
* - Each **import** gets an apply-only subscription (mode "mirror")
|
|
808
|
+
* materializing another binding into a subdirectory, read-only. No
|
|
809
|
+
* writer — a mirror never pushes.
|
|
522
810
|
*
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
* download time, not pollSeconds.
|
|
527
|
-
* - poll loop: every `pollSeconds`, runs applyOnce as a fallback
|
|
528
|
-
* for SSE outages (and for multi-relay deployments where the SSE
|
|
529
|
-
* bus is single-process; see relay's event-bus.ts).
|
|
530
|
-
* - watcher: chokidar emits add / change / unlink / addDir / unlinkDir.
|
|
531
|
-
* Debounced rescan calls `scanAndPush` so file diffs flow upstream.
|
|
811
|
+
* The subscription machinery (SSE + poll + apply-mutex) lives in
|
|
812
|
+
* subscription.ts; this file wires the pieces together and owns the
|
|
813
|
+
* primary writer.
|
|
532
814
|
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
815
|
+
* Critical invariant: import mount points are HARD-excluded from the
|
|
816
|
+
* primary writer (watcher `ignored` + walker `excludePaths`), so a
|
|
817
|
+
* mirrored subtree is never re-uploaded into the primary's own binding
|
|
818
|
+
* — the "accidental re-share".
|
|
536
819
|
*/
|
|
537
820
|
|
|
538
821
|
type StartOptions = {
|
|
@@ -540,6 +823,13 @@ type StartOptions = {
|
|
|
540
823
|
pollSeconds?: number;
|
|
541
824
|
/** Quiescence window before the watcher triggers a rescan. */
|
|
542
825
|
debounceMs?: number;
|
|
826
|
+
/**
|
|
827
|
+
* Read-only imports to mount into subdirectories. When omitted, the
|
|
828
|
+
* daemon loads them from `.rig/tap/imports/*.local.json` (the normal
|
|
829
|
+
* path). Pass explicitly to bypass disk loading (tests / programmatic).
|
|
830
|
+
* Each carries its own binding + capability token.
|
|
831
|
+
*/
|
|
832
|
+
imports?: ReadonlyArray<ImportSpec>;
|
|
543
833
|
/** Test seam — override fetch (passed to RelayClient + SSE subscriber). */
|
|
544
834
|
fetch?: typeof fetch;
|
|
545
835
|
/** Test seam — disable the chokidar watcher (poll loop only). */
|
|
@@ -549,16 +839,25 @@ type StartOptions = {
|
|
|
549
839
|
/** SSE watchdog window in ms. Default 45s. */
|
|
550
840
|
sseHeartbeatTimeoutMs?: number;
|
|
551
841
|
};
|
|
842
|
+
/** A live import mount — exposed for status + tests. */
|
|
843
|
+
type ImportHandle = {
|
|
844
|
+
name: string;
|
|
845
|
+
path: string;
|
|
846
|
+
applyNow(): Promise<ApplyResult>;
|
|
847
|
+
stateDb: StateDb;
|
|
848
|
+
};
|
|
552
849
|
type DaemonHandle = {
|
|
553
|
-
/** Cleanly shut down the
|
|
850
|
+
/** Cleanly shut down the writer + every subscription + close state DBs. */
|
|
554
851
|
stop(): Promise<void>;
|
|
555
|
-
/** Force one apply cycle now.
|
|
852
|
+
/** Force one primary apply cycle now. No-op for an import-only daemon. */
|
|
556
853
|
applyNow(): Promise<ApplyResult>;
|
|
557
|
-
/** Force one upstream scan+push now.
|
|
854
|
+
/** Force one upstream scan+push now. No-op for an import-only daemon. */
|
|
558
855
|
scanNow(): Promise<ScanAndPushResult>;
|
|
559
|
-
/**
|
|
856
|
+
/** Primary state DB (or first mount's, if import-only). Do NOT close it. */
|
|
560
857
|
stateDb: StateDb;
|
|
858
|
+
/** Live import mounts, in declaration order (valid ones only). */
|
|
859
|
+
imports: ImportHandle[];
|
|
561
860
|
};
|
|
562
861
|
declare function start(opts: StartOptions): Promise<DaemonHandle>;
|
|
563
862
|
|
|
564
|
-
export { AlreadyInitializedError, AlreadyJoinedError, type ApplyResult, BINDING_CONFIG_PATH, BUILTIN_IGNORE_LINES, type BindingConfig, type DaemonHandle, type InitOptions, type InitResult, InvalidInviteUrlError, type JoinOptions, type JoinResult, type LocalPathState, type MintInviteOptions, NotInitializedError, RelayClient, type RelayClientOptions, RelayError, STATE_KEY_CONFLICT_COUNT, type ScanAndPushResult, type SseSubscriber, type SseSubscriberOptions, type StartOptions, type StateDb, type WalkFile, type WalkResult, type WalkWarning, applyOnce, bindingConfigFile, conflictSidecarPath, createBinding, hashFile, init, isAlwaysExcluded, join, list as listInvites, loadIgnore, mint as mintInvite, openStateDb, parseInviteUrl, readBindingConfig, revoke as revokeInvite, scanAndPush, subscribe as sseSubscribe, start, walk, writeBindingConfig };
|
|
863
|
+
export { type AddImportOptions, type AddImportResult, AlreadyInitializedError, AlreadyJoinedError, type ApplyMode, type ApplyResult, BINDING_CONFIG_PATH, BUILTIN_IGNORE_LINES, type BindingConfig, type DaemonHandle, type ImportHandle, type ImportMountFile, type ImportSpec, ImportTokenScopeError, type ImportValidationError, ImportValidationFailed, type InitOptions, type InitResult, InvalidInviteUrlError, type JoinOptions, type JoinResult, type LocalPathState, type MintInviteOptions, NotInitializedError, RelayClient, type RelayClientOptions, RelayError, type RemoveImportResult, STATE_KEY_CONFLICT_COUNT, type ScanAndPushResult, type SseSubscriber, type SseSubscriberOptions, type StartOptions, type StartSubscriptionOptions, type StateDb, type SubscriptionConfig, type SubscriptionHandle, type WalkFile, type WalkResult, type WalkWarning, addImport, applyOnce, bindingConfigFile, conflictSidecarPath, createBinding, hashFile, importMountFile, importStateDbPath, importsDir, init, isAlwaysExcluded, join, list as listInvites, loadIgnore, loadImportMounts, mint as mintInvite, normalizeImportPath, openStateDb, parseInviteUrl, primaryStateDbPath, readBindingConfig, readImportMount, removeImport, revoke as revokeInvite, scanAndPush, subscribe as sseSubscribe, start, startSubscription, validateImportName, validateImportPath, validateImports, walk, writeBindingConfig, writeImportMount };
|
package/dist/index.js
CHANGED
|
@@ -4,61 +4,93 @@ import {
|
|
|
4
4
|
AlreadyJoinedError,
|
|
5
5
|
BINDING_CONFIG_PATH,
|
|
6
6
|
BUILTIN_IGNORE_LINES,
|
|
7
|
+
ImportTokenScopeError,
|
|
8
|
+
ImportValidationFailed,
|
|
7
9
|
InvalidInviteUrlError,
|
|
8
10
|
NotInitializedError,
|
|
9
11
|
RelayClient,
|
|
10
12
|
RelayError,
|
|
11
13
|
STATE_KEY_CONFLICT_COUNT,
|
|
14
|
+
addImport,
|
|
12
15
|
applyOnce,
|
|
13
16
|
bindingConfigFile,
|
|
14
17
|
conflictSidecarPath,
|
|
15
18
|
createBinding,
|
|
16
19
|
hashFile,
|
|
20
|
+
importMountFile,
|
|
21
|
+
importStateDbPath,
|
|
22
|
+
importsDir,
|
|
17
23
|
init,
|
|
18
24
|
isAlwaysExcluded,
|
|
19
25
|
join,
|
|
20
26
|
list,
|
|
21
27
|
loadIgnore,
|
|
28
|
+
loadImportMounts,
|
|
22
29
|
mint,
|
|
30
|
+
normalizeImportPath,
|
|
23
31
|
openStateDb,
|
|
24
32
|
parseInviteUrl,
|
|
33
|
+
primaryStateDbPath,
|
|
25
34
|
readBindingConfig,
|
|
35
|
+
readImportMount,
|
|
36
|
+
removeImport,
|
|
26
37
|
revoke,
|
|
27
38
|
scanAndPush,
|
|
28
39
|
start,
|
|
40
|
+
startSubscription,
|
|
29
41
|
subscribe,
|
|
42
|
+
validateImportName,
|
|
43
|
+
validateImportPath,
|
|
44
|
+
validateImports,
|
|
30
45
|
walk,
|
|
31
|
-
writeBindingConfig
|
|
32
|
-
|
|
46
|
+
writeBindingConfig,
|
|
47
|
+
writeImportMount
|
|
48
|
+
} from "./chunk-JBX2ZRMD.js";
|
|
33
49
|
export {
|
|
34
50
|
AlreadyInitializedError,
|
|
35
51
|
AlreadyJoinedError,
|
|
36
52
|
BINDING_CONFIG_PATH,
|
|
37
53
|
BUILTIN_IGNORE_LINES,
|
|
54
|
+
ImportTokenScopeError,
|
|
55
|
+
ImportValidationFailed,
|
|
38
56
|
InvalidInviteUrlError,
|
|
39
57
|
NotInitializedError,
|
|
40
58
|
RelayClient,
|
|
41
59
|
RelayError,
|
|
42
60
|
STATE_KEY_CONFLICT_COUNT,
|
|
61
|
+
addImport,
|
|
43
62
|
applyOnce,
|
|
44
63
|
bindingConfigFile,
|
|
45
64
|
conflictSidecarPath,
|
|
46
65
|
createBinding,
|
|
47
66
|
hashFile,
|
|
67
|
+
importMountFile,
|
|
68
|
+
importStateDbPath,
|
|
69
|
+
importsDir,
|
|
48
70
|
init,
|
|
49
71
|
isAlwaysExcluded,
|
|
50
72
|
join,
|
|
51
73
|
list as listInvites,
|
|
52
74
|
loadIgnore,
|
|
75
|
+
loadImportMounts,
|
|
53
76
|
mint as mintInvite,
|
|
77
|
+
normalizeImportPath,
|
|
54
78
|
openStateDb,
|
|
55
79
|
parseInviteUrl,
|
|
80
|
+
primaryStateDbPath,
|
|
56
81
|
readBindingConfig,
|
|
82
|
+
readImportMount,
|
|
83
|
+
removeImport,
|
|
57
84
|
revoke as revokeInvite,
|
|
58
85
|
scanAndPush,
|
|
59
86
|
subscribe as sseSubscribe,
|
|
60
87
|
start,
|
|
88
|
+
startSubscription,
|
|
89
|
+
validateImportName,
|
|
90
|
+
validateImportPath,
|
|
91
|
+
validateImports,
|
|
61
92
|
walk,
|
|
62
|
-
writeBindingConfig
|
|
93
|
+
writeBindingConfig,
|
|
94
|
+
writeImportMount
|
|
63
95
|
};
|
|
64
96
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigxyz/tapd",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Local daemon for the hosted Tap relay — watches files, hashes content, uploads/downloads objects, applies remote changes. Pairs with @rigxyz/cli for shared-rig sync.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Dylan Bourgeois <dtsbourg@gmail.com>",
|
|
@@ -29,6 +29,13 @@
|
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsup",
|
|
34
|
+
"dev": "tsup --watch",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"test:watch": "vitest"
|
|
38
|
+
},
|
|
32
39
|
"dependencies": {
|
|
33
40
|
"better-sqlite3": "^11.5.0",
|
|
34
41
|
"chokidar": "^4.0.1",
|
|
@@ -36,20 +43,13 @@
|
|
|
36
43
|
"kleur": "^4.1.5"
|
|
37
44
|
},
|
|
38
45
|
"devDependencies": {
|
|
46
|
+
"@tap/core": "workspace:*",
|
|
47
|
+
"@tap/relay": "workspace:*",
|
|
39
48
|
"@types/better-sqlite3": "^7.6.12",
|
|
40
49
|
"@types/pg": "^8.20.0",
|
|
41
50
|
"pg": "^8.21.0",
|
|
42
51
|
"tsup": "^8.3.5",
|
|
43
52
|
"typescript": "^5.7.2",
|
|
44
|
-
"vitest": "^2.1.9"
|
|
45
|
-
"@tap/core": "0.1.0",
|
|
46
|
-
"@tap/relay": "0.1.0"
|
|
47
|
-
},
|
|
48
|
-
"scripts": {
|
|
49
|
-
"build": "tsup",
|
|
50
|
-
"dev": "tsup --watch",
|
|
51
|
-
"typecheck": "tsc --noEmit",
|
|
52
|
-
"test": "vitest run",
|
|
53
|
-
"test:watch": "vitest"
|
|
53
|
+
"vitest": "^2.1.9"
|
|
54
54
|
}
|
|
55
|
-
}
|
|
55
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Dylan Bourgeois
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|