@camera.ui/transport 0.0.30 → 0.1.0
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/closeCodes-CltSRjdJ.js +30 -0
- package/dist/core/types.d.ts +1 -0
- package/dist/effects/backgroundProbe.d.ts +1 -0
- package/dist/effects/crossTab.d.ts +6 -0
- package/dist/effects/degradedRecovery.d.ts +1 -0
- package/dist/effects/persistence.d.ts +2 -0
- package/dist/effects/probeLoop.d.ts +1 -0
- package/dist/effects/tokenLifecycle.d.ts +8 -3
- package/dist/effects/workerBridge.d.ts +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +378 -82
- package/dist/signal.d.ts +2 -0
- package/dist/testing/fakeTransport.d.ts +2 -1
- package/dist/testing.js +7 -3
- package/dist/transports/closeCodes.d.ts +2 -0
- package/dist/transports/contract.d.ts +2 -0
- package/dist/transports/http.js +31 -14
- package/dist/transports/nativeHttp.d.ts +3 -1
- package/dist/transports/nativeHttp.js +118 -14
- package/dist/transports/nats.js +185 -86
- package/dist/transports/socketio.d.ts +4 -1
- package/dist/transports/socketio.js +168 -67
- package/dist/transports/ws.d.ts +0 -1
- package/dist/transports/ws.js +39 -13
- package/package.json +14 -13
- package/dist/closeCodes-ClWJVOpq.js +0 -14
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/transports/closeCodes.ts
|
|
2
|
+
function classifyErrorCode(code) {
|
|
3
|
+
if (code === "insufficient_role" || code === "user_not_found") return "forbidden";
|
|
4
|
+
if (code === "invalid_token" || code === "unauthenticated" || code.startsWith("credentials_")) return "auth-expired";
|
|
5
|
+
}
|
|
6
|
+
function classifyClose(input) {
|
|
7
|
+
const obj = typeof input === "string" ? void 0 : input;
|
|
8
|
+
const code = obj?.wsCloseCode ?? obj?.code;
|
|
9
|
+
if (code === 4401) return "auth-expired";
|
|
10
|
+
if (code === 4403 || code === 4400) return "forbidden";
|
|
11
|
+
const errorCode = typeof obj?.data === "object" && obj.data !== null ? obj.data.code : void 0;
|
|
12
|
+
const byErrorCode = typeof errorCode === "string" ? classifyErrorCode(errorCode) : void 0;
|
|
13
|
+
if (byErrorCode) return byErrorCode;
|
|
14
|
+
const text = (typeof input === "string" ? input : obj?.reason ?? obj?.message ?? "").toLowerCase();
|
|
15
|
+
if (!text) return "other";
|
|
16
|
+
if (text.includes("forbidden") || text.includes("403")) return "forbidden";
|
|
17
|
+
if (text.includes("unauthorized") || text.includes("unauthenticated") || text.includes("401")) return "auth-expired";
|
|
18
|
+
return "other";
|
|
19
|
+
}
|
|
20
|
+
function refusedByServer(input) {
|
|
21
|
+
if (typeof input !== "object" || input === null) return false;
|
|
22
|
+
const { wsCloseCode, code, data } = input;
|
|
23
|
+
return classifyClose({
|
|
24
|
+
wsCloseCode,
|
|
25
|
+
code,
|
|
26
|
+
data
|
|
27
|
+
}) === "forbidden";
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { refusedByServer as n, classifyClose as t };
|
package/dist/core/types.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export interface BackgroundProbeOptions {
|
|
|
13
13
|
readonly preferGraceMs?: number;
|
|
14
14
|
readonly isCurrentHealthy?: () => boolean;
|
|
15
15
|
readonly onResult?: (outcome: BackgroundProbeOutcome, detail?: string) => void;
|
|
16
|
+
readonly ready?: () => Promise<unknown>;
|
|
16
17
|
}
|
|
17
18
|
export interface BackgroundProbe {
|
|
18
19
|
run(): Promise<BackgroundProbeOutcome>;
|
|
@@ -3,12 +3,18 @@ import { ConnectionTarget } from '../core/types.js';
|
|
|
3
3
|
export type Detach = () => void;
|
|
4
4
|
export interface CrossTabSource extends EventTarget {
|
|
5
5
|
}
|
|
6
|
+
export interface CrossTabPayload {
|
|
7
|
+
readonly endpoint?: ConnectionTarget['endpoint'];
|
|
8
|
+
readonly tokens: ConnectionTarget['tokens'];
|
|
9
|
+
}
|
|
6
10
|
export interface CrossTabOptions {
|
|
7
11
|
readonly kernel: Kernel;
|
|
8
12
|
readonly key?: string;
|
|
9
13
|
readonly source?: CrossTabSource;
|
|
14
|
+
readonly accept?: (payload: CrossTabPayload, current: ConnectionTarget | null) => boolean;
|
|
10
15
|
readonly absorb?: (target: ConnectionTarget | null) => void;
|
|
11
16
|
readonly onTokensReceived?: (tokens: ConnectionTarget['tokens']) => void;
|
|
17
|
+
readonly onTokensIgnored?: (payload: CrossTabPayload) => void;
|
|
12
18
|
readonly onResetReceived?: () => void;
|
|
13
19
|
readonly onError?: (op: 'parse', err: unknown) => void;
|
|
14
20
|
}
|
|
@@ -8,6 +8,7 @@ export interface DegradedRecoveryOptions {
|
|
|
8
8
|
readonly ensureAll: () => void;
|
|
9
9
|
readonly probe: () => Promise<BackgroundProbeOutcome>;
|
|
10
10
|
readonly graceMs?: number;
|
|
11
|
+
readonly maxBackoffMs?: number;
|
|
11
12
|
readonly isReachable?: () => boolean;
|
|
12
13
|
readonly onEscalate?: (round: number) => void;
|
|
13
14
|
readonly onOffline?: (reason: string) => void;
|
|
@@ -14,6 +14,7 @@ export interface PersistedTarget {
|
|
|
14
14
|
}
|
|
15
15
|
export interface Persistence {
|
|
16
16
|
readonly detach: Detach;
|
|
17
|
+
readonly ready: Promise<void>;
|
|
17
18
|
peek(): ConnectionTarget | null;
|
|
18
19
|
seed(target: ConnectionTarget): Promise<void>;
|
|
19
20
|
absorb(target: ConnectionTarget | null): void;
|
|
@@ -26,6 +27,7 @@ export interface PersistenceOptions {
|
|
|
26
27
|
readonly onPersist?: (target: ConnectionTarget) => void;
|
|
27
28
|
readonly onClear?: () => void;
|
|
28
29
|
readonly onError?: (op: 'get' | 'set' | 'del' | 'parse', err: unknown) => void;
|
|
30
|
+
readonly readyTimeoutMs?: number;
|
|
29
31
|
}
|
|
30
32
|
export declare function attachPersistence(options: PersistenceOptions): Persistence;
|
|
31
33
|
export declare function localStorageAdapter(scope?: Storage): StorageAdapter;
|
|
@@ -28,5 +28,6 @@ export interface ProbeLoopOptions {
|
|
|
28
28
|
readonly onProbeError?: (endpoint: Endpoint, err: unknown) => void;
|
|
29
29
|
readonly onAllFailed?: (reason: string) => void;
|
|
30
30
|
readonly lastTarget?: () => ConnectionTarget | null;
|
|
31
|
+
readonly ready?: () => Promise<unknown>;
|
|
31
32
|
}
|
|
32
33
|
export declare function attachProbeLoop(options: ProbeLoopOptions): Detach;
|
|
@@ -9,13 +9,17 @@ export interface TokenLifecycleOptions {
|
|
|
9
9
|
readonly maxTransientRetries?: number;
|
|
10
10
|
readonly transientRetryDelayMs?: number;
|
|
11
11
|
readonly maxServerErrorRetries?: number;
|
|
12
|
+
readonly minRefreshIntervalMs?: number;
|
|
13
|
+
readonly reachableRetryDelaysMs?: readonly number[];
|
|
14
|
+
readonly lockTimeoutMs?: number;
|
|
12
15
|
readonly refresh: (target: ConnectionTarget, reason: RefreshReason) => Promise<Tokens>;
|
|
13
16
|
readonly isTransientError?: (err: unknown) => boolean;
|
|
14
17
|
readonly isServerError?: (err: unknown) => boolean;
|
|
15
18
|
readonly now?: () => number;
|
|
16
19
|
readonly setTimer?: (cb: () => void, ms: number) => unknown;
|
|
17
20
|
readonly clearTimer?: (handle: unknown) => void;
|
|
18
|
-
readonly
|
|
21
|
+
readonly isReachable?: () => boolean;
|
|
22
|
+
readonly acquireRefreshLock?: <T>(fn: () => Promise<T>, signal?: AbortSignal) => Promise<T>;
|
|
19
23
|
readonly getLatestTokens?: () => Tokens | null;
|
|
20
24
|
readonly onRefreshStart?: (reason: RefreshReason) => void;
|
|
21
25
|
readonly onRefreshSuccess?: (reason: RefreshReason, tokens: Tokens) => void;
|
|
@@ -28,11 +32,11 @@ export interface TokenLifecycleOptions {
|
|
|
28
32
|
}) => void;
|
|
29
33
|
readonly onScheduled?: (delayMs: number, expiresAt: number) => void;
|
|
30
34
|
readonly onWakeChecked?: (info: {
|
|
31
|
-
decision: 'refresh-now' | 'still-fresh' | 'no-target' | 'no-expiry';
|
|
35
|
+
decision: 'refresh-now' | 'still-fresh' | 'throttled' | 'no-target' | 'no-expiry';
|
|
32
36
|
remainingMs?: number;
|
|
33
37
|
phase: string;
|
|
34
38
|
}) => void;
|
|
35
|
-
readonly onTriggerSkipped?: (reason: RefreshReason, why: 'detached' | 'already-inflight' | 'no-target', phase: string) => void;
|
|
39
|
+
readonly onTriggerSkipped?: (reason: RefreshReason, why: 'detached' | 'already-inflight' | 'no-target' | 'throttled', phase: string) => void;
|
|
36
40
|
}
|
|
37
41
|
export type Detach = () => void;
|
|
38
42
|
export interface TokenLifecycle {
|
|
@@ -40,3 +44,4 @@ export interface TokenLifecycle {
|
|
|
40
44
|
readonly wake: () => void;
|
|
41
45
|
}
|
|
42
46
|
export declare function attachTokenLifecycle(options: TokenLifecycleOptions): TokenLifecycle;
|
|
47
|
+
export declare function localAccessExpiry(access: string, serverExpiresAt?: number, receivedAt?: number): number | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { attachNetworkChange } from './effects/networkChange.js';
|
|
|
8
8
|
export { attachPersistence, localStorageAdapter, memoryStorageAdapter } from './effects/persistence.js';
|
|
9
9
|
export { attachPresence } from './effects/presence.js';
|
|
10
10
|
export { attachProbeLoop, isProbeFailure, makeProbeFailure } from './effects/probeLoop.js';
|
|
11
|
-
export { attachTokenLifecycle } from './effects/tokenLifecycle.js';
|
|
11
|
+
export { attachTokenLifecycle, localAccessExpiry } from './effects/tokenLifecycle.js';
|
|
12
12
|
export { attachTransportSync } from './effects/transportSync.js';
|
|
13
13
|
export { attachWorkerBridge } from './effects/workerBridge.js';
|
|
14
14
|
export { createConnectionJournal } from './journal.js';
|
|
@@ -20,7 +20,7 @@ export type { Kernel, KernelOptions, Listener, Unsubscribe } from './core/kernel
|
|
|
20
20
|
export type { Action, BackoffHint, ConnectionPhase, ConnectionTarget, Endpoint, EndpointMode, ReducerContext, Tokens, TransportId, TransportKind, TransportSpec, TransportStatus, } from './core/types.js';
|
|
21
21
|
export type { BackgroundProbe, BackgroundProbeOptions, BackgroundProbeOutcome } from './effects/backgroundProbe.js';
|
|
22
22
|
export type { BackoffOptions } from './effects/backoff.js';
|
|
23
|
-
export type { CrossTabOptions, CrossTabSource } from './effects/crossTab.js';
|
|
23
|
+
export type { CrossTabOptions, CrossTabPayload, CrossTabSource } from './effects/crossTab.js';
|
|
24
24
|
export type { DegradedRecoveryOptions } from './effects/degradedRecovery.js';
|
|
25
25
|
export type { NetworkChangeOptions, NetworkChangeSource } from './effects/networkChange.js';
|
|
26
26
|
export type { PersistedTarget, Persistence, PersistenceOptions, StorageAdapter } from './effects/persistence.js';
|