uidex 0.6.0 → 0.7.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/README.md +3 -3
- package/dist/cli/cli.cjs +1510 -1244
- package/dist/cli/cli.cjs.map +1 -1
- package/dist/cloud/index.cjs +385 -175
- package/dist/cloud/index.cjs.map +1 -1
- package/dist/cloud/index.d.cts +192 -4
- package/dist/cloud/index.d.ts +192 -4
- package/dist/cloud/index.js +377 -177
- package/dist/cloud/index.js.map +1 -1
- package/dist/headless/index.cjs +82 -255
- package/dist/headless/index.cjs.map +1 -1
- package/dist/headless/index.d.cts +5 -11
- package/dist/headless/index.d.ts +5 -11
- package/dist/headless/index.js +82 -257
- package/dist/headless/index.js.map +1 -1
- package/dist/index.cjs +721 -1053
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +149 -160
- package/dist/index.d.ts +149 -160
- package/dist/index.js +741 -1068
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +729 -1000
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +99 -86
- package/dist/react/index.d.ts +99 -86
- package/dist/react/index.js +745 -1015
- package/dist/react/index.js.map +1 -1
- package/dist/scan/index.cjs +1518 -1237
- package/dist/scan/index.cjs.map +1 -1
- package/dist/scan/index.d.cts +209 -12
- package/dist/scan/index.d.ts +209 -12
- package/dist/scan/index.js +1515 -1236
- package/dist/scan/index.js.map +1 -1
- package/package.json +22 -21
- package/templates/claude/SKILL.md +71 -0
- package/templates/claude/references/audit.md +43 -0
- package/templates/claude/{rules.md → references/conventions.md} +25 -28
- package/templates/claude/audit.md +0 -43
- /package/templates/claude/{api.md → references/api.md} +0 -0
package/dist/cloud/index.d.ts
CHANGED
|
@@ -11,7 +11,10 @@ declare const DEFAULT_CLOUD_ENDPOINT = "https://app.uidex.dev";
|
|
|
11
11
|
interface CloudOptions {
|
|
12
12
|
projectKey: string;
|
|
13
13
|
endpoint?: string;
|
|
14
|
+
/** @deprecated Unused — the adapter talks RPC over WebSocket. Kept for API compatibility. */
|
|
14
15
|
fetch?: typeof fetch;
|
|
16
|
+
/** Optional WebSocket constructor override (tests, Node). Defaults to `globalThis.WebSocket`. */
|
|
17
|
+
WebSocketImpl?: typeof WebSocket;
|
|
15
18
|
git?: {
|
|
16
19
|
branch?: string;
|
|
17
20
|
commit?: string;
|
|
@@ -44,6 +47,8 @@ interface RealtimeChannel {
|
|
|
44
47
|
joinRoute(route: string): void;
|
|
45
48
|
onPresence(cb: (users: RealtimePresenceUser[]) => void): () => void;
|
|
46
49
|
onPin(cb: (pin: PinRecord) => void): () => void;
|
|
50
|
+
/** Optional so pre-existing channel stubs keep satisfying the interface. */
|
|
51
|
+
onPinArchived?(cb: (reportId: string) => void): () => void;
|
|
47
52
|
}
|
|
48
53
|
interface CloudAdapter<TPayload = ReportPayload, TResult = ReportResult, TIntegrations = {
|
|
49
54
|
getConfig(): Promise<IngestConfig>;
|
|
@@ -65,18 +70,201 @@ interface CloudAdapter<TPayload = ReportPayload, TResult = ReportResult, TIntegr
|
|
|
65
70
|
route?: string;
|
|
66
71
|
entities?: string;
|
|
67
72
|
}): Promise<PinRecord[]>;
|
|
68
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Pin records travel without their screenshot (kept out of `pins.list`
|
|
75
|
+
* so multi-MB frames don't stall the shared socket); the report detail
|
|
76
|
+
* view fetches it lazily through here. Optional for host-provided
|
|
77
|
+
* adapters that inline screenshots on the record instead.
|
|
78
|
+
*/
|
|
79
|
+
screenshot?(reportId: string): Promise<string | null>;
|
|
80
|
+
close(reportId: string, reason?: ArchiveReason): Promise<void>;
|
|
69
81
|
};
|
|
82
|
+
/** Closes the adapter's shared socket. Any later RPC call revives it. */
|
|
83
|
+
dispose?(): void;
|
|
70
84
|
}
|
|
71
85
|
|
|
72
86
|
declare function cloud(options: CloudOptions): CloudAdapter;
|
|
73
87
|
|
|
88
|
+
/**
|
|
89
|
+
* WS RPC protocol shared by the SDK (`packages/sdk/src/cloud`) and the relay
|
|
90
|
+
* server (`apps/app/src/lib/relay-handler.ts`, type-only import from
|
|
91
|
+
* "uidex/cloud"). These frames ride the same socket as the existing
|
|
92
|
+
* fire-and-forget messages (`cursor`, `join`, `presence`, `pin`); peers that
|
|
93
|
+
* predate a frame type silently drop it.
|
|
94
|
+
*/
|
|
95
|
+
declare const RPC_METHODS: readonly ["reports.submit", "reports.list", "config.get", "pins.list", "pins.screenshot", "pins.archive", "screenshot.chunk"];
|
|
96
|
+
type RpcMethod = (typeof RPC_METHODS)[number];
|
|
97
|
+
/**
|
|
98
|
+
* Screenshots whose base64 data-URL length is at or below this ride inline in
|
|
99
|
+
* the `reports.submit` frame (the common case). Larger ones are streamed via
|
|
100
|
+
* `screenshot.chunk` so no single frame approaches the relay's 25 MiB WS
|
|
101
|
+
* `maxPayload` — an oversized frame is dropped server-side (close 1009), which
|
|
102
|
+
* the SDK surfaces as "Connection lost".
|
|
103
|
+
*/
|
|
104
|
+
declare const SCREENSHOT_INLINE_MAX_BYTES: number;
|
|
105
|
+
/** Per-chunk size when a screenshot is streamed. Each `screenshot.chunk` frame stays well under `maxPayload`. */
|
|
106
|
+
declare const SCREENSHOT_CHUNK_BYTES: number;
|
|
107
|
+
/** One streamed screenshot fragment. Parts are keyed by `seq` and reassembled in order server-side. */
|
|
108
|
+
type ScreenshotChunkParams = {
|
|
109
|
+
/** Client-generated id grouping a screenshot's chunks; referenced by `reports.submit` as `screenshotUploadId`. */
|
|
110
|
+
uploadId: string;
|
|
111
|
+
/** 0-based index of this part. */
|
|
112
|
+
seq: number;
|
|
113
|
+
/** Total number of parts in this upload. */
|
|
114
|
+
total: number;
|
|
115
|
+
/** A slice of the screenshot data URL. */
|
|
116
|
+
data: string;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* `reports.submit` params. Either the screenshot rides inline (`screenshot`) or,
|
|
120
|
+
* for large captures, it is streamed via `screenshot.chunk` and referenced here
|
|
121
|
+
* by `screenshotUploadId` — the server reassembles it before persisting.
|
|
122
|
+
*/
|
|
123
|
+
type ReportSubmitParams = ReportPayload & {
|
|
124
|
+
screenshotUploadId?: string;
|
|
125
|
+
};
|
|
126
|
+
interface RpcParamsMap {
|
|
127
|
+
"reports.submit": ReportSubmitParams;
|
|
128
|
+
"reports.list": {
|
|
129
|
+
page?: number;
|
|
130
|
+
limit?: number;
|
|
131
|
+
};
|
|
132
|
+
"config.get": undefined;
|
|
133
|
+
"pins.list": {
|
|
134
|
+
route?: string;
|
|
135
|
+
entities?: string[];
|
|
136
|
+
};
|
|
137
|
+
"pins.screenshot": {
|
|
138
|
+
reportId: string;
|
|
139
|
+
};
|
|
140
|
+
"pins.archive": {
|
|
141
|
+
reportId: string;
|
|
142
|
+
reason?: ArchiveReason;
|
|
143
|
+
};
|
|
144
|
+
"screenshot.chunk": ScreenshotChunkParams;
|
|
145
|
+
}
|
|
146
|
+
interface RpcResultMap {
|
|
147
|
+
"reports.submit": ReportResult;
|
|
148
|
+
"reports.list": ReportListResponse;
|
|
149
|
+
"config.get": IngestConfig;
|
|
150
|
+
"pins.list": {
|
|
151
|
+
pins: PinRecord[];
|
|
152
|
+
};
|
|
153
|
+
"pins.screenshot": {
|
|
154
|
+
screenshot: string | null;
|
|
155
|
+
};
|
|
156
|
+
"pins.archive": {
|
|
157
|
+
ok: true;
|
|
158
|
+
};
|
|
159
|
+
/** Acks a stored chunk; `received` is how many distinct parts have arrived. */
|
|
160
|
+
"screenshot.chunk": {
|
|
161
|
+
received: number;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
type RpcRequestFrame = {
|
|
165
|
+
type: "rpc";
|
|
166
|
+
id: string;
|
|
167
|
+
method: RpcMethod;
|
|
168
|
+
params?: unknown;
|
|
169
|
+
};
|
|
170
|
+
type RpcOkFrame = {
|
|
171
|
+
type: "rpc:res";
|
|
172
|
+
id: string;
|
|
173
|
+
ok: true;
|
|
174
|
+
data: unknown;
|
|
175
|
+
};
|
|
176
|
+
type RpcErrFrame = {
|
|
177
|
+
type: "rpc:res";
|
|
178
|
+
id: string;
|
|
179
|
+
ok: false;
|
|
180
|
+
/** HTTP-equivalent status so CloudError semantics survive the transport. */
|
|
181
|
+
status: number;
|
|
182
|
+
error: string;
|
|
183
|
+
/** Seconds, present on 429 responses (mirrors the Retry-After header). */
|
|
184
|
+
retryAfter?: number;
|
|
185
|
+
details?: unknown;
|
|
186
|
+
};
|
|
187
|
+
type RpcResponseFrame = RpcOkFrame | RpcErrFrame;
|
|
188
|
+
/**
|
|
189
|
+
* Sent by the SDK after `realtime.connect(opts)` to attach a user identity to
|
|
190
|
+
* an initially anonymous connection. The server marks the connection visible
|
|
191
|
+
* in presence from this point on. Connections that never identify stay
|
|
192
|
+
* RPC-only: excluded from presence, no room auto-join.
|
|
193
|
+
*/
|
|
194
|
+
type IdentifyFrame = {
|
|
195
|
+
type: "identify";
|
|
196
|
+
userId: string;
|
|
197
|
+
name?: string;
|
|
198
|
+
avatar?: string;
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* Reverse of `IdentifyFrame`: sent when a realtime consumer disconnects
|
|
202
|
+
* (e.g. the uidex surface unmounts) while the adapter keeps using the socket
|
|
203
|
+
* for RPC. The server drops the connection from presence and its room but
|
|
204
|
+
* keeps the socket open.
|
|
205
|
+
*/
|
|
206
|
+
type LeaveFrame = {
|
|
207
|
+
type: "leave";
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Server→client broadcast when a pin's report leaves the open statuses
|
|
211
|
+
* (closed via the SDK, the dashboard, or the REST route). Sent to the room of
|
|
212
|
+
* the report's route so live overlays drop the pin without a refresh.
|
|
213
|
+
*/
|
|
214
|
+
type PinArchivedFrame = {
|
|
215
|
+
type: "pin:archived";
|
|
216
|
+
reportId: string;
|
|
217
|
+
};
|
|
218
|
+
declare function isRpcMethod(value: unknown): value is RpcMethod;
|
|
219
|
+
/** Client-side guard for inbound `rpc:res` frames (server validates inbound `rpc` frames itself). */
|
|
220
|
+
declare function parseRpcResponseFrame(msg: unknown): RpcResponseFrame | null;
|
|
221
|
+
|
|
74
222
|
type RealtimeChannelOptions = {
|
|
75
|
-
/** Builds the WebSocket URL on each (re)connect attempt.
|
|
223
|
+
/** Builds the WebSocket URL on each (re)connect attempt. Only needs the project key — identity and route ride dedicated frames. */
|
|
76
224
|
buildUrl: () => string;
|
|
77
225
|
/** Optional WebSocket constructor override (testing). Defaults to `globalThis.WebSocket`. */
|
|
78
226
|
WebSocketImpl?: typeof WebSocket;
|
|
79
227
|
};
|
|
80
|
-
|
|
228
|
+
/**
|
|
229
|
+
* Superset of the public `RealtimeChannel` used internally by the cloud
|
|
230
|
+
* adapter: the RPC client (`./rpc`) shares the same socket and needs raw
|
|
231
|
+
* frame access plus open/close notifications.
|
|
232
|
+
*/
|
|
233
|
+
interface InternalRealtimeChannel extends RealtimeChannel {
|
|
234
|
+
/** Required here (optional on the public interface only for channel stubs). */
|
|
235
|
+
onPinArchived(cb: (reportId: string) => void): () => void;
|
|
236
|
+
/** Stores the identity and (re)sends the `identify` frame on every open. */
|
|
237
|
+
identify(user: UserIdentity): void;
|
|
238
|
+
/** Drops the stored identity/route without touching the socket (soft leave). */
|
|
239
|
+
clearSession(): void;
|
|
240
|
+
/** Sends a JSON frame if the socket is OPEN. Returns false otherwise. */
|
|
241
|
+
sendFrame(frame: object): boolean;
|
|
242
|
+
/** Fires after the channel finished its identify/join replay on (re)open. */
|
|
243
|
+
onOpen(cb: () => void): () => void;
|
|
244
|
+
/**
|
|
245
|
+
* Fires with the close code (or `CLOSE_CODE_SYNTHETIC`) whenever the socket
|
|
246
|
+
* goes away. `willReconnect` is false for terminal closes (`disconnect()`,
|
|
247
|
+
* auth failure, no WebSocket implementation): queued work must reject
|
|
248
|
+
* instead of riding a reconnect that will never come.
|
|
249
|
+
*/
|
|
250
|
+
onClose(cb: (code: number, willReconnect: boolean) => void): () => void;
|
|
251
|
+
onRpcResponse(cb: (frame: RpcResponseFrame) => void): () => void;
|
|
252
|
+
}
|
|
253
|
+
declare function createRealtimeChannel(options: RealtimeChannelOptions): InternalRealtimeChannel;
|
|
254
|
+
|
|
255
|
+
declare const DEFAULT_RPC_TIMEOUT_MS = 30000;
|
|
256
|
+
interface RpcClient {
|
|
257
|
+
call<M extends RpcMethod>(method: M, params: RpcParamsMap[M], opts?: {
|
|
258
|
+
timeoutMs?: number;
|
|
259
|
+
}): Promise<RpcResultMap[M]>;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Request/response RPC over the realtime channel's socket. Requests made
|
|
263
|
+
* while the socket is closed are queued and flushed on (re)open — after the
|
|
264
|
+
* channel's identify/join replay, because the channel emits `onOpen` last.
|
|
265
|
+
*/
|
|
266
|
+
declare function createRpcClient(channel: InternalRealtimeChannel, options?: {
|
|
267
|
+
timeoutMs?: number;
|
|
268
|
+
}): RpcClient;
|
|
81
269
|
|
|
82
|
-
export { type CloudAdapter, CloudError, type CloudOptions, DEFAULT_CLOUD_ENDPOINT, type RealtimeChannel, type RealtimeChannelState, type RealtimeConnectOpts, type RealtimePresenceUser, cloud, createRealtimeChannel };
|
|
270
|
+
export { type CloudAdapter, CloudError, type CloudOptions, DEFAULT_CLOUD_ENDPOINT, DEFAULT_RPC_TIMEOUT_MS, type IdentifyFrame, type InternalRealtimeChannel, type LeaveFrame, type PinArchivedFrame, RPC_METHODS, type RealtimeChannel, type RealtimeChannelState, type RealtimeConnectOpts, type RealtimePresenceUser, type ReportSubmitParams, type RpcClient, type RpcErrFrame, type RpcMethod, type RpcOkFrame, type RpcParamsMap, type RpcRequestFrame, type RpcResponseFrame, type RpcResultMap, SCREENSHOT_CHUNK_BYTES, SCREENSHOT_INLINE_MAX_BYTES, type ScreenshotChunkParams, cloud, createRealtimeChannel, createRpcClient, isRpcMethod, parseRpcResponseFrame };
|