uidex 0.4.0 → 0.5.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/cli/cli.cjs +1111 -87
- package/dist/cli/cli.cjs.map +1 -1
- package/dist/cloud/index.cjs +375 -72
- package/dist/cloud/index.cjs.map +1 -1
- package/dist/cloud/index.d.cts +82 -0
- package/dist/cloud/index.d.ts +82 -0
- package/dist/cloud/index.js +376 -71
- package/dist/cloud/index.js.map +1 -1
- package/dist/headless/index.cjs +623 -469
- package/dist/headless/index.cjs.map +1 -1
- package/dist/headless/index.d.cts +77 -75
- package/dist/headless/index.d.ts +77 -75
- package/dist/headless/index.js +627 -469
- package/dist/headless/index.js.map +1 -1
- package/dist/index.cjs +4258 -2884
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +275 -234
- package/dist/index.d.ts +275 -234
- package/dist/index.js +4280 -2890
- package/dist/index.js.map +1 -1
- package/dist/playwright/index.cjs +4 -4
- package/dist/playwright/index.cjs.map +1 -1
- package/dist/playwright/index.js +3 -3
- package/dist/playwright/index.js.map +1 -1
- package/dist/playwright/reporter.cjs +3 -3
- package/dist/playwright/reporter.cjs.map +1 -1
- package/dist/playwright/reporter.js +3 -3
- package/dist/playwright/reporter.js.map +1 -1
- package/dist/react/index.cjs +4299 -2906
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +206 -200
- package/dist/react/index.d.ts +206 -200
- package/dist/react/index.js +4339 -2926
- package/dist/react/index.js.map +1 -1
- package/dist/scan/index.cjs +201 -49
- package/dist/scan/index.cjs.map +1 -1
- package/dist/scan/index.d.cts +27 -1
- package/dist/scan/index.d.ts +27 -1
- package/dist/scan/index.js +200 -48
- package/dist/scan/index.js.map +1 -1
- package/package.json +8 -14
- package/templates/claude/api.md +110 -0
package/dist/cloud/index.cjs
CHANGED
|
@@ -22,10 +22,288 @@ var cloud_exports = {};
|
|
|
22
22
|
__export(cloud_exports, {
|
|
23
23
|
CloudError: () => CloudError,
|
|
24
24
|
DEFAULT_CLOUD_ENDPOINT: () => DEFAULT_CLOUD_ENDPOINT,
|
|
25
|
-
cloud: () => cloud
|
|
25
|
+
cloud: () => cloud,
|
|
26
|
+
createRealtimeChannel: () => createRealtimeChannel
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(cloud_exports);
|
|
28
29
|
|
|
30
|
+
// src/cloud/client.ts
|
|
31
|
+
var import_client_fetch2 = require("@hey-api/client-fetch");
|
|
32
|
+
|
|
33
|
+
// ../api-client/src/client.gen.ts
|
|
34
|
+
var import_client_fetch = require("@hey-api/client-fetch");
|
|
35
|
+
var client = (0, import_client_fetch.createClient)(
|
|
36
|
+
(0, import_client_fetch.createConfig)({
|
|
37
|
+
baseUrl: "https://app.uidex.dev"
|
|
38
|
+
})
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// ../api-client/src/sdk.gen.ts
|
|
42
|
+
var submitReport = (options) => {
|
|
43
|
+
return (options.client ?? client).post({
|
|
44
|
+
security: [
|
|
45
|
+
{
|
|
46
|
+
scheme: "bearer",
|
|
47
|
+
type: "http"
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
url: "/api/ingest",
|
|
51
|
+
...options,
|
|
52
|
+
headers: {
|
|
53
|
+
"Content-Type": "application/json",
|
|
54
|
+
...options?.headers
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
var getIngestConfig = (options) => {
|
|
59
|
+
return (options?.client ?? client).get({
|
|
60
|
+
security: [
|
|
61
|
+
{
|
|
62
|
+
scheme: "bearer",
|
|
63
|
+
type: "http"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
url: "/api/ingest/config",
|
|
67
|
+
...options
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
var listIngestReports = (options) => {
|
|
71
|
+
return (options?.client ?? client).get({
|
|
72
|
+
security: [
|
|
73
|
+
{
|
|
74
|
+
scheme: "bearer",
|
|
75
|
+
type: "http"
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
url: "/api/ingest/reports",
|
|
79
|
+
...options
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
var listPins = (options) => {
|
|
83
|
+
return (options?.client ?? client).get({
|
|
84
|
+
security: [
|
|
85
|
+
{
|
|
86
|
+
scheme: "bearer",
|
|
87
|
+
type: "http"
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
url: "/api/ingest/pins",
|
|
91
|
+
...options
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
var archivePin = (options) => {
|
|
95
|
+
return (options.client ?? client).post({
|
|
96
|
+
security: [
|
|
97
|
+
{
|
|
98
|
+
scheme: "bearer",
|
|
99
|
+
type: "http"
|
|
100
|
+
}
|
|
101
|
+
],
|
|
102
|
+
url: "/api/ingest/pins/archive",
|
|
103
|
+
...options,
|
|
104
|
+
headers: {
|
|
105
|
+
"Content-Type": "application/json",
|
|
106
|
+
...options?.headers
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// src/cloud/realtime.ts
|
|
112
|
+
var RECONNECT_INITIAL_MS = 1e3;
|
|
113
|
+
var RECONNECT_MAX_MS = 3e4;
|
|
114
|
+
var CLOSE_CODE_AUTH_FAILED = 4001;
|
|
115
|
+
function emit(listeners, value) {
|
|
116
|
+
for (const cb of listeners) {
|
|
117
|
+
try {
|
|
118
|
+
cb(value);
|
|
119
|
+
} catch {
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function resolveWebSocket(override) {
|
|
124
|
+
if (override) return override;
|
|
125
|
+
if (typeof globalThis !== "undefined" && typeof globalThis.WebSocket === "function") {
|
|
126
|
+
return globalThis.WebSocket;
|
|
127
|
+
}
|
|
128
|
+
throw new Error(
|
|
129
|
+
"uidex/cloud: global WebSocket is not available; pass a `WebSocketImpl` override"
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
function createRealtimeChannel(options) {
|
|
133
|
+
const WS = resolveWebSocket(options.WebSocketImpl);
|
|
134
|
+
const presenceListeners = /* @__PURE__ */ new Set();
|
|
135
|
+
const pinListeners = /* @__PURE__ */ new Set();
|
|
136
|
+
let ws = null;
|
|
137
|
+
let state = "disconnected";
|
|
138
|
+
let disposed = false;
|
|
139
|
+
let reconnectAttempts = 0;
|
|
140
|
+
let reconnectTimer = null;
|
|
141
|
+
function clearReconnectTimer() {
|
|
142
|
+
if (reconnectTimer !== null) {
|
|
143
|
+
clearTimeout(reconnectTimer);
|
|
144
|
+
reconnectTimer = null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function scheduleReconnect() {
|
|
148
|
+
if (disposed) return;
|
|
149
|
+
const delay = Math.min(
|
|
150
|
+
RECONNECT_INITIAL_MS * 2 ** reconnectAttempts,
|
|
151
|
+
RECONNECT_MAX_MS
|
|
152
|
+
);
|
|
153
|
+
reconnectAttempts += 1;
|
|
154
|
+
state = "connecting";
|
|
155
|
+
clearReconnectTimer();
|
|
156
|
+
reconnectTimer = setTimeout(() => {
|
|
157
|
+
reconnectTimer = null;
|
|
158
|
+
openSocket();
|
|
159
|
+
}, delay);
|
|
160
|
+
}
|
|
161
|
+
function handleMessage(event) {
|
|
162
|
+
if (typeof event.data !== "string") return;
|
|
163
|
+
let parsed;
|
|
164
|
+
try {
|
|
165
|
+
parsed = JSON.parse(event.data);
|
|
166
|
+
} catch {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (!parsed || typeof parsed !== "object") return;
|
|
170
|
+
const msg = parsed;
|
|
171
|
+
if (msg.type === "presence") {
|
|
172
|
+
const p = msg;
|
|
173
|
+
if (!Array.isArray(p.users)) return;
|
|
174
|
+
const users = [];
|
|
175
|
+
for (const raw of p.users) {
|
|
176
|
+
if (!raw || typeof raw !== "object") continue;
|
|
177
|
+
const u = raw;
|
|
178
|
+
if (typeof u.userId !== "string" || typeof u.name !== "string") continue;
|
|
179
|
+
users.push({
|
|
180
|
+
userId: u.userId,
|
|
181
|
+
name: u.name,
|
|
182
|
+
avatar: typeof u.avatar === "string" ? u.avatar : null
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
emit(presenceListeners, users);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (msg.type === "pin") {
|
|
189
|
+
const p = msg;
|
|
190
|
+
if (typeof p.feedbackId !== "string" || !p.elementRef || typeof p.elementRef !== "object" || typeof p.elementRef.kind !== "string" || typeof p.elementRef.id !== "string" || !p.author || typeof p.author !== "object" || typeof p.body !== "string" || typeof p.reportType !== "string" || typeof p.reportSeverity !== "string" || typeof p.createdAt !== "string") {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const author = p.author;
|
|
194
|
+
const elRef = p.elementRef;
|
|
195
|
+
const pin = {
|
|
196
|
+
id: p.feedbackId,
|
|
197
|
+
entity: `${elRef.kind}:${elRef.id}`,
|
|
198
|
+
reporter: {
|
|
199
|
+
name: typeof author.name === "string" ? author.name : void 0,
|
|
200
|
+
email: typeof author.email === "string" ? author.email : void 0
|
|
201
|
+
},
|
|
202
|
+
body: p.body,
|
|
203
|
+
type: p.reportType,
|
|
204
|
+
severity: p.reportSeverity,
|
|
205
|
+
status: "open",
|
|
206
|
+
createdAt: p.createdAt,
|
|
207
|
+
url: ""
|
|
208
|
+
};
|
|
209
|
+
emit(pinListeners, pin);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function openSocket() {
|
|
214
|
+
if (disposed) return;
|
|
215
|
+
state = "connecting";
|
|
216
|
+
let url;
|
|
217
|
+
try {
|
|
218
|
+
url = options.buildUrl();
|
|
219
|
+
} catch {
|
|
220
|
+
state = "disconnected";
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
let socket;
|
|
224
|
+
try {
|
|
225
|
+
socket = new WS(url);
|
|
226
|
+
} catch {
|
|
227
|
+
scheduleReconnect();
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
ws = socket;
|
|
231
|
+
socket.addEventListener("open", () => {
|
|
232
|
+
if (ws !== socket) return;
|
|
233
|
+
state = "connected";
|
|
234
|
+
reconnectAttempts = 0;
|
|
235
|
+
});
|
|
236
|
+
socket.addEventListener("message", (event) => {
|
|
237
|
+
if (ws !== socket) return;
|
|
238
|
+
handleMessage(event);
|
|
239
|
+
});
|
|
240
|
+
socket.addEventListener("close", (event) => {
|
|
241
|
+
if (ws !== socket) return;
|
|
242
|
+
ws = null;
|
|
243
|
+
const code = event.code;
|
|
244
|
+
if (disposed || code === CLOSE_CODE_AUTH_FAILED) {
|
|
245
|
+
state = "disconnected";
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
scheduleReconnect();
|
|
249
|
+
});
|
|
250
|
+
socket.addEventListener("error", () => {
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
function connect() {
|
|
254
|
+
if (disposed) {
|
|
255
|
+
disposed = false;
|
|
256
|
+
}
|
|
257
|
+
if (ws) return;
|
|
258
|
+
if (state === "connecting") return;
|
|
259
|
+
reconnectAttempts = 0;
|
|
260
|
+
openSocket();
|
|
261
|
+
}
|
|
262
|
+
function disconnect() {
|
|
263
|
+
disposed = true;
|
|
264
|
+
clearReconnectTimer();
|
|
265
|
+
state = "disconnected";
|
|
266
|
+
if (ws) {
|
|
267
|
+
try {
|
|
268
|
+
ws.close(1e3);
|
|
269
|
+
} catch {
|
|
270
|
+
}
|
|
271
|
+
ws = null;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function joinRoute(route) {
|
|
275
|
+
emit(presenceListeners, []);
|
|
276
|
+
if (ws && ws.readyState === WS.OPEN) {
|
|
277
|
+
try {
|
|
278
|
+
ws.send(JSON.stringify({ type: "join", route }));
|
|
279
|
+
} catch {
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function onPresence(cb) {
|
|
284
|
+
presenceListeners.add(cb);
|
|
285
|
+
return () => {
|
|
286
|
+
presenceListeners.delete(cb);
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function onPin(cb) {
|
|
290
|
+
pinListeners.add(cb);
|
|
291
|
+
return () => {
|
|
292
|
+
pinListeners.delete(cb);
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
get state() {
|
|
297
|
+
return state;
|
|
298
|
+
},
|
|
299
|
+
connect,
|
|
300
|
+
disconnect,
|
|
301
|
+
joinRoute,
|
|
302
|
+
onPresence,
|
|
303
|
+
onPin
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
29
307
|
// src/cloud/types.ts
|
|
30
308
|
var DEFAULT_CLOUD_ENDPOINT = "https://app.uidex.dev";
|
|
31
309
|
var CloudError = class extends Error {
|
|
@@ -42,18 +320,18 @@ var CloudError = class extends Error {
|
|
|
42
320
|
};
|
|
43
321
|
|
|
44
322
|
// src/cloud/client.ts
|
|
45
|
-
function resolveFetch(override) {
|
|
46
|
-
if (override) return override;
|
|
47
|
-
if (typeof globalThis !== "undefined" && typeof globalThis.fetch === "function") {
|
|
48
|
-
return globalThis.fetch.bind(globalThis);
|
|
49
|
-
}
|
|
50
|
-
throw new Error(
|
|
51
|
-
"uidex/cloud: global fetch is not available; pass a `fetch` override"
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
323
|
function trimEndpoint(endpoint) {
|
|
55
324
|
return endpoint.endsWith("/") ? endpoint.slice(0, -1) : endpoint;
|
|
56
325
|
}
|
|
326
|
+
function unwrap(result) {
|
|
327
|
+
if (result.error !== void 0 || !result.data) {
|
|
328
|
+
const status = result.response.status;
|
|
329
|
+
const retryAfter = status === 429 ? parseRetryAfter(result.response.headers.get("Retry-After")) : void 0;
|
|
330
|
+
const msg = result.error && typeof result.error === "object" && "error" in result.error && typeof result.error.error === "string" ? result.error.error : `Request failed (${status})`;
|
|
331
|
+
throw new CloudError(msg, { status, retryAfter, details: result.error });
|
|
332
|
+
}
|
|
333
|
+
return result.data;
|
|
334
|
+
}
|
|
57
335
|
function parseRetryAfter(header) {
|
|
58
336
|
if (!header) return void 0;
|
|
59
337
|
const seconds = Number(header);
|
|
@@ -65,21 +343,6 @@ function parseRetryAfter(header) {
|
|
|
65
343
|
}
|
|
66
344
|
return void 0;
|
|
67
345
|
}
|
|
68
|
-
async function readBody(response) {
|
|
69
|
-
const text = await response.text();
|
|
70
|
-
if (!text) return void 0;
|
|
71
|
-
try {
|
|
72
|
-
return JSON.parse(text);
|
|
73
|
-
} catch {
|
|
74
|
-
return text;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
function errorMessage(body, fallback) {
|
|
78
|
-
if (body && typeof body === "object" && "error" in body && typeof body.error === "string") {
|
|
79
|
-
return body.error;
|
|
80
|
-
}
|
|
81
|
-
return fallback;
|
|
82
|
-
}
|
|
83
346
|
function cloud(options) {
|
|
84
347
|
let cachedConfig = null;
|
|
85
348
|
let resolvedConfig = null;
|
|
@@ -88,54 +351,34 @@ function cloud(options) {
|
|
|
88
351
|
throw new Error("uidex/cloud: `projectKey` is required");
|
|
89
352
|
}
|
|
90
353
|
const endpoint = trimEndpoint(options.endpoint ?? DEFAULT_CLOUD_ENDPOINT);
|
|
91
|
-
const
|
|
92
|
-
const
|
|
354
|
+
const git = options.git;
|
|
355
|
+
const apiClient = (0, import_client_fetch2.createClient)(
|
|
356
|
+
(0, import_client_fetch2.createConfig)({
|
|
357
|
+
baseUrl: endpoint,
|
|
358
|
+
...options.fetch ? { fetch: options.fetch } : {},
|
|
359
|
+
headers: { Authorization: `Bearer ${projectKey}` }
|
|
360
|
+
})
|
|
361
|
+
);
|
|
93
362
|
async function submit(payload) {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
363
|
+
const enriched = git?.branch || git?.commit ? {
|
|
364
|
+
...payload,
|
|
365
|
+
context: {
|
|
366
|
+
...payload.context,
|
|
367
|
+
git: payload.context?.git ?? {
|
|
368
|
+
branch: git.branch,
|
|
369
|
+
commit: git.commit
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
} : payload;
|
|
373
|
+
const result = await submitReport({
|
|
374
|
+
client: apiClient,
|
|
375
|
+
body: enriched
|
|
101
376
|
});
|
|
102
|
-
|
|
103
|
-
if (!response.ok) {
|
|
104
|
-
const retryAfter = response.status === 429 ? parseRetryAfter(response.headers.get("Retry-After")) : void 0;
|
|
105
|
-
throw new CloudError(
|
|
106
|
-
errorMessage(body, `Feedback submission failed (${response.status})`),
|
|
107
|
-
{ status: response.status, retryAfter, details: body }
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
if (!body || typeof body !== "object") {
|
|
111
|
-
throw new CloudError("Feedback submission returned an empty response", {
|
|
112
|
-
status: response.status
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
return body;
|
|
377
|
+
return unwrap(result);
|
|
116
378
|
}
|
|
117
379
|
async function fetchConfig() {
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
headers: {
|
|
121
|
-
Accept: "application/json",
|
|
122
|
-
Authorization: authHeader
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
const body = await readBody(response);
|
|
126
|
-
if (!response.ok) {
|
|
127
|
-
const retryAfter = response.status === 429 ? parseRetryAfter(response.headers.get("Retry-After")) : void 0;
|
|
128
|
-
throw new CloudError(
|
|
129
|
-
errorMessage(body, `Ingest config request failed (${response.status})`),
|
|
130
|
-
{ status: response.status, retryAfter, details: body }
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
if (!body || typeof body !== "object") {
|
|
134
|
-
throw new CloudError("Ingest config returned an empty response", {
|
|
135
|
-
status: response.status
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
return body;
|
|
380
|
+
const result = await getIngestConfig({ client: apiClient });
|
|
381
|
+
return unwrap(result);
|
|
139
382
|
}
|
|
140
383
|
function startFetch() {
|
|
141
384
|
const promise = fetchConfig();
|
|
@@ -155,15 +398,75 @@ function cloud(options) {
|
|
|
155
398
|
function getCachedConfig() {
|
|
156
399
|
return resolvedConfig;
|
|
157
400
|
}
|
|
401
|
+
function realtimeUrl(route, user) {
|
|
402
|
+
const httpToWs = endpoint.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
|
|
403
|
+
const params = new URLSearchParams();
|
|
404
|
+
params.set("key", projectKey);
|
|
405
|
+
params.set("route", route);
|
|
406
|
+
params.set("userId", user.id);
|
|
407
|
+
if (user.name) params.set("name", user.name);
|
|
408
|
+
if (user.avatar) params.set("avatar", user.avatar);
|
|
409
|
+
return `${httpToWs}/ws?${params.toString()}`;
|
|
410
|
+
}
|
|
411
|
+
function connectRealtime(opts) {
|
|
412
|
+
if (!opts || !opts.user || typeof opts.user.id !== "string") {
|
|
413
|
+
throw new TypeError("uidex/cloud: realtime.connect requires `user.id`");
|
|
414
|
+
}
|
|
415
|
+
let currentRoute = opts.route;
|
|
416
|
+
const channel = createRealtimeChannel({
|
|
417
|
+
buildUrl: () => realtimeUrl(currentRoute, opts.user)
|
|
418
|
+
});
|
|
419
|
+
const originalJoinRoute = channel.joinRoute;
|
|
420
|
+
const wrapped = {
|
|
421
|
+
get state() {
|
|
422
|
+
return channel.state;
|
|
423
|
+
},
|
|
424
|
+
connect: () => channel.connect(),
|
|
425
|
+
disconnect: () => channel.disconnect(),
|
|
426
|
+
joinRoute: (route) => {
|
|
427
|
+
currentRoute = route;
|
|
428
|
+
originalJoinRoute(route);
|
|
429
|
+
},
|
|
430
|
+
onPresence: (cb) => channel.onPresence(cb),
|
|
431
|
+
onPin: (cb) => channel.onPin(cb)
|
|
432
|
+
};
|
|
433
|
+
channel.connect();
|
|
434
|
+
return wrapped;
|
|
435
|
+
}
|
|
436
|
+
async function listPins2(params) {
|
|
437
|
+
const result = await listPins({
|
|
438
|
+
client: apiClient,
|
|
439
|
+
query: params
|
|
440
|
+
});
|
|
441
|
+
const data = unwrap(result);
|
|
442
|
+
return data.pins;
|
|
443
|
+
}
|
|
444
|
+
async function archivePin2(reportId, reason) {
|
|
445
|
+
const result = await archivePin({
|
|
446
|
+
client: apiClient,
|
|
447
|
+
body: { reportId, ...reason ? { reason } : {} }
|
|
448
|
+
});
|
|
449
|
+
unwrap(result);
|
|
450
|
+
}
|
|
451
|
+
async function listReports(opts) {
|
|
452
|
+
const result = await listIngestReports({
|
|
453
|
+
client: apiClient,
|
|
454
|
+
query: opts
|
|
455
|
+
});
|
|
456
|
+
return unwrap(result);
|
|
457
|
+
}
|
|
158
458
|
return {
|
|
159
|
-
|
|
160
|
-
integrations: { getConfig, getCachedConfig }
|
|
459
|
+
reports: { submit, list: listReports },
|
|
460
|
+
integrations: { getConfig, getCachedConfig },
|
|
461
|
+
realtime: { connect: connectRealtime },
|
|
462
|
+
pins: { list: listPins2, archive: archivePin2 }
|
|
161
463
|
};
|
|
162
464
|
}
|
|
163
465
|
// Annotate the CommonJS export names for ESM import in node:
|
|
164
466
|
0 && (module.exports = {
|
|
165
467
|
CloudError,
|
|
166
468
|
DEFAULT_CLOUD_ENDPOINT,
|
|
167
|
-
cloud
|
|
469
|
+
cloud,
|
|
470
|
+
createRealtimeChannel
|
|
168
471
|
});
|
|
169
472
|
//# sourceMappingURL=index.cjs.map
|
package/dist/cloud/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cloud/index.ts","../../src/cloud/types.ts","../../src/cloud/client.ts"],"sourcesContent":["export { cloud } from \"./client\"\nexport {\n CloudError,\n DEFAULT_CLOUD_ENDPOINT,\n type CloudAdapter,\n type CloudOptions,\n type FeedbackExternalLink,\n type FeedbackPayload,\n type FeedbackResult,\n type FeedbackSuggestedTarget,\n type IngestConfig,\n type IngestConfigIssue,\n type SourceRef,\n} from \"./types\"\n","export type {\n CloudAdapter,\n FeedbackExternalLink,\n FeedbackPayload,\n FeedbackResult,\n FeedbackSuggestedTarget,\n IngestConfig,\n IngestConfigIssue,\n SourceRef,\n} from \"../ingest/feedback-contract\"\n\nexport const DEFAULT_CLOUD_ENDPOINT = \"https://app.uidex.dev\"\n\nexport interface CloudOptions {\n projectKey: string\n endpoint?: string\n fetch?: typeof fetch\n}\n\nexport class CloudError extends Error {\n readonly status: number\n readonly retryAfter?: number\n readonly details?: unknown\n\n constructor(\n message: string,\n options: { status: number; retryAfter?: number; details?: unknown }\n ) {\n super(message)\n this.name = \"CloudError\"\n this.status = options.status\n this.retryAfter = options.retryAfter\n this.details = options.details\n }\n}\n","import {\n CloudError,\n DEFAULT_CLOUD_ENDPOINT,\n type CloudAdapter,\n type CloudOptions,\n type FeedbackPayload,\n type FeedbackResult,\n type IngestConfig,\n} from \"./types\"\n\nfunction resolveFetch(override?: typeof fetch): typeof fetch {\n if (override) return override\n if (\n typeof globalThis !== \"undefined\" &&\n typeof globalThis.fetch === \"function\"\n ) {\n return globalThis.fetch.bind(globalThis)\n }\n throw new Error(\n \"uidex/cloud: global fetch is not available; pass a `fetch` override\"\n )\n}\n\nfunction trimEndpoint(endpoint: string): string {\n return endpoint.endsWith(\"/\") ? endpoint.slice(0, -1) : endpoint\n}\n\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined\n const seconds = Number(header)\n if (Number.isFinite(seconds) && seconds >= 0) return seconds\n const date = Date.parse(header)\n if (Number.isFinite(date)) {\n const delta = Math.ceil((date - Date.now()) / 1000)\n return delta > 0 ? delta : 0\n }\n return undefined\n}\n\nasync function readBody(response: Response): Promise<unknown> {\n const text = await response.text()\n if (!text) return undefined\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n}\n\nfunction errorMessage(body: unknown, fallback: string): string {\n if (\n body &&\n typeof body === \"object\" &&\n \"error\" in body &&\n typeof (body as { error: unknown }).error === \"string\"\n ) {\n return (body as { error: string }).error\n }\n return fallback\n}\n\nexport function cloud(options: CloudOptions): CloudAdapter {\n let cachedConfig: Promise<IngestConfig> | null = null\n let resolvedConfig: IngestConfig | null = null\n\n const projectKey = options.projectKey\n if (!projectKey) {\n throw new Error(\"uidex/cloud: `projectKey` is required\")\n }\n const endpoint = trimEndpoint(options.endpoint ?? DEFAULT_CLOUD_ENDPOINT)\n const fetchImpl = resolveFetch(options.fetch)\n const authHeader = `Bearer ${projectKey}`\n\n async function submit(payload: FeedbackPayload): Promise<FeedbackResult> {\n const response = await fetchImpl(`${endpoint}/api/ingest`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: authHeader,\n },\n body: JSON.stringify(payload),\n })\n\n const body = await readBody(response)\n\n if (!response.ok) {\n const retryAfter =\n response.status === 429\n ? parseRetryAfter(response.headers.get(\"Retry-After\"))\n : undefined\n throw new CloudError(\n errorMessage(body, `Feedback submission failed (${response.status})`),\n { status: response.status, retryAfter, details: body }\n )\n }\n\n if (!body || typeof body !== \"object\") {\n throw new CloudError(\"Feedback submission returned an empty response\", {\n status: response.status,\n })\n }\n return body as FeedbackResult\n }\n\n async function fetchConfig(): Promise<IngestConfig> {\n const response = await fetchImpl(`${endpoint}/api/ingest/config`, {\n method: \"GET\",\n headers: {\n Accept: \"application/json\",\n Authorization: authHeader,\n },\n })\n\n const body = await readBody(response)\n\n if (!response.ok) {\n const retryAfter =\n response.status === 429\n ? parseRetryAfter(response.headers.get(\"Retry-After\"))\n : undefined\n throw new CloudError(\n errorMessage(body, `Ingest config request failed (${response.status})`),\n { status: response.status, retryAfter, details: body }\n )\n }\n\n if (!body || typeof body !== \"object\") {\n throw new CloudError(\"Ingest config returned an empty response\", {\n status: response.status,\n })\n }\n return body as IngestConfig\n }\n\n function startFetch(): Promise<IngestConfig> {\n const promise = fetchConfig()\n promise.then(\n (config) => {\n resolvedConfig = config\n },\n () => {}\n )\n return promise\n }\n\n cachedConfig = startFetch()\n\n function getConfig(): Promise<IngestConfig> {\n return cachedConfig ?? (cachedConfig = startFetch())\n }\n\n function getCachedConfig(): IngestConfig | null {\n return resolvedConfig\n }\n\n return {\n feedback: { submit },\n integrations: { getConfig, getCachedConfig },\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cloud/index.ts","../../src/cloud/client.ts","../../../api-client/src/client.gen.ts","../../../api-client/src/sdk.gen.ts","../../src/cloud/realtime.ts","../../src/cloud/types.ts"],"sourcesContent":["export { cloud } from \"./client\"\nexport { createRealtimeChannel } from \"./realtime\"\nexport {\n CloudError,\n DEFAULT_CLOUD_ENDPOINT,\n type CloudAdapter,\n type CloudOptions,\n type RealtimeChannel,\n type RealtimeChannelState,\n type RealtimeConnectOpts,\n type RealtimePresenceUser,\n} from \"./types\"\nexport type {\n ArchiveReason,\n ReportListRecord,\n ReportListResponse,\n ReportPayload,\n ReportResult,\n IngestConfig,\n PinRecord,\n} from \"@uidex/api-client\"\n","import { createClient, createConfig } from \"@hey-api/client-fetch\"\nimport {\n submitReport as submitReportSdk,\n getIngestConfig as getIngestConfigSdk,\n listIngestReports as listIngestReportsSdk,\n listPins as listPinsSdk,\n archivePin as archivePinSdk,\n} from \"@uidex/api-client\"\nimport { createRealtimeChannel } from \"./realtime\"\nimport {\n CloudError,\n DEFAULT_CLOUD_ENDPOINT,\n type ArchiveReason,\n type CloudAdapter,\n type CloudOptions,\n type ReportListResponse,\n type ReportPayload,\n type ReportResult,\n type IngestConfig,\n type PinRecord,\n type RealtimeChannel,\n type RealtimeConnectOpts,\n} from \"./types\"\n\nfunction trimEndpoint(endpoint: string): string {\n return endpoint.endsWith(\"/\") ? endpoint.slice(0, -1) : endpoint\n}\n\nfunction unwrap<T>(result: {\n data?: T\n error?: unknown\n response: Response\n}): T {\n if (result.error !== undefined || !result.data) {\n const status = result.response.status\n const retryAfter =\n status === 429\n ? parseRetryAfter(result.response.headers.get(\"Retry-After\"))\n : undefined\n const msg =\n result.error &&\n typeof result.error === \"object\" &&\n \"error\" in result.error &&\n typeof (result.error as { error: unknown }).error === \"string\"\n ? (result.error as { error: string }).error\n : `Request failed (${status})`\n throw new CloudError(msg, { status, retryAfter, details: result.error })\n }\n return result.data\n}\n\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined\n const seconds = Number(header)\n if (Number.isFinite(seconds) && seconds >= 0) return seconds\n const date = Date.parse(header)\n if (Number.isFinite(date)) {\n const delta = Math.ceil((date - Date.now()) / 1000)\n return delta > 0 ? delta : 0\n }\n return undefined\n}\n\nexport function cloud(options: CloudOptions): CloudAdapter {\n let cachedConfig: Promise<IngestConfig> | null = null\n let resolvedConfig: IngestConfig | null = null\n\n const projectKey = options.projectKey\n if (!projectKey) {\n throw new Error(\"uidex/cloud: `projectKey` is required\")\n }\n const endpoint = trimEndpoint(options.endpoint ?? DEFAULT_CLOUD_ENDPOINT)\n const git = options.git\n\n const apiClient = createClient(\n createConfig({\n baseUrl: endpoint,\n ...(options.fetch ? { fetch: options.fetch } : {}),\n headers: { Authorization: `Bearer ${projectKey}` },\n })\n )\n\n async function submit(payload: ReportPayload): Promise<ReportResult> {\n const enriched =\n git?.branch || git?.commit\n ? {\n ...payload,\n context: {\n ...payload.context,\n git: payload.context?.git ?? {\n branch: git.branch,\n commit: git.commit,\n },\n },\n }\n : payload\n const result = await submitReportSdk({\n client: apiClient,\n body: enriched as Parameters<typeof submitReportSdk>[0][\"body\"],\n })\n return unwrap(result) as ReportResult\n }\n\n async function fetchConfig(): Promise<IngestConfig> {\n const result = await getIngestConfigSdk({ client: apiClient })\n return unwrap(result) as IngestConfig\n }\n\n function startFetch(): Promise<IngestConfig> {\n const promise = fetchConfig()\n promise.then(\n (config) => {\n resolvedConfig = config\n },\n () => {}\n )\n return promise\n }\n\n cachedConfig = startFetch()\n\n function getConfig(): Promise<IngestConfig> {\n return cachedConfig ?? (cachedConfig = startFetch())\n }\n\n function getCachedConfig(): IngestConfig | null {\n return resolvedConfig\n }\n\n function realtimeUrl(\n route: string,\n user: RealtimeConnectOpts[\"user\"]\n ): string {\n const httpToWs = endpoint\n .replace(/^http:/, \"ws:\")\n .replace(/^https:/, \"wss:\")\n const params = new URLSearchParams()\n params.set(\"key\", projectKey)\n params.set(\"route\", route)\n params.set(\"userId\", user.id)\n if (user.name) params.set(\"name\", user.name)\n if (user.avatar) params.set(\"avatar\", user.avatar)\n return `${httpToWs}/ws?${params.toString()}`\n }\n\n function connectRealtime(opts: RealtimeConnectOpts): RealtimeChannel {\n if (!opts || !opts.user || typeof opts.user.id !== \"string\") {\n throw new TypeError(\"uidex/cloud: realtime.connect requires `user.id`\")\n }\n let currentRoute = opts.route\n const channel = createRealtimeChannel({\n buildUrl: () => realtimeUrl(currentRoute, opts.user),\n })\n const originalJoinRoute = channel.joinRoute\n const wrapped: RealtimeChannel = {\n get state() {\n return channel.state\n },\n connect: () => channel.connect(),\n disconnect: () => channel.disconnect(),\n joinRoute: (route: string) => {\n currentRoute = route\n originalJoinRoute(route)\n },\n onPresence: (cb) => channel.onPresence(cb),\n onPin: (cb) => channel.onPin(cb),\n }\n channel.connect()\n return wrapped\n }\n\n async function listPins(params: {\n route?: string\n entities?: string\n }): Promise<PinRecord[]> {\n const result = await listPinsSdk({\n client: apiClient,\n query: params,\n })\n const data = unwrap(result)\n return data.pins\n }\n\n async function archivePin(\n reportId: string,\n reason?: ArchiveReason\n ): Promise<void> {\n const result = await archivePinSdk({\n client: apiClient,\n body: { reportId, ...(reason ? { reason } : {}) },\n })\n unwrap(result)\n }\n\n async function listReports(opts?: {\n page?: number\n limit?: number\n }): Promise<ReportListResponse> {\n const result = await listIngestReportsSdk({\n client: apiClient,\n query: opts,\n })\n return unwrap(result) as ReportListResponse\n }\n\n return {\n reports: { submit, list: listReports },\n integrations: { getConfig, getCachedConfig },\n realtime: { connect: connectRealtime },\n pins: { list: listPins, archive: archivePin },\n }\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { ClientOptions } from \"./types.gen\"\nimport {\n type Config,\n type ClientOptions as DefaultClientOptions,\n createClient,\n createConfig,\n} from \"@hey-api/client-fetch\"\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> =\n (\n override?: Config<DefaultClientOptions & T>\n ) => Config<Required<DefaultClientOptions> & T>\n\nexport const client = createClient(\n createConfig<ClientOptions>({\n baseUrl: \"https://app.uidex.dev\",\n })\n)\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type {\n Options as ClientOptions,\n TDataShape,\n Client,\n} from \"@hey-api/client-fetch\"\nimport type {\n SubmitReportData,\n SubmitReportResponse,\n SubmitReportError,\n GetIngestConfigData,\n GetIngestConfigResponse,\n ListIngestReportsData,\n ListIngestReportsResponse,\n ListPinsData,\n ListPinsResponse,\n ListPinsError,\n ArchivePinData,\n ArchivePinResponse,\n ArchivePinError,\n AuthorizeCliData,\n AuthorizeCliResponse,\n AuthorizeCliError,\n ListOrganizationsData,\n ListOrganizationsResponse,\n CreateOrganizationData,\n CreateOrganizationResponse,\n CreateOrganizationError,\n SwitchOrganizationData,\n SwitchOrganizationResponse,\n DeleteOrganizationData,\n DeleteOrganizationResponse,\n GetOrganizationData,\n GetOrganizationResponse,\n GetOrganizationError,\n UpdateOrganizationData,\n UpdateOrganizationResponse,\n RemoveMemberData,\n RemoveMemberResponse,\n RemoveMemberError,\n ListMembersData,\n ListMembersResponse,\n UpdateMemberData,\n UpdateMemberResponse,\n UpdateMemberError,\n ListInvitationsData,\n ListInvitationsResponse,\n CreateInvitationData,\n CreateInvitationResponse,\n DeleteInvitationData,\n DeleteInvitationResponse,\n DeleteInvitationError,\n ListProjectsData,\n ListProjectsResponse,\n CreateProjectData,\n CreateProjectResponse,\n CreateProjectError,\n DeleteProjectData,\n DeleteProjectResponse,\n GetProjectData,\n GetProjectResponse,\n GetProjectError,\n UpdateProjectData,\n UpdateProjectResponse,\n UpdateProjectError,\n ResolveProjectData,\n ResolveProjectResponse,\n ResolveProjectError,\n ListApiKeysData,\n ListApiKeysResponse,\n CreateApiKeyData,\n CreateApiKeyResponse,\n CreateApiKeyError,\n DeleteApiKeyData,\n DeleteApiKeyResponse,\n DeleteApiKeyError,\n RevokeApiKeyData,\n RevokeApiKeyResponse,\n RevokeApiKeyError,\n ListProjectReportsData,\n ListProjectReportsResponse,\n DeleteReportData,\n DeleteReportResponse,\n DeleteReportError,\n GetReportData,\n GetReportResponse,\n GetReportError,\n UpdateReportData,\n UpdateReportResponse,\n BulkArchiveReportData,\n BulkArchiveReportResponse,\n ListIntegrationsData,\n ListIntegrationsResponse,\n CreateIntegrationData,\n CreateIntegrationResponse,\n CreateIntegrationError,\n DeleteIntegrationData,\n DeleteIntegrationResponse,\n DeleteIntegrationError,\n GetIntegrationData,\n GetIntegrationResponse,\n GetIntegrationError,\n ListIntegrationTargetsData,\n ListIntegrationTargetsResponse,\n TestIntegrationData,\n TestIntegrationResponse,\n ListExternalIssuesData,\n ListExternalIssuesResponse,\n ListIssueDraftsData,\n ListIssueDraftsResponse,\n CreateIssueDraftData,\n CreateIssueDraftResponse,\n CreateIssueDraftError,\n DeleteIssueDraftData,\n DeleteIssueDraftResponse,\n DeleteIssueDraftError,\n UpdateIssueDraftData,\n UpdateIssueDraftResponse,\n UpdateIssueDraftError,\n SubmitIssueDraftData,\n SubmitIssueDraftResponse,\n SubmitIssueDraftError,\n RunTriageData,\n RunTriageResponse,\n RunTriageError,\n ListUserTokensData,\n ListUserTokensResponse,\n CreateUserTokenData,\n CreateUserTokenResponse,\n CreateUserTokenError,\n DeleteUserTokenData,\n DeleteUserTokenResponse,\n DeleteUserTokenError,\n} from \"./types.gen\"\nimport { client as _heyApiClient } from \"./client.gen\"\n\nexport type Options<\n TData extends TDataShape = TDataShape,\n ThrowOnError extends boolean = boolean,\n> = ClientOptions<TData, ThrowOnError> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: Record<string, unknown>\n}\n\n/**\n * Submit feedback from the SDK.\n */\nexport const submitReport = <ThrowOnError extends boolean = false>(\n options: Options<SubmitReportData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n SubmitReportResponse,\n SubmitReportError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/ingest\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Get integration configuration for the project.\n */\nexport const getIngestConfig = <ThrowOnError extends boolean = false>(\n options?: Options<GetIngestConfigData, ThrowOnError>\n) => {\n return (options?.client ?? _heyApiClient).get<\n GetIngestConfigResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/ingest/config\",\n ...options,\n })\n}\n\n/**\n * List feedback for the project (SDK view).\n */\nexport const listIngestReports = <ThrowOnError extends boolean = false>(\n options?: Options<ListIngestReportsData, ThrowOnError>\n) => {\n return (options?.client ?? _heyApiClient).get<\n ListIngestReportsResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/ingest/reports\",\n ...options,\n })\n}\n\n/**\n * List pins by route and/or entity.\n * At least one of `route` or `entities` must be provided.\n */\nexport const listPins = <ThrowOnError extends boolean = false>(\n options?: Options<ListPinsData, ThrowOnError>\n) => {\n return (options?.client ?? _heyApiClient).get<\n ListPinsResponse,\n ListPinsError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/ingest/pins\",\n ...options,\n })\n}\n\n/**\n * Archive a pin.\n */\nexport const archivePin = <ThrowOnError extends boolean = false>(\n options: Options<ArchivePinData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n ArchivePinResponse,\n ArchivePinError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/ingest/pins/archive\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Authorize a CLI session by delivering a token.\n */\nexport const authorizeCli = <ThrowOnError extends boolean = false>(\n options: Options<AuthorizeCliData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n AuthorizeCliResponse,\n AuthorizeCliError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/cli-auth/authorize\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * List organizations for the current user.\n */\nexport const listOrganizations = <ThrowOnError extends boolean = false>(\n options?: Options<ListOrganizationsData, ThrowOnError>\n) => {\n return (options?.client ?? _heyApiClient).get<\n ListOrganizationsResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations\",\n ...options,\n })\n}\n\n/**\n * Create an organization.\n */\nexport const createOrganization = <ThrowOnError extends boolean = false>(\n options: Options<CreateOrganizationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n CreateOrganizationResponse,\n CreateOrganizationError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Switch the active organization.\n */\nexport const switchOrganization = <ThrowOnError extends boolean = false>(\n options: Options<SwitchOrganizationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n SwitchOrganizationResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/switch\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Delete an organization.\n */\nexport const deleteOrganization = <ThrowOnError extends boolean = false>(\n options: Options<DeleteOrganizationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).delete<\n DeleteOrganizationResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}\",\n ...options,\n })\n}\n\n/**\n * Get organization details.\n */\nexport const getOrganization = <ThrowOnError extends boolean = false>(\n options: Options<GetOrganizationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n GetOrganizationResponse,\n GetOrganizationError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}\",\n ...options,\n })\n}\n\n/**\n * Update an organization.\n */\nexport const updateOrganization = <ThrowOnError extends boolean = false>(\n options: Options<UpdateOrganizationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).patch<\n UpdateOrganizationResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Remove a member from the organization.\n */\nexport const removeMember = <ThrowOnError extends boolean = false>(\n options: Options<RemoveMemberData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).delete<\n RemoveMemberResponse,\n RemoveMemberError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/members\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * List organization members.\n */\nexport const listMembers = <ThrowOnError extends boolean = false>(\n options: Options<ListMembersData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n ListMembersResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/members\",\n ...options,\n })\n}\n\n/**\n * Update a member's role.\n */\nexport const updateMember = <ThrowOnError extends boolean = false>(\n options: Options<UpdateMemberData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).patch<\n UpdateMemberResponse,\n UpdateMemberError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/members/{memberId}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * List organization invitations.\n */\nexport const listInvitations = <ThrowOnError extends boolean = false>(\n options: Options<ListInvitationsData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n ListInvitationsResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/invitations\",\n ...options,\n })\n}\n\n/**\n * Create an invitation link.\n */\nexport const createInvitation = <ThrowOnError extends boolean = false>(\n options: Options<CreateInvitationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n CreateInvitationResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/invitations\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Revoke an invitation.\n */\nexport const deleteInvitation = <ThrowOnError extends boolean = false>(\n options: Options<DeleteInvitationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).delete<\n DeleteInvitationResponse,\n DeleteInvitationError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/invitations/{inviteId}\",\n ...options,\n })\n}\n\n/**\n * List projects in an organization.\n */\nexport const listProjects = <ThrowOnError extends boolean = false>(\n options: Options<ListProjectsData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n ListProjectsResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects\",\n ...options,\n })\n}\n\n/**\n * Create a project.\n */\nexport const createProject = <ThrowOnError extends boolean = false>(\n options: Options<CreateProjectData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n CreateProjectResponse,\n CreateProjectError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Delete a project.\n */\nexport const deleteProject = <ThrowOnError extends boolean = false>(\n options: Options<DeleteProjectData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).delete<\n DeleteProjectResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}\",\n ...options,\n })\n}\n\n/**\n * Get project details.\n */\nexport const getProject = <ThrowOnError extends boolean = false>(\n options: Options<GetProjectData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n GetProjectResponse,\n GetProjectError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}\",\n ...options,\n })\n}\n\n/**\n * Update a project.\n */\nexport const updateProject = <ThrowOnError extends boolean = false>(\n options: Options<UpdateProjectData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).patch<\n UpdateProjectResponse,\n UpdateProjectError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Resolve an API key to its project and organization.\n */\nexport const resolveProject = <ThrowOnError extends boolean = false>(\n options: Options<ResolveProjectData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n ResolveProjectResponse,\n ResolveProjectError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/projects/resolve\",\n ...options,\n })\n}\n\n/**\n * List API keys for a project.\n */\nexport const listApiKeys = <ThrowOnError extends boolean = false>(\n options: Options<ListApiKeysData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n ListApiKeysResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}/api-keys\",\n ...options,\n })\n}\n\n/**\n * Create an API key.\n */\nexport const createApiKey = <ThrowOnError extends boolean = false>(\n options: Options<CreateApiKeyData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n CreateApiKeyResponse,\n CreateApiKeyError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}/api-keys\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Permanently delete an API key.\n */\nexport const deleteApiKey = <ThrowOnError extends boolean = false>(\n options: Options<DeleteApiKeyData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).delete<\n DeleteApiKeyResponse,\n DeleteApiKeyError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}/api-keys/{keyId}\",\n ...options,\n })\n}\n\n/**\n * Revoke an API key.\n */\nexport const revokeApiKey = <ThrowOnError extends boolean = false>(\n options: Options<RevokeApiKeyData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).patch<\n RevokeApiKeyResponse,\n RevokeApiKeyError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}/api-keys/{keyId}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * List feedback for a project.\n */\nexport const listProjectReports = <ThrowOnError extends boolean = false>(\n options: Options<ListProjectReportsData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n ListProjectReportsResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}/reports\",\n ...options,\n })\n}\n\n/**\n * Delete a feedback record.\n */\nexport const deleteReport = <ThrowOnError extends boolean = false>(\n options: Options<DeleteReportData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).delete<\n DeleteReportResponse,\n DeleteReportError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}/feedback/{reportId}\",\n ...options,\n })\n}\n\n/**\n * Get feedback details.\n */\nexport const getReport = <ThrowOnError extends boolean = false>(\n options: Options<GetReportData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n GetReportResponse,\n GetReportError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}/feedback/{reportId}\",\n ...options,\n })\n}\n\n/**\n * Update feedback status, priority, or assignment.\n */\nexport const updateReport = <ThrowOnError extends boolean = false>(\n options: Options<UpdateReportData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).patch<\n UpdateReportResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}/feedback/{reportId}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Archive multiple feedback records.\n */\nexport const bulkArchiveReport = <ThrowOnError extends boolean = false>(\n options: Options<BulkArchiveReportData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n BulkArchiveReportResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}/reports/archive\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * List integrations for an organization.\n */\nexport const listIntegrations = <ThrowOnError extends boolean = false>(\n options: Options<ListIntegrationsData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n ListIntegrationsResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/integrations\",\n ...options,\n })\n}\n\n/**\n * Create an integration.\n */\nexport const createIntegration = <ThrowOnError extends boolean = false>(\n options: Options<CreateIntegrationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n CreateIntegrationResponse,\n CreateIntegrationError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/integrations\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Delete an integration.\n */\nexport const deleteIntegration = <ThrowOnError extends boolean = false>(\n options: Options<DeleteIntegrationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).delete<\n DeleteIntegrationResponse,\n DeleteIntegrationError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/integrations/{integrationId}\",\n ...options,\n })\n}\n\n/**\n * Get integration details.\n */\nexport const getIntegration = <ThrowOnError extends boolean = false>(\n options: Options<GetIntegrationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n GetIntegrationResponse,\n GetIntegrationError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/integrations/{integrationId}\",\n ...options,\n })\n}\n\n/**\n * List available targets (e.g. Jira projects/boards).\n */\nexport const listIntegrationTargets = <ThrowOnError extends boolean = false>(\n options: Options<ListIntegrationTargetsData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n ListIntegrationTargetsResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/integrations/{integrationId}/targets\",\n ...options,\n })\n}\n\n/**\n * Test integration connectivity.\n */\nexport const testIntegration = <ThrowOnError extends boolean = false>(\n options: Options<TestIntegrationData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n TestIntegrationResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/integrations/{integrationId}/test\",\n ...options,\n })\n}\n\n/**\n * List external issues, optionally filtered by feedback.\n */\nexport const listExternalIssues = <ThrowOnError extends boolean = false>(\n options: Options<ListExternalIssuesData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n ListExternalIssuesResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/external-issues\",\n ...options,\n })\n}\n\n/**\n * List issue drafts for a project.\n */\nexport const listIssueDrafts = <ThrowOnError extends boolean = false>(\n options: Options<ListIssueDraftsData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).get<\n ListIssueDraftsResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/issue-drafts\",\n ...options,\n })\n}\n\n/**\n * Manually create an issue draft.\n */\nexport const createIssueDraft = <ThrowOnError extends boolean = false>(\n options: Options<CreateIssueDraftData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n CreateIssueDraftResponse,\n CreateIssueDraftError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/issue-drafts\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Delete an issue draft.\n */\nexport const deleteIssueDraft = <ThrowOnError extends boolean = false>(\n options: Options<DeleteIssueDraftData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).delete<\n DeleteIssueDraftResponse,\n DeleteIssueDraftError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/issue-drafts/{draftId}\",\n ...options,\n })\n}\n\n/**\n * Update an issue draft.\n */\nexport const updateIssueDraft = <ThrowOnError extends boolean = false>(\n options: Options<UpdateIssueDraftData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).patch<\n UpdateIssueDraftResponse,\n UpdateIssueDraftError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/issue-drafts/{draftId}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Submit a draft to the configured integration.\n */\nexport const submitIssueDraft = <ThrowOnError extends boolean = false>(\n options: Options<SubmitIssueDraftData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n SubmitIssueDraftResponse,\n SubmitIssueDraftError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/issue-drafts/{draftId}/submit\",\n ...options,\n })\n}\n\n/**\n * Run LLM-powered triage on untriaged feedback.\n */\nexport const runTriage = <ThrowOnError extends boolean = false>(\n options: Options<RunTriageData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n RunTriageResponse,\n RunTriageError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/organizations/{orgId}/projects/{projectId}/triage\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * List personal access tokens.\n */\nexport const listUserTokens = <ThrowOnError extends boolean = false>(\n options?: Options<ListUserTokensData, ThrowOnError>\n) => {\n return (options?.client ?? _heyApiClient).get<\n ListUserTokensResponse,\n unknown,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/user/tokens\",\n ...options,\n })\n}\n\n/**\n * Create a personal access token.\n */\nexport const createUserToken = <ThrowOnError extends boolean = false>(\n options: Options<CreateUserTokenData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).post<\n CreateUserTokenResponse,\n CreateUserTokenError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/user/tokens\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n })\n}\n\n/**\n * Revoke and delete a personal access token.\n */\nexport const deleteUserToken = <ThrowOnError extends boolean = false>(\n options: Options<DeleteUserTokenData, ThrowOnError>\n) => {\n return (options.client ?? _heyApiClient).delete<\n DeleteUserTokenResponse,\n DeleteUserTokenError,\n ThrowOnError\n >({\n security: [\n {\n scheme: \"bearer\",\n type: \"http\",\n },\n ],\n url: \"/api/user/tokens/{tokenId}\",\n ...options,\n })\n}\n","import type { PinRecord } from \"@uidex/api-client\"\nimport type {\n RealtimeChannel,\n RealtimeChannelState,\n RealtimePresenceUser,\n} from \"./types\"\n\nconst RECONNECT_INITIAL_MS = 1000\nconst RECONNECT_MAX_MS = 30_000\nconst CLOSE_CODE_AUTH_FAILED = 4001\n\nexport type RealtimeChannelOptions = {\n /** Builds the WebSocket URL on each (re)connect attempt. Allows the caller to refresh `route` query params. */\n buildUrl: () => string\n /** Optional WebSocket constructor override (testing). Defaults to `globalThis.WebSocket`. */\n WebSocketImpl?: typeof WebSocket\n}\n\ntype Listener<T> = (value: T) => void\n\nfunction emit<T>(listeners: Set<Listener<T>>, value: T): void {\n for (const cb of listeners) {\n try {\n cb(value)\n } catch {\n // listener errors must not break the channel\n }\n }\n}\n\nfunction resolveWebSocket(override?: typeof WebSocket): typeof WebSocket {\n if (override) return override\n if (\n typeof globalThis !== \"undefined\" &&\n typeof (globalThis as { WebSocket?: typeof WebSocket }).WebSocket ===\n \"function\"\n ) {\n return (globalThis as { WebSocket: typeof WebSocket }).WebSocket\n }\n throw new Error(\n \"uidex/cloud: global WebSocket is not available; pass a `WebSocketImpl` override\"\n )\n}\n\nexport function createRealtimeChannel(\n options: RealtimeChannelOptions\n): RealtimeChannel {\n const WS = resolveWebSocket(options.WebSocketImpl)\n\n const presenceListeners = new Set<Listener<RealtimePresenceUser[]>>()\n const pinListeners = new Set<Listener<PinRecord>>()\n\n let ws: WebSocket | null = null\n let state: RealtimeChannelState = \"disconnected\"\n let disposed = false\n let reconnectAttempts = 0\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n\n function clearReconnectTimer(): void {\n if (reconnectTimer !== null) {\n clearTimeout(reconnectTimer)\n reconnectTimer = null\n }\n }\n\n function scheduleReconnect(): void {\n if (disposed) return\n const delay = Math.min(\n RECONNECT_INITIAL_MS * 2 ** reconnectAttempts,\n RECONNECT_MAX_MS\n )\n reconnectAttempts += 1\n state = \"connecting\"\n clearReconnectTimer()\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null\n openSocket()\n }, delay)\n }\n\n function handleMessage(event: MessageEvent): void {\n if (typeof event.data !== \"string\") return\n let parsed: unknown\n try {\n parsed = JSON.parse(event.data)\n } catch {\n return\n }\n if (!parsed || typeof parsed !== \"object\") return\n const msg = parsed as { type?: unknown }\n\n if (msg.type === \"presence\") {\n const p = msg as { users?: unknown }\n if (!Array.isArray(p.users)) return\n const users: RealtimePresenceUser[] = []\n for (const raw of p.users) {\n if (!raw || typeof raw !== \"object\") continue\n const u = raw as Partial<RealtimePresenceUser>\n if (typeof u.userId !== \"string\" || typeof u.name !== \"string\") continue\n users.push({\n userId: u.userId,\n name: u.name,\n avatar: typeof u.avatar === \"string\" ? u.avatar : null,\n })\n }\n emit(presenceListeners, users)\n return\n }\n\n if (msg.type === \"pin\") {\n // Wire format uses legacy field names; map to API PinRecord shape\n const p = msg as Record<string, unknown>\n if (\n typeof p.feedbackId !== \"string\" ||\n !p.elementRef ||\n typeof p.elementRef !== \"object\" ||\n typeof (p.elementRef as { kind?: unknown }).kind !== \"string\" ||\n typeof (p.elementRef as { id?: unknown }).id !== \"string\" ||\n !p.author ||\n typeof p.author !== \"object\" ||\n typeof p.body !== \"string\" ||\n typeof p.reportType !== \"string\" ||\n typeof p.reportSeverity !== \"string\" ||\n typeof p.createdAt !== \"string\"\n ) {\n return\n }\n const author = p.author as Record<string, unknown>\n const elRef = p.elementRef as { kind: string; id: string }\n const pin: PinRecord = {\n id: p.feedbackId,\n entity: `${elRef.kind}:${elRef.id}`,\n reporter: {\n name: typeof author.name === \"string\" ? author.name : undefined,\n email: typeof author.email === \"string\" ? author.email : undefined,\n },\n body: p.body,\n type: p.reportType as PinRecord[\"type\"],\n severity: p.reportSeverity as PinRecord[\"severity\"],\n status: \"open\" as PinRecord[\"status\"],\n createdAt: p.createdAt,\n url: \"\",\n }\n emit(pinListeners, pin)\n return\n }\n }\n\n function openSocket(): void {\n if (disposed) return\n state = \"connecting\"\n let url: string\n try {\n url = options.buildUrl()\n } catch {\n state = \"disconnected\"\n return\n }\n let socket: WebSocket\n try {\n socket = new WS(url)\n } catch {\n scheduleReconnect()\n return\n }\n ws = socket\n\n socket.addEventListener(\"open\", () => {\n if (ws !== socket) return\n state = \"connected\"\n reconnectAttempts = 0\n })\n\n socket.addEventListener(\"message\", (event) => {\n if (ws !== socket) return\n handleMessage(event as MessageEvent)\n })\n\n socket.addEventListener(\"close\", (event) => {\n if (ws !== socket) return\n ws = null\n const code = (event as CloseEvent).code\n if (disposed || code === CLOSE_CODE_AUTH_FAILED) {\n state = \"disconnected\"\n return\n }\n scheduleReconnect()\n })\n\n socket.addEventListener(\"error\", () => {\n // close fires after error; reconnect handled there\n })\n }\n\n function connect(): void {\n if (disposed) {\n disposed = false\n }\n if (ws) return\n if (state === \"connecting\") return\n reconnectAttempts = 0\n openSocket()\n }\n\n function disconnect(): void {\n disposed = true\n clearReconnectTimer()\n state = \"disconnected\"\n if (ws) {\n try {\n ws.close(1000)\n } catch {\n // ignore\n }\n ws = null\n }\n }\n\n function joinRoute(route: string): void {\n emit(presenceListeners, [])\n if (ws && ws.readyState === WS.OPEN) {\n try {\n ws.send(JSON.stringify({ type: \"join\", route }))\n } catch {\n // socket may have closed mid-call\n }\n }\n }\n\n function onPresence(cb: Listener<RealtimePresenceUser[]>): () => void {\n presenceListeners.add(cb)\n return () => {\n presenceListeners.delete(cb)\n }\n }\n\n function onPin(cb: Listener<PinRecord>): () => void {\n pinListeners.add(cb)\n return () => {\n pinListeners.delete(cb)\n }\n }\n\n return {\n get state() {\n return state\n },\n connect,\n disconnect,\n joinRoute,\n onPresence,\n onPin,\n }\n}\n","import type {\n ArchiveReason,\n ReportListResponse,\n ReportPayload,\n ReportResult,\n IngestConfig,\n PinRecord,\n} from \"@uidex/api-client\"\nimport type { UserIdentity } from \"../shared/user\"\n\nexport type {\n ArchiveReason,\n ReportListResponse,\n ReportPayload,\n ReportResult,\n IngestConfig,\n PinRecord,\n} from \"@uidex/api-client\"\n\nexport const DEFAULT_CLOUD_ENDPOINT = \"https://app.uidex.dev\"\n\nexport interface CloudOptions {\n projectKey: string\n endpoint?: string\n fetch?: typeof fetch\n git?: { branch?: string; commit?: string }\n}\n\nexport class CloudError extends Error {\n readonly status: number\n readonly retryAfter?: number\n readonly details?: unknown\n\n constructor(\n message: string,\n options: { status: number; retryAfter?: number; details?: unknown }\n ) {\n super(message)\n this.name = \"CloudError\"\n this.status = options.status\n this.retryAfter = options.retryAfter\n this.details = options.details\n }\n}\n\nexport type RealtimePresenceUser = {\n userId: string\n name: string\n avatar: string | null\n}\n\nexport type RealtimeChannelState = \"connecting\" | \"connected\" | \"disconnected\"\n\nexport interface RealtimeConnectOpts {\n user: UserIdentity\n route: string\n}\n\nexport interface RealtimeChannel {\n readonly state: RealtimeChannelState\n connect(): void\n disconnect(): void\n joinRoute(route: string): void\n onPresence(cb: (users: RealtimePresenceUser[]) => void): () => void\n onPin(cb: (pin: PinRecord) => void): () => void\n}\n\nexport interface CloudAdapter<\n TPayload = ReportPayload,\n TResult = ReportResult,\n TIntegrations = {\n getConfig(): Promise<IngestConfig>\n getCachedConfig(): IngestConfig | null\n },\n> {\n readonly reports: {\n submit(payload: TPayload): Promise<TResult>\n list?(opts?: { page?: number; limit?: number }): Promise<ReportListResponse>\n }\n readonly integrations: TIntegrations\n readonly realtime: {\n connect(opts: RealtimeConnectOpts): RealtimeChannel\n }\n readonly pins: {\n list(params: { route?: string; entities?: string }): Promise<PinRecord[]>\n archive(reportId: string, reason?: ArchiveReason): Promise<void>\n }\n}\n"],"mappings":"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","names":["import_client_fetch","listPins","archivePin"]}
|