@freqhole/api-client 0.1.30
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/auth-test.html +651 -0
- package/package.json +42 -0
- package/src/AdminClient.ts +154 -0
- package/src/CharnelLocalTransport.ts +598 -0
- package/src/CharnelTransport.ts +616 -0
- package/src/FreqholeClient.ts +261 -0
- package/src/WasmTransport.ts +1077 -0
- package/src/automerge/IrohNetworkAdapter.ts +727 -0
- package/src/automerge/index.ts +14 -0
- package/src/codegen/admin_commands.ts +61 -0
- package/src/codegen/routes.ts +213 -0
- package/src/codegen/schema.ts +6721 -0
- package/src/domains/admin.ts +97 -0
- package/src/domains/app.ts +98 -0
- package/src/domains/auth.ts +191 -0
- package/src/domains/favorites.types.ts +52 -0
- package/src/domains/jobs.ts +48 -0
- package/src/domains/music.ts +1935 -0
- package/src/domains/types.ts +19 -0
- package/src/domains/upload.ts +214 -0
- package/src/index.ts +48 -0
- package/src/permissions.ts +468 -0
- package/src/playlistz/convert.ts +267 -0
- package/src/playlistz/index.ts +6 -0
- package/src/playlistz/mutations.ts +181 -0
- package/src/playlistz/protocol.ts +222 -0
- package/src/playlistz/schema.ts +138 -0
- package/src/playlistz/shareLink.ts +76 -0
- package/src/storage/blobs.ts +272 -0
- package/src/storage/identity.ts +190 -0
- package/src/storage/index.ts +5 -0
- package/src/storage/webLocks.ts +92 -0
- package/src/test/automerge.ts +796 -0
- package/src/test/coverage.ts +105 -0
- package/src/test/fixtures.ts +460 -0
- package/src/test/integration.ts +320 -0
- package/src/test/playlistz.ts +631 -0
- package/src/test/stateful.ts +561 -0
- package/src/test/storage.ts +443 -0
- package/src/test.ts +75 -0
- package/src/transport.ts +391 -0
- package/src/utils.ts +79 -0
- package/src/webauthn.ts +228 -0
- package/tsconfig.json +22 -0
- package/vite.config.js +9 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// web locks leader election for the iroh node.
|
|
2
|
+
// only one tab per origin runs the midden node at a time.
|
|
3
|
+
|
|
4
|
+
/** lock name used for iroh node leader election */
|
|
5
|
+
export const LOCK_NAME = "freqhole-iroh-node";
|
|
6
|
+
|
|
7
|
+
export interface AcquireNodeLeadershipOpts {
|
|
8
|
+
/** called when this tab becomes the node leader */
|
|
9
|
+
onAcquired: () => void | Promise<void>;
|
|
10
|
+
/** called with state transitions; optional */
|
|
11
|
+
onStateChange?: (state: "leader" | "waiting" | "unsupported") => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* attempt to acquire exclusive leadership of the iroh node.
|
|
16
|
+
*
|
|
17
|
+
* behavior:
|
|
18
|
+
* - tries ifAvailable first; if the lock is free, holds it and calls onAcquired
|
|
19
|
+
* - if already held, reports "waiting" and queues a normal request with an AbortController
|
|
20
|
+
* so leadership transfers when the current leader tab closes
|
|
21
|
+
* - if navigator.locks is absent (e.g. non-secure context), reports "unsupported"
|
|
22
|
+
* and calls onAcquired immediately (single-tab fallback)
|
|
23
|
+
*
|
|
24
|
+
* returns a cancel/release function; call it to give up leadership or cancel the wait.
|
|
25
|
+
*/
|
|
26
|
+
export function acquireNodeLeadership(
|
|
27
|
+
opts: AcquireNodeLeadershipOpts,
|
|
28
|
+
): () => void {
|
|
29
|
+
const { onAcquired, onStateChange } = opts;
|
|
30
|
+
|
|
31
|
+
// single-tab fallback for environments without Web Locks
|
|
32
|
+
if (
|
|
33
|
+
typeof navigator === "undefined" ||
|
|
34
|
+
!navigator.locks
|
|
35
|
+
) {
|
|
36
|
+
onStateChange?.("unsupported");
|
|
37
|
+
void Promise.resolve().then(() => onAcquired());
|
|
38
|
+
return () => {};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let released = false;
|
|
42
|
+
// resolving this promise releases the held lock
|
|
43
|
+
let releaseLock: (() => void) | null = null;
|
|
44
|
+
// used to cancel the waiting queue request
|
|
45
|
+
const waitAbort = new AbortController();
|
|
46
|
+
|
|
47
|
+
function cancel() {
|
|
48
|
+
released = true;
|
|
49
|
+
waitAbort.abort();
|
|
50
|
+
releaseLock?.();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// try to grab the lock immediately without queuing
|
|
54
|
+
navigator.locks.request(
|
|
55
|
+
LOCK_NAME,
|
|
56
|
+
{ ifAvailable: true },
|
|
57
|
+
async (lock: Lock | null) => {
|
|
58
|
+
if (released) return;
|
|
59
|
+
|
|
60
|
+
if (lock !== null) {
|
|
61
|
+
// we are now the leader - call onAcquired, then hold the lock until released
|
|
62
|
+
onStateChange?.("leader");
|
|
63
|
+
await onAcquired();
|
|
64
|
+
await new Promise<void>((resolve) => {
|
|
65
|
+
releaseLock = resolve;
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
// another tab holds the lock - queue up for leadership
|
|
69
|
+
onStateChange?.("waiting");
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
await navigator.locks.request(
|
|
73
|
+
LOCK_NAME,
|
|
74
|
+
{ signal: waitAbort.signal },
|
|
75
|
+
async () => {
|
|
76
|
+
if (released) return;
|
|
77
|
+
onStateChange?.("leader");
|
|
78
|
+
await onAcquired();
|
|
79
|
+
await new Promise<void>((resolve) => {
|
|
80
|
+
releaseLock = resolve;
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
} catch {
|
|
85
|
+
// aborted by cancel() or context destroyed - not an error
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
return cancel;
|
|
92
|
+
}
|