@parcae/sdk 0.3.3 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-DAHSIKBD.js +845 -0
- package/dist/chunk-DAHSIKBD.js.map +1 -0
- package/dist/client-0OLcV8PA.d.ts +38 -0
- package/dist/index.d.ts +41 -23
- package/dist/index.js +1 -1
- package/dist/react/index.d.ts +11 -28
- package/dist/react/index.js +103 -85
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-IETH2XOR.js +0 -432
- package/dist/chunk-IETH2XOR.js.map +0 -1
- package/dist/client-uWUdynht.d.ts +0 -63
package/dist/chunk-IETH2XOR.js
DELETED
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
import SocketIO from 'socket.io-client';
|
|
2
|
-
import pako from 'pako';
|
|
3
|
-
import { decompress } from 'compress-json';
|
|
4
|
-
import { EventEmitter } from 'eventemitter3';
|
|
5
|
-
import ShortId from 'short-unique-id';
|
|
6
|
-
import { Model, FrontendAdapter } from '@parcae/model';
|
|
7
|
-
|
|
8
|
-
// src/transports/socket.ts
|
|
9
|
-
var uid = new ShortId({ length: 10 });
|
|
10
|
-
var SOCKET_CONNECTIONS = /* @__PURE__ */ new Map();
|
|
11
|
-
var SocketTransport = class extends EventEmitter {
|
|
12
|
-
socket = null;
|
|
13
|
-
pendingHandlers = [];
|
|
14
|
-
apiKey;
|
|
15
|
-
key = null;
|
|
16
|
-
url;
|
|
17
|
-
version;
|
|
18
|
-
socketPath;
|
|
19
|
-
waitForAuth = null;
|
|
20
|
-
resolveAuth = null;
|
|
21
|
-
inflight = /* @__PURE__ */ new Map();
|
|
22
|
-
loading;
|
|
23
|
-
isLoading = true;
|
|
24
|
-
isConnected = false;
|
|
25
|
-
isConnecting = false;
|
|
26
|
-
authVersion = 0;
|
|
27
|
-
constructor(config) {
|
|
28
|
-
super();
|
|
29
|
-
this.url = config.url;
|
|
30
|
-
this.apiKey = config.key ?? null;
|
|
31
|
-
this.version = config.version ?? "v1";
|
|
32
|
-
this.socketPath = config.path ?? "/ws";
|
|
33
|
-
this.loading = this.init(this.apiKey);
|
|
34
|
-
}
|
|
35
|
-
// ── Auth ──────────────────────────────────────────────────────────────
|
|
36
|
-
async setKey(key) {
|
|
37
|
-
this.apiKey = key;
|
|
38
|
-
this.isLoading = true;
|
|
39
|
-
this.loading = this.init(key);
|
|
40
|
-
await this.loading;
|
|
41
|
-
}
|
|
42
|
-
// ── Init ──────────────────────────────────────────────────────────────
|
|
43
|
-
async init(key) {
|
|
44
|
-
this.isLoading = true;
|
|
45
|
-
this.isConnecting = true;
|
|
46
|
-
try {
|
|
47
|
-
this.key = typeof key === "function" ? await key() : key;
|
|
48
|
-
const socketKey = `${this.url}:${this.version}`;
|
|
49
|
-
if (!SOCKET_CONNECTIONS.has(socketKey)) {
|
|
50
|
-
SOCKET_CONNECTIONS.set(
|
|
51
|
-
socketKey,
|
|
52
|
-
SocketIO(this.url, {
|
|
53
|
-
path: this.socketPath,
|
|
54
|
-
agent: true,
|
|
55
|
-
transports: ["websocket"],
|
|
56
|
-
withCredentials: true,
|
|
57
|
-
query: { key: this.key ?? void 0, compression: true }
|
|
58
|
-
})
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
this.socket = SOCKET_CONNECTIONS.get(socketKey);
|
|
62
|
-
if (this.key) {
|
|
63
|
-
const prevResolve = this.resolveAuth;
|
|
64
|
-
this.waitForAuth = new Promise((resolve) => {
|
|
65
|
-
this.resolveAuth = resolve;
|
|
66
|
-
this.socket.emit("authenticate", this.key, () => {
|
|
67
|
-
this.waitForAuth = null;
|
|
68
|
-
this.resolveAuth = null;
|
|
69
|
-
this.authVersion++;
|
|
70
|
-
this.emit("authenticated");
|
|
71
|
-
if (prevResolve) prevResolve();
|
|
72
|
-
resolve();
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
} else {
|
|
76
|
-
this.waitForAuth = null;
|
|
77
|
-
this.resolveAuth = null;
|
|
78
|
-
}
|
|
79
|
-
this.isLoading = false;
|
|
80
|
-
} catch (error) {
|
|
81
|
-
this.isLoading = false;
|
|
82
|
-
this.isConnecting = false;
|
|
83
|
-
this.emit("error", error);
|
|
84
|
-
throw error;
|
|
85
|
-
}
|
|
86
|
-
this.setupEvents();
|
|
87
|
-
}
|
|
88
|
-
setupEvents() {
|
|
89
|
-
if (!this.socket) return;
|
|
90
|
-
for (const { event, handler } of this.pendingHandlers) {
|
|
91
|
-
this.socket.on(event, handler);
|
|
92
|
-
}
|
|
93
|
-
this.pendingHandlers = [];
|
|
94
|
-
let hasConnected = this.isConnected;
|
|
95
|
-
this.socket.off("connect");
|
|
96
|
-
this.socket.off("disconnect");
|
|
97
|
-
this.socket.off("error");
|
|
98
|
-
this.socket.on("connect", () => {
|
|
99
|
-
const wasDisconnected = !this.isConnected && hasConnected;
|
|
100
|
-
this.isConnected = true;
|
|
101
|
-
this.isConnecting = false;
|
|
102
|
-
hasConnected = true;
|
|
103
|
-
if (wasDisconnected && this.key) {
|
|
104
|
-
this.socket.emit("authenticate", this.key, () => {
|
|
105
|
-
this.emit("reconnected");
|
|
106
|
-
});
|
|
107
|
-
} else {
|
|
108
|
-
this.emit(wasDisconnected ? "reconnected" : "connected");
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
this.socket.on("disconnect", () => {
|
|
112
|
-
this.isConnected = false;
|
|
113
|
-
this.emit("disconnected");
|
|
114
|
-
});
|
|
115
|
-
this.socket.on("error", (error) => {
|
|
116
|
-
this.emit("error", error);
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
// ── Request/Response ──────────────────────────────────────────────────
|
|
120
|
-
async fetch(method, path, data = {}) {
|
|
121
|
-
await this.loading;
|
|
122
|
-
if (this.waitForAuth) await this.waitForAuth;
|
|
123
|
-
if (!this.socket) throw new Error("Socket not initialized");
|
|
124
|
-
const upper = method.toUpperCase();
|
|
125
|
-
if (upper === "GET") {
|
|
126
|
-
const dedupeKey = `GET:${path}:${this.authVersion}:${JSON.stringify(data)}`;
|
|
127
|
-
const existing = this.inflight.get(dedupeKey);
|
|
128
|
-
if (existing) return existing;
|
|
129
|
-
const req = this._doFetch(method, path, data);
|
|
130
|
-
this.inflight.set(dedupeKey, req);
|
|
131
|
-
req.finally(() => this.inflight.delete(dedupeKey));
|
|
132
|
-
return req;
|
|
133
|
-
}
|
|
134
|
-
return this._doFetch(method, path, data);
|
|
135
|
-
}
|
|
136
|
-
async _doFetch(method, path, data = {}) {
|
|
137
|
-
if (!this.isConnected) {
|
|
138
|
-
await new Promise((resolve, reject) => {
|
|
139
|
-
if (this.socket.connected) return resolve();
|
|
140
|
-
const timeout = setTimeout(() => {
|
|
141
|
-
cleanup();
|
|
142
|
-
reject(new Error("Connection timeout"));
|
|
143
|
-
}, 3e4);
|
|
144
|
-
const onConnect = () => {
|
|
145
|
-
cleanup();
|
|
146
|
-
resolve();
|
|
147
|
-
};
|
|
148
|
-
const onError = (err) => {
|
|
149
|
-
cleanup();
|
|
150
|
-
reject(new Error(`Connection failed: ${err.message}`));
|
|
151
|
-
};
|
|
152
|
-
const cleanup = () => {
|
|
153
|
-
clearTimeout(timeout);
|
|
154
|
-
this.socket.off("connect", onConnect);
|
|
155
|
-
this.socket.off("connect_error", onError);
|
|
156
|
-
};
|
|
157
|
-
this.socket.once("connect", onConnect);
|
|
158
|
-
this.socket.once("connect_error", onError);
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
const id = uid.rnd();
|
|
162
|
-
return new Promise((resolve, reject) => {
|
|
163
|
-
this.socket.once(id, (msg) => {
|
|
164
|
-
try {
|
|
165
|
-
const uncompressed = pako.ungzip(msg, { to: "string" });
|
|
166
|
-
const { success, result, message, error } = decompress(
|
|
167
|
-
JSON.parse(uncompressed)
|
|
168
|
-
);
|
|
169
|
-
if (success) resolve(result);
|
|
170
|
-
else
|
|
171
|
-
reject(
|
|
172
|
-
new Error(
|
|
173
|
-
message || error || `Request failed: ${method}:${path}`
|
|
174
|
-
)
|
|
175
|
-
);
|
|
176
|
-
} catch (err) {
|
|
177
|
-
reject(err);
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
this.socket.emit(
|
|
181
|
-
"call",
|
|
182
|
-
id,
|
|
183
|
-
method.toUpperCase(),
|
|
184
|
-
`/${this.version}${path}`,
|
|
185
|
-
data
|
|
186
|
-
);
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
async get(path, data) {
|
|
190
|
-
return this.fetch("get", path, data);
|
|
191
|
-
}
|
|
192
|
-
async post(path, data) {
|
|
193
|
-
return this.fetch("post", path, data);
|
|
194
|
-
}
|
|
195
|
-
async put(path, data) {
|
|
196
|
-
return this.fetch("put", path, data);
|
|
197
|
-
}
|
|
198
|
-
async patch(path, data) {
|
|
199
|
-
return this.fetch("patch", path, data);
|
|
200
|
-
}
|
|
201
|
-
async delete(path, data) {
|
|
202
|
-
return this.fetch("delete", path, data);
|
|
203
|
-
}
|
|
204
|
-
// ── Subscriptions ─────────────────────────────────────────────────────
|
|
205
|
-
subscribe(event, handler) {
|
|
206
|
-
if (this.socket) {
|
|
207
|
-
this.socket.on(event, handler);
|
|
208
|
-
} else {
|
|
209
|
-
this.pendingHandlers.push({ event, handler });
|
|
210
|
-
}
|
|
211
|
-
return () => this.unsubscribe(event, handler);
|
|
212
|
-
}
|
|
213
|
-
unsubscribe(event, handler) {
|
|
214
|
-
if (this.socket) this.socket.off(event, handler);
|
|
215
|
-
this.pendingHandlers = this.pendingHandlers.filter(
|
|
216
|
-
(h) => !(h.event === event && (!handler || h.handler === handler))
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
// ── Control messages ──────────────────────────────────────────────────
|
|
220
|
-
async send(event, ...args) {
|
|
221
|
-
if (!this.isConnected && this.socket) {
|
|
222
|
-
await new Promise((resolve) => {
|
|
223
|
-
if (this.socket.connected) return resolve();
|
|
224
|
-
this.socket.once("connect", () => resolve());
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
if (this.waitForAuth) await this.waitForAuth;
|
|
228
|
-
if (this.socket) this.socket.emit(event, ...args);
|
|
229
|
-
}
|
|
230
|
-
// ── Lifecycle ─────────────────────────────────────────────────────────
|
|
231
|
-
disconnect() {
|
|
232
|
-
if (this.socket) {
|
|
233
|
-
this.socket.disconnect();
|
|
234
|
-
SOCKET_CONNECTIONS.delete(`${this.url}:${this.version}`);
|
|
235
|
-
this.socket = null;
|
|
236
|
-
this.isConnected = false;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
async reconnect() {
|
|
240
|
-
this.loading = this.init(this.apiKey);
|
|
241
|
-
await this.loading;
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
var SSETransport = class extends EventEmitter {
|
|
245
|
-
url;
|
|
246
|
-
version;
|
|
247
|
-
apiKey;
|
|
248
|
-
key = null;
|
|
249
|
-
eventSources = /* @__PURE__ */ new Map();
|
|
250
|
-
isConnected = true;
|
|
251
|
-
// HTTP is "always connected"
|
|
252
|
-
isLoading = true;
|
|
253
|
-
loading;
|
|
254
|
-
constructor(config) {
|
|
255
|
-
super();
|
|
256
|
-
this.url = config.url.replace(/\/$/, "");
|
|
257
|
-
this.version = config.version ?? "v1";
|
|
258
|
-
this.apiKey = config.key ?? null;
|
|
259
|
-
this.loading = this.resolveKey();
|
|
260
|
-
}
|
|
261
|
-
async resolveKey() {
|
|
262
|
-
try {
|
|
263
|
-
this.key = typeof this.apiKey === "function" ? await this.apiKey() : this.apiKey;
|
|
264
|
-
this.isLoading = false;
|
|
265
|
-
this.emit("connected");
|
|
266
|
-
} catch (err) {
|
|
267
|
-
this.isLoading = false;
|
|
268
|
-
this.emit("error", err);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
headers() {
|
|
272
|
-
const h = { "Content-Type": "application/json" };
|
|
273
|
-
if (this.key) h["Authorization"] = `Bearer ${this.key}`;
|
|
274
|
-
return h;
|
|
275
|
-
}
|
|
276
|
-
fullUrl(path) {
|
|
277
|
-
return `${this.url}/${this.version}${path}`;
|
|
278
|
-
}
|
|
279
|
-
// ── Request/Response ──────────────────────────────────────────────────
|
|
280
|
-
async request(method, path, data) {
|
|
281
|
-
await this.loading;
|
|
282
|
-
const isGet = method.toUpperCase() === "GET";
|
|
283
|
-
let url = this.fullUrl(path);
|
|
284
|
-
if (isGet && data) {
|
|
285
|
-
const params = new URLSearchParams();
|
|
286
|
-
for (const [k, v] of Object.entries(data)) {
|
|
287
|
-
params.set(k, typeof v === "object" ? JSON.stringify(v) : String(v));
|
|
288
|
-
}
|
|
289
|
-
url += `?${params.toString()}`;
|
|
290
|
-
}
|
|
291
|
-
const res = await fetch(url, {
|
|
292
|
-
method: method.toUpperCase(),
|
|
293
|
-
headers: this.headers(),
|
|
294
|
-
body: isGet ? void 0 : JSON.stringify(data)
|
|
295
|
-
});
|
|
296
|
-
if (!res.ok) {
|
|
297
|
-
const body2 = await res.json().catch(() => ({ error: res.statusText }));
|
|
298
|
-
throw new Error(body2.error || body2.message || `HTTP ${res.status}`);
|
|
299
|
-
}
|
|
300
|
-
const body = await res.json();
|
|
301
|
-
if (body.success === false) throw new Error(body.error || "Request failed");
|
|
302
|
-
return body.result ?? body;
|
|
303
|
-
}
|
|
304
|
-
async get(path, data) {
|
|
305
|
-
return this.request("GET", path, data);
|
|
306
|
-
}
|
|
307
|
-
async post(path, data) {
|
|
308
|
-
return this.request("POST", path, data);
|
|
309
|
-
}
|
|
310
|
-
async put(path, data) {
|
|
311
|
-
return this.request("PUT", path, data);
|
|
312
|
-
}
|
|
313
|
-
async patch(path, data) {
|
|
314
|
-
return this.request("PATCH", path, data);
|
|
315
|
-
}
|
|
316
|
-
async delete(path, data) {
|
|
317
|
-
return this.request("DELETE", path, data);
|
|
318
|
-
}
|
|
319
|
-
// ── Subscriptions (via Server-Sent Events) ────────────────────────────
|
|
320
|
-
subscribe(event, handler) {
|
|
321
|
-
const url = `${this.url}/${this.version}/__events/${encodeURIComponent(event)}`;
|
|
322
|
-
const source = new EventSource(url, { withCredentials: true });
|
|
323
|
-
source.onmessage = (e) => {
|
|
324
|
-
try {
|
|
325
|
-
const data = JSON.parse(e.data);
|
|
326
|
-
handler(data);
|
|
327
|
-
} catch {
|
|
328
|
-
handler(e.data);
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
source.onerror = () => {
|
|
332
|
-
};
|
|
333
|
-
this.eventSources.set(event, source);
|
|
334
|
-
return () => {
|
|
335
|
-
source.close();
|
|
336
|
-
this.eventSources.delete(event);
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
unsubscribe(event) {
|
|
340
|
-
const source = this.eventSources.get(event);
|
|
341
|
-
if (source) {
|
|
342
|
-
source.close();
|
|
343
|
-
this.eventSources.delete(event);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
// ── Control messages ──────────────────────────────────────────────────
|
|
347
|
-
async send(event, ...args) {
|
|
348
|
-
await this.request("POST", "/__control", { event, args });
|
|
349
|
-
}
|
|
350
|
-
// ── Lifecycle ─────────────────────────────────────────────────────────
|
|
351
|
-
disconnect() {
|
|
352
|
-
for (const [, source] of this.eventSources) source.close();
|
|
353
|
-
this.eventSources.clear();
|
|
354
|
-
this.isConnected = false;
|
|
355
|
-
this.emit("disconnected");
|
|
356
|
-
}
|
|
357
|
-
async reconnect() {
|
|
358
|
-
this.loading = this.resolveKey();
|
|
359
|
-
await this.loading;
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
function createClient(config) {
|
|
363
|
-
const version = config.version ?? "v1";
|
|
364
|
-
let transport;
|
|
365
|
-
if (config.transport && typeof config.transport === "object") {
|
|
366
|
-
transport = config.transport;
|
|
367
|
-
} else if (config.transport === "sse") {
|
|
368
|
-
transport = new SSETransport({
|
|
369
|
-
url: config.url,
|
|
370
|
-
key: config.key,
|
|
371
|
-
version
|
|
372
|
-
});
|
|
373
|
-
} else {
|
|
374
|
-
transport = new SocketTransport({
|
|
375
|
-
url: config.url,
|
|
376
|
-
key: config.key,
|
|
377
|
-
version
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
Model.use(new FrontendAdapter(transport));
|
|
381
|
-
const client = {
|
|
382
|
-
transport,
|
|
383
|
-
get: (path, data) => transport.get(path, data),
|
|
384
|
-
post: (path, data) => transport.post(path, data),
|
|
385
|
-
put: (path, data) => transport.put(path, data),
|
|
386
|
-
patch: (path, data) => transport.patch(path, data),
|
|
387
|
-
delete: (path, data) => transport.delete(path, data),
|
|
388
|
-
subscribe(event, handler) {
|
|
389
|
-
if (transport.subscribe) return transport.subscribe(event, handler);
|
|
390
|
-
return () => {
|
|
391
|
-
};
|
|
392
|
-
},
|
|
393
|
-
unsubscribe(event, handler) {
|
|
394
|
-
transport.unsubscribe?.(event, handler);
|
|
395
|
-
},
|
|
396
|
-
send(event, ...args) {
|
|
397
|
-
transport.send?.(event, ...args);
|
|
398
|
-
},
|
|
399
|
-
get isConnected() {
|
|
400
|
-
return transport.isConnected ?? false;
|
|
401
|
-
},
|
|
402
|
-
get isLoading() {
|
|
403
|
-
return transport.isLoading ?? false;
|
|
404
|
-
},
|
|
405
|
-
get loading() {
|
|
406
|
-
return transport.loading ?? Promise.resolve();
|
|
407
|
-
},
|
|
408
|
-
get authVersion() {
|
|
409
|
-
return transport.authVersion ?? 0;
|
|
410
|
-
},
|
|
411
|
-
async setKey(key) {
|
|
412
|
-
if (transport.setKey) await transport.setKey(key);
|
|
413
|
-
},
|
|
414
|
-
on(event, handler) {
|
|
415
|
-
transport.on?.(event, handler);
|
|
416
|
-
},
|
|
417
|
-
off(event, handler) {
|
|
418
|
-
transport.off?.(event, handler);
|
|
419
|
-
},
|
|
420
|
-
disconnect() {
|
|
421
|
-
transport.disconnect?.();
|
|
422
|
-
},
|
|
423
|
-
async reconnect() {
|
|
424
|
-
await transport.reconnect?.();
|
|
425
|
-
}
|
|
426
|
-
};
|
|
427
|
-
return client;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
export { SSETransport, SocketTransport, createClient };
|
|
431
|
-
//# sourceMappingURL=chunk-IETH2XOR.js.map
|
|
432
|
-
//# sourceMappingURL=chunk-IETH2XOR.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/transports/socket.ts","../src/transports/sse.ts","../src/client.ts"],"names":["EventEmitter","body"],"mappings":"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","file":"chunk-IETH2XOR.js","sourcesContent":["/**\n * SocketTransport — Socket.IO implementation of the Transport interface.\n *\n * Bidirectional, full-duplex. Best for apps that need realtime subscriptions\n * (live query updates, collaborative editing, chat, etc.).\n *\n * Extracted from Dollhouse Studio's Dollhouse.ts (667 lines).\n */\n\nimport SocketIO from \"socket.io-client\";\nimport pako from \"pako\";\nimport { decompress } from \"compress-json\";\nimport { EventEmitter } from \"eventemitter3\";\nimport ShortId from \"short-unique-id\";\nimport type { Transport } from \"@parcae/model\";\n\nconst uid = new ShortId({ length: 10 });\nconst SOCKET_CONNECTIONS = new Map<string, any>();\n\nexport interface SocketTransportConfig {\n url: string;\n key?: string | null | (() => Promise<string | null>);\n version?: string;\n /** Socket.IO path. Default: \"/ws\" */\n path?: string;\n}\n\nexport class SocketTransport extends EventEmitter implements Transport {\n private socket: any = null;\n private pendingHandlers: Array<{\n event: string;\n handler: (...args: any[]) => void;\n }> = [];\n private apiKey: string | null | (() => Promise<string | null>);\n private key: string | null = null;\n private url: string;\n private version: string;\n private socketPath: string;\n private waitForAuth: Promise<void> | null = null;\n private resolveAuth: (() => void) | null = null;\n private inflight = new Map<string, Promise<any>>();\n\n public loading: Promise<void>;\n public isLoading = true;\n public isConnected = false;\n public isConnecting = false;\n public authVersion = 0;\n\n constructor(config: SocketTransportConfig) {\n super();\n this.url = config.url;\n this.apiKey = config.key ?? null;\n this.version = config.version ?? \"v1\";\n this.socketPath = config.path ?? \"/ws\";\n this.loading = this.init(this.apiKey);\n }\n\n // ── Auth ──────────────────────────────────────────────────────────────\n\n async setKey(\n key: string | null | (() => Promise<string | null>),\n ): Promise<void> {\n this.apiKey = key;\n this.isLoading = true;\n this.loading = this.init(key);\n await this.loading;\n }\n\n // ── Init ──────────────────────────────────────────────────────────────\n\n private async init(\n key: string | null | (() => Promise<string | null>),\n ): Promise<void> {\n this.isLoading = true;\n this.isConnecting = true;\n\n try {\n this.key = typeof key === \"function\" ? await key() : key;\n const socketKey = `${this.url}:${this.version}`;\n\n if (!SOCKET_CONNECTIONS.has(socketKey)) {\n SOCKET_CONNECTIONS.set(\n socketKey,\n SocketIO(this.url, {\n path: this.socketPath,\n agent: true,\n transports: [\"websocket\"],\n withCredentials: true,\n query: { key: this.key ?? undefined, compression: true },\n }),\n );\n }\n\n this.socket = SOCKET_CONNECTIONS.get(socketKey);\n\n if (this.key) {\n const prevResolve = this.resolveAuth;\n this.waitForAuth = new Promise<void>((resolve) => {\n this.resolveAuth = resolve;\n this.socket.emit(\"authenticate\", this.key, () => {\n this.waitForAuth = null;\n this.resolveAuth = null;\n this.authVersion++;\n this.emit(\"authenticated\");\n if (prevResolve) prevResolve();\n resolve();\n });\n });\n } else {\n this.waitForAuth = null;\n this.resolveAuth = null;\n }\n\n this.isLoading = false;\n } catch (error) {\n this.isLoading = false;\n this.isConnecting = false;\n this.emit(\"error\", error);\n throw error;\n }\n\n this.setupEvents();\n }\n\n private setupEvents(): void {\n if (!this.socket) return;\n\n for (const { event, handler } of this.pendingHandlers) {\n this.socket.on(event, handler);\n }\n this.pendingHandlers = [];\n\n let hasConnected = this.isConnected;\n this.socket.off(\"connect\");\n this.socket.off(\"disconnect\");\n this.socket.off(\"error\");\n\n this.socket.on(\"connect\", () => {\n const wasDisconnected = !this.isConnected && hasConnected;\n this.isConnected = true;\n this.isConnecting = false;\n hasConnected = true;\n\n // Re-authenticate on reconnect\n if (wasDisconnected && this.key) {\n this.socket.emit(\"authenticate\", this.key, () => {\n this.emit(\"reconnected\");\n });\n } else {\n this.emit(wasDisconnected ? \"reconnected\" : \"connected\");\n }\n });\n\n this.socket.on(\"disconnect\", () => {\n this.isConnected = false;\n this.emit(\"disconnected\");\n });\n\n this.socket.on(\"error\", (error: Error) => {\n this.emit(\"error\", error);\n });\n }\n\n // ── Request/Response ──────────────────────────────────────────────────\n\n private async fetch(\n method: string,\n path: string,\n data: any = {},\n ): Promise<any> {\n await this.loading;\n if (this.waitForAuth) await this.waitForAuth;\n if (!this.socket) throw new Error(\"Socket not initialized\");\n\n const upper = method.toUpperCase();\n if (upper === \"GET\") {\n const dedupeKey = `GET:${path}:${this.authVersion}:${JSON.stringify(data)}`;\n const existing = this.inflight.get(dedupeKey);\n if (existing) return existing;\n const req = this._doFetch(method, path, data);\n this.inflight.set(dedupeKey, req);\n req.finally(() => this.inflight.delete(dedupeKey));\n return req;\n }\n\n return this._doFetch(method, path, data);\n }\n\n private async _doFetch(\n method: string,\n path: string,\n data: any = {},\n ): Promise<any> {\n if (!this.isConnected) {\n await new Promise<void>((resolve, reject) => {\n if (this.socket.connected) return resolve();\n const timeout = setTimeout(() => {\n cleanup();\n reject(new Error(\"Connection timeout\"));\n }, 30000);\n const onConnect = () => {\n cleanup();\n resolve();\n };\n const onError = (err: Error) => {\n cleanup();\n reject(new Error(`Connection failed: ${err.message}`));\n };\n const cleanup = () => {\n clearTimeout(timeout);\n this.socket.off(\"connect\", onConnect);\n this.socket.off(\"connect_error\", onError);\n };\n this.socket.once(\"connect\", onConnect);\n this.socket.once(\"connect_error\", onError);\n });\n }\n\n const id = uid.rnd();\n\n return new Promise((resolve, reject) => {\n this.socket.once(id, (msg: any) => {\n try {\n const uncompressed = pako.ungzip(msg, { to: \"string\" });\n const { success, result, message, error } = decompress(\n JSON.parse(uncompressed),\n );\n if (success) resolve(result);\n else\n reject(\n new Error(\n message || error || `Request failed: ${method}:${path}`,\n ),\n );\n } catch (err) {\n reject(err);\n }\n });\n this.socket.emit(\n \"call\",\n id,\n method.toUpperCase(),\n `/${this.version}${path}`,\n data,\n );\n });\n }\n\n async get(path: string, data?: any): Promise<any> {\n return this.fetch(\"get\", path, data);\n }\n async post(path: string, data?: any): Promise<any> {\n return this.fetch(\"post\", path, data);\n }\n async put(path: string, data?: any): Promise<any> {\n return this.fetch(\"put\", path, data);\n }\n async patch(path: string, data?: any): Promise<any> {\n return this.fetch(\"patch\", path, data);\n }\n async delete(path: string, data?: any): Promise<any> {\n return this.fetch(\"delete\", path, data);\n }\n\n // ── Subscriptions ─────────────────────────────────────────────────────\n\n subscribe(event: string, handler: (...args: any[]) => void): () => void {\n if (this.socket) {\n this.socket.on(event, handler);\n } else {\n this.pendingHandlers.push({ event, handler });\n }\n return () => this.unsubscribe(event, handler);\n }\n\n unsubscribe(event: string, handler?: (...args: any[]) => void): void {\n if (this.socket) this.socket.off(event, handler);\n this.pendingHandlers = this.pendingHandlers.filter(\n (h) => !(h.event === event && (!handler || h.handler === handler)),\n );\n }\n\n // ── Control messages ──────────────────────────────────────────────────\n\n async send(event: string, ...args: any[]): Promise<void> {\n if (!this.isConnected && this.socket) {\n await new Promise<void>((resolve) => {\n if (this.socket.connected) return resolve();\n this.socket.once(\"connect\", () => resolve());\n });\n }\n if (this.waitForAuth) await this.waitForAuth;\n if (this.socket) this.socket.emit(event, ...args);\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────\n\n disconnect(): void {\n if (this.socket) {\n this.socket.disconnect();\n SOCKET_CONNECTIONS.delete(`${this.url}:${this.version}`);\n this.socket = null;\n this.isConnected = false;\n }\n }\n\n async reconnect(): Promise<void> {\n this.loading = this.init(this.apiKey);\n await this.loading;\n }\n}\n\nexport default SocketTransport;\n","/**\n * SSETransport — HTTP + Server-Sent Events implementation of the Transport interface.\n *\n * Request/response via standard fetch(). Subscriptions via EventSource.\n * Simpler than Socket.IO — no websocket infra needed. Good for read-heavy\n * apps, serverless backends, or environments where WebSocket isn't available.\n *\n * Trade-offs vs SocketTransport:\n * - Simpler infra (no sticky sessions, works behind any CDN/proxy)\n * - Server → client streaming only (no client → server streaming)\n * - Request/response is standard HTTP (cacheable, observable, debuggable)\n * - No compression (relies on HTTP gzip)\n * - No request deduplication (relies on HTTP/2 multiplexing)\n */\n\nimport { EventEmitter } from \"eventemitter3\";\nimport type { Transport } from \"@parcae/model\";\n\nexport interface SSETransportConfig {\n /** Base URL of the Parcae backend. */\n url: string;\n /** API key or async function returning a key. */\n key?: string | null | (() => Promise<string | null>);\n /** API version prefix. Default: \"v1\" */\n version?: string;\n}\n\nexport class SSETransport extends EventEmitter implements Transport {\n private url: string;\n private version: string;\n private apiKey: string | null | (() => Promise<string | null>);\n private key: string | null = null;\n private eventSources = new Map<string, EventSource>();\n\n public isConnected = true; // HTTP is \"always connected\"\n public isLoading = true;\n public loading: Promise<void>;\n\n constructor(config: SSETransportConfig) {\n super();\n this.url = config.url.replace(/\\/$/, \"\");\n this.version = config.version ?? \"v1\";\n this.apiKey = config.key ?? null;\n this.loading = this.resolveKey();\n }\n\n private async resolveKey(): Promise<void> {\n try {\n this.key =\n typeof this.apiKey === \"function\" ? await this.apiKey() : this.apiKey;\n this.isLoading = false;\n this.emit(\"connected\");\n } catch (err) {\n this.isLoading = false;\n this.emit(\"error\", err);\n }\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.key) h[\"Authorization\"] = `Bearer ${this.key}`;\n return h;\n }\n\n private fullUrl(path: string): string {\n return `${this.url}/${this.version}${path}`;\n }\n\n // ── Request/Response ──────────────────────────────────────────────────\n\n private async request(\n method: string,\n path: string,\n data?: any,\n ): Promise<any> {\n await this.loading;\n\n const isGet = method.toUpperCase() === \"GET\";\n let url = this.fullUrl(path);\n\n if (isGet && data) {\n const params = new URLSearchParams();\n for (const [k, v] of Object.entries(data)) {\n params.set(k, typeof v === \"object\" ? JSON.stringify(v) : String(v));\n }\n url += `?${params.toString()}`;\n }\n\n const res = await fetch(url, {\n method: method.toUpperCase(),\n headers: this.headers(),\n body: isGet ? undefined : JSON.stringify(data),\n });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: res.statusText }));\n throw new Error(body.error || body.message || `HTTP ${res.status}`);\n }\n\n const body = await res.json();\n if (body.success === false) throw new Error(body.error || \"Request failed\");\n return body.result ?? body;\n }\n\n async get(path: string, data?: any): Promise<any> {\n return this.request(\"GET\", path, data);\n }\n async post(path: string, data?: any): Promise<any> {\n return this.request(\"POST\", path, data);\n }\n async put(path: string, data?: any): Promise<any> {\n return this.request(\"PUT\", path, data);\n }\n async patch(path: string, data?: any): Promise<any> {\n return this.request(\"PATCH\", path, data);\n }\n async delete(path: string, data?: any): Promise<any> {\n return this.request(\"DELETE\", path, data);\n }\n\n // ── Subscriptions (via Server-Sent Events) ────────────────────────────\n\n subscribe(event: string, handler: (...args: any[]) => void): () => void {\n const url = `${this.url}/${this.version}/__events/${encodeURIComponent(event)}`;\n const source = new EventSource(url, { withCredentials: true });\n\n source.onmessage = (e) => {\n try {\n const data = JSON.parse(e.data);\n handler(data);\n } catch {\n handler(e.data);\n }\n };\n\n source.onerror = () => {\n // EventSource auto-reconnects\n };\n\n this.eventSources.set(event, source);\n\n return () => {\n source.close();\n this.eventSources.delete(event);\n };\n }\n\n unsubscribe(event: string): void {\n const source = this.eventSources.get(event);\n if (source) {\n source.close();\n this.eventSources.delete(event);\n }\n }\n\n // ── Control messages ──────────────────────────────────────────────────\n\n async send(event: string, ...args: any[]): Promise<void> {\n await this.request(\"POST\", \"/__control\", { event, args });\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────\n\n disconnect(): void {\n for (const [, source] of this.eventSources) source.close();\n this.eventSources.clear();\n this.isConnected = false;\n this.emit(\"disconnected\");\n }\n\n async reconnect(): Promise<void> {\n this.loading = this.resolveKey();\n await this.loading;\n }\n}\n\nexport default SSETransport;\n","/**\n * @parcae/sdk — createClient()\n *\n * Creates a Parcae client with a pluggable transport layer.\n * Default: Socket.IO (bidirectional, realtime).\n * Alternative: SSE (HTTP + Server-Sent Events, simpler).\n *\n * The transport is abstracted — the client exposes the same API\n * regardless of which transport is used underneath.\n */\n\nimport { Model, FrontendAdapter } from \"@parcae/model\";\nimport type { Transport } from \"@parcae/model\";\nimport { SocketTransport } from \"./transports/socket\";\nimport type { SocketTransportConfig } from \"./transports/socket\";\nimport { SSETransport } from \"./transports/sse\";\nimport type { SSETransportConfig } from \"./transports/sse\";\n\n// ─── Configuration ───────────────────────────────────────────────────────────\n\nexport interface ClientConfig {\n /** URL of the Parcae backend. */\n url: string;\n /** API key — string or async function that returns a key. */\n key?: string | null | (() => Promise<string | null>);\n /** API version prefix. Default: \"v1\" */\n version?: string;\n /**\n * Transport type. Default: \"socket\"\n * - \"socket\": Socket.IO (bidirectional, realtime subscriptions)\n * - \"sse\": HTTP + Server-Sent Events (read-heavy, simpler infra)\n * - Transport instance: provide your own Transport implementation\n */\n transport?: \"socket\" | \"sse\" | Transport;\n}\n\nexport interface ParcaeClient {\n /** The underlying transport instance. */\n transport: Transport;\n /** Shorthand for transport methods. */\n get(path: string, data?: any): Promise<any>;\n post(path: string, data?: any): Promise<any>;\n put(path: string, data?: any): Promise<any>;\n patch(path: string, data?: any): Promise<any>;\n delete(path: string, data?: any): Promise<any>;\n /** Subscribe to a named event. Returns dispose function. */\n subscribe(event: string, handler: (...args: any[]) => void): () => void;\n /** Unsubscribe from a named event. */\n unsubscribe(event: string, handler?: (...args: any[]) => void): void;\n /** Send a control message. */\n send(event: string, ...args: any[]): void;\n /** Connection state. */\n readonly isConnected: boolean;\n readonly isLoading: boolean;\n /** Promise that resolves when the client is ready. */\n loading: Promise<void>;\n /** Update the auth key. */\n setKey(key: string | null | (() => Promise<string | null>)): Promise<void>;\n /** Listen for transport events. */\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler?: (...args: any[]) => void): void;\n /** Disconnect from the server. */\n disconnect(): void;\n /** Reconnect. */\n reconnect(): Promise<void>;\n /** Auth version — incremented on auth changes. Useful for cache invalidation. */\n readonly authVersion: number;\n}\n\n// ─── createClient ────────────────────────────────────────────────────────────\n\nexport function createClient(config: ClientConfig): ParcaeClient {\n const version = config.version ?? \"v1\";\n\n // Create the transport\n let transport: Transport & {\n loading?: Promise<void>;\n isLoading?: boolean;\n isConnected?: boolean;\n authVersion?: number;\n setKey?: (key: any) => Promise<void>;\n on?: (event: string, handler: (...args: any[]) => void) => void;\n off?: (event: string, handler?: (...args: any[]) => void) => void;\n disconnect?: () => void;\n reconnect?: () => Promise<void>;\n };\n\n if (config.transport && typeof config.transport === \"object\") {\n // Custom transport instance\n transport = config.transport as any;\n } else if (config.transport === \"sse\") {\n transport = new SSETransport({\n url: config.url,\n key: config.key,\n version,\n });\n } else {\n // Default: Socket.IO\n transport = new SocketTransport({\n url: config.url,\n key: config.key,\n version,\n });\n }\n\n // Wire up FrontendAdapter so Model.where(), .findById() etc work\n Model.use(new FrontendAdapter(transport));\n\n const client: ParcaeClient = {\n transport,\n\n get: (path, data) => transport.get(path, data),\n post: (path, data) => transport.post(path, data),\n put: (path, data) => transport.put(path, data),\n patch: (path, data) => transport.patch(path, data),\n delete: (path, data) => transport.delete(path, data),\n\n subscribe(event, handler) {\n if (transport.subscribe) return transport.subscribe(event, handler);\n return () => {}; // no-op if transport doesn't support subscriptions\n },\n\n unsubscribe(event, handler) {\n transport.unsubscribe?.(event, handler);\n },\n\n send(event, ...args) {\n (transport as any).send?.(event, ...args);\n },\n\n get isConnected() {\n return transport.isConnected ?? false;\n },\n get isLoading() {\n return transport.isLoading ?? false;\n },\n get loading() {\n return (transport as any).loading ?? Promise.resolve();\n },\n get authVersion() {\n return (transport as any).authVersion ?? 0;\n },\n\n async setKey(key) {\n if ((transport as any).setKey) await (transport as any).setKey(key);\n },\n\n on(event, handler) {\n transport.on?.(event, handler);\n },\n off(event, handler) {\n transport.off?.(event, handler);\n },\n\n disconnect() {\n transport.disconnect?.();\n },\n async reconnect() {\n await transport.reconnect?.();\n },\n };\n\n return client;\n}\n"]}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Transport } from '@parcae/model';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @parcae/sdk — createClient()
|
|
5
|
-
*
|
|
6
|
-
* Creates a Parcae client with a pluggable transport layer.
|
|
7
|
-
* Default: Socket.IO (bidirectional, realtime).
|
|
8
|
-
* Alternative: SSE (HTTP + Server-Sent Events, simpler).
|
|
9
|
-
*
|
|
10
|
-
* The transport is abstracted — the client exposes the same API
|
|
11
|
-
* regardless of which transport is used underneath.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
interface ClientConfig {
|
|
15
|
-
/** URL of the Parcae backend. */
|
|
16
|
-
url: string;
|
|
17
|
-
/** API key — string or async function that returns a key. */
|
|
18
|
-
key?: string | null | (() => Promise<string | null>);
|
|
19
|
-
/** API version prefix. Default: "v1" */
|
|
20
|
-
version?: string;
|
|
21
|
-
/**
|
|
22
|
-
* Transport type. Default: "socket"
|
|
23
|
-
* - "socket": Socket.IO (bidirectional, realtime subscriptions)
|
|
24
|
-
* - "sse": HTTP + Server-Sent Events (read-heavy, simpler infra)
|
|
25
|
-
* - Transport instance: provide your own Transport implementation
|
|
26
|
-
*/
|
|
27
|
-
transport?: "socket" | "sse" | Transport;
|
|
28
|
-
}
|
|
29
|
-
interface ParcaeClient {
|
|
30
|
-
/** The underlying transport instance. */
|
|
31
|
-
transport: Transport;
|
|
32
|
-
/** Shorthand for transport methods. */
|
|
33
|
-
get(path: string, data?: any): Promise<any>;
|
|
34
|
-
post(path: string, data?: any): Promise<any>;
|
|
35
|
-
put(path: string, data?: any): Promise<any>;
|
|
36
|
-
patch(path: string, data?: any): Promise<any>;
|
|
37
|
-
delete(path: string, data?: any): Promise<any>;
|
|
38
|
-
/** Subscribe to a named event. Returns dispose function. */
|
|
39
|
-
subscribe(event: string, handler: (...args: any[]) => void): () => void;
|
|
40
|
-
/** Unsubscribe from a named event. */
|
|
41
|
-
unsubscribe(event: string, handler?: (...args: any[]) => void): void;
|
|
42
|
-
/** Send a control message. */
|
|
43
|
-
send(event: string, ...args: any[]): void;
|
|
44
|
-
/** Connection state. */
|
|
45
|
-
readonly isConnected: boolean;
|
|
46
|
-
readonly isLoading: boolean;
|
|
47
|
-
/** Promise that resolves when the client is ready. */
|
|
48
|
-
loading: Promise<void>;
|
|
49
|
-
/** Update the auth key. */
|
|
50
|
-
setKey(key: string | null | (() => Promise<string | null>)): Promise<void>;
|
|
51
|
-
/** Listen for transport events. */
|
|
52
|
-
on(event: string, handler: (...args: any[]) => void): void;
|
|
53
|
-
off(event: string, handler?: (...args: any[]) => void): void;
|
|
54
|
-
/** Disconnect from the server. */
|
|
55
|
-
disconnect(): void;
|
|
56
|
-
/** Reconnect. */
|
|
57
|
-
reconnect(): Promise<void>;
|
|
58
|
-
/** Auth version — incremented on auth changes. Useful for cache invalidation. */
|
|
59
|
-
readonly authVersion: number;
|
|
60
|
-
}
|
|
61
|
-
declare function createClient(config: ClientConfig): ParcaeClient;
|
|
62
|
-
|
|
63
|
-
export { type ClientConfig as C, type ParcaeClient as P, createClient as c };
|