@superblocksteam/sdk 2.0.3-next.99 → 2.0.3

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.
Files changed (67) hide show
  1. package/dist/application-build.d.mts +12 -0
  2. package/dist/application-build.d.mts.map +1 -0
  3. package/dist/application-build.mjs +113 -0
  4. package/dist/application-build.mjs.map +1 -0
  5. package/dist/cli-replacement/automatic-upgrades.d.ts +14 -0
  6. package/dist/cli-replacement/automatic-upgrades.d.ts.map +1 -0
  7. package/dist/cli-replacement/automatic-upgrades.js +267 -0
  8. package/dist/cli-replacement/automatic-upgrades.js.map +1 -0
  9. package/dist/cli-replacement/dev.d.mts +3 -6
  10. package/dist/cli-replacement/dev.d.mts.map +1 -1
  11. package/dist/cli-replacement/dev.mjs +80 -3
  12. package/dist/cli-replacement/dev.mjs.map +1 -1
  13. package/dist/client.d.ts +2 -1
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/client.js +7 -5
  16. package/dist/client.js.map +1 -1
  17. package/dist/dev-utils/dev-server.d.mts.map +1 -1
  18. package/dist/dev-utils/dev-server.mjs +59 -19
  19. package/dist/dev-utils/dev-server.mjs.map +1 -1
  20. package/dist/dev-utils/dev-tracer.d.ts +1 -1
  21. package/dist/dev-utils/dev-tracer.d.ts.map +1 -1
  22. package/dist/dev-utils/dev-tracer.js +66 -24
  23. package/dist/dev-utils/dev-tracer.js.map +1 -1
  24. package/dist/dev-utils/vite-plugin-react-transform.d.mts.map +1 -1
  25. package/dist/dev-utils/vite-plugin-react-transform.mjs +1 -0
  26. package/dist/dev-utils/vite-plugin-react-transform.mjs.map +1 -1
  27. package/dist/dev-utils/vite-plugin-sb-cdn.d.mts.map +1 -1
  28. package/dist/dev-utils/vite-plugin-sb-cdn.mjs +34 -9
  29. package/dist/dev-utils/vite-plugin-sb-cdn.mjs.map +1 -1
  30. package/dist/index.d.ts +4 -2
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +2 -0
  33. package/dist/index.js.map +1 -1
  34. package/dist/socket/handlers.d.ts +2 -2
  35. package/dist/socket/handlers.d.ts.map +1 -1
  36. package/dist/socket/handlers.js.map +1 -1
  37. package/dist/socket/index.d.ts +1 -11
  38. package/dist/socket/index.d.ts.map +1 -1
  39. package/dist/socket/index.js +11 -43
  40. package/dist/socket/index.js.map +1 -1
  41. package/dist/types/common.d.ts +6 -0
  42. package/dist/types/common.d.ts.map +1 -1
  43. package/dist/types/common.js.map +1 -1
  44. package/dist/vite-plugin-inject-sb-ids-transform.d.mts +15 -0
  45. package/dist/vite-plugin-inject-sb-ids-transform.d.mts.map +1 -0
  46. package/dist/vite-plugin-inject-sb-ids-transform.mjs +86 -0
  47. package/dist/vite-plugin-inject-sb-ids-transform.mjs.map +1 -0
  48. package/package.json +26 -6
  49. package/src/application-build.mts +160 -0
  50. package/src/cli-replacement/automatic-upgrades.ts +363 -0
  51. package/src/cli-replacement/dev.mts +120 -10
  52. package/src/client.ts +13 -4
  53. package/src/dev-utils/dev-server.mts +79 -19
  54. package/src/dev-utils/dev-tracer.ts +69 -24
  55. package/src/dev-utils/vite-plugin-react-transform.mts +1 -0
  56. package/src/dev-utils/vite-plugin-sb-cdn.mts +45 -11
  57. package/src/index.ts +6 -1
  58. package/src/socket/handlers.ts +109 -105
  59. package/src/socket/index.ts +21 -101
  60. package/src/types/common.ts +7 -0
  61. package/src/vite-plugin-inject-sb-ids-transform.mts +104 -0
  62. package/tsconfig.tsbuildinfo +1 -1
  63. package/dist/socket/socket.d.ts +0 -61
  64. package/dist/socket/socket.d.ts.map +0 -1
  65. package/dist/socket/socket.js +0 -251
  66. package/dist/socket/socket.js.map +0 -1
  67. package/src/socket/socket.ts +0 -399
@@ -1,399 +0,0 @@
1
- import { SocketErrorException } from "../types/index.js";
2
- import type {
3
- ISocketClient,
4
- MethodHandler,
5
- MethodHandlers,
6
- RequestContextBase,
7
- SocketTimeouts,
8
- GenericMiddleware,
9
- NonEmptyArray,
10
- } from "../types/index.js";
11
- import type WebSocket from "ws";
12
-
13
- interface SocketRequest<Payload = unknown> {
14
- method: string;
15
- payload: Payload;
16
- id: number;
17
- setAuthorization?: string;
18
- }
19
-
20
- interface SocketResponse<Payload = unknown> {
21
- id: number;
22
- payload: Payload;
23
- error: SocketError | null;
24
- }
25
-
26
- export interface SocketMessage<
27
- RequestPayload = unknown,
28
- ResponsePayload = unknown,
29
- > {
30
- request?: SocketRequest<RequestPayload>;
31
- response?: SocketResponse<ResponsePayload>;
32
- }
33
-
34
- export interface SocketError {
35
- message: string;
36
- code: number;
37
- }
38
-
39
- /**
40
- * ISocket is a class that wraps a WebSocket connection and provides a simple interface for sending and receiving messages.
41
- * ISocket is initialized by both server and client and request/response is called symmetrically.
42
- *
43
- * ISocket handles has two timeout actions:
44
- * 1. Connection timeout: If the connection is not closed after a certain time, the connection is closed.
45
- * - This is useful to prevent a connection from being open indefinitely. This is mainly used in the server side since
46
- * the client side manages connection lifecycle manually.
47
- * 2. No response timeout: If the response is not received after a certain time, the request is timed out.
48
- * - This is mainly used by CLI to handle the case where the server is not responding.
49
- *
50
- * It is expected that timeouts should be relatively sorted in the order of connection timeout > request timeout > no response timeout.
51
- */
52
- export class ISocket<
53
- ImplementedMethods,
54
- CallableMethods,
55
- RequestContext extends RequestContextBase,
56
- > {
57
- private readonly ws: WebSocket;
58
- private readonly requestHandlers: MethodHandlers<
59
- ImplementedMethods,
60
- CallableMethods,
61
- RequestContext
62
- >;
63
- private readonly globalMiddlewares: GenericMiddleware<
64
- CallableMethods,
65
- RequestContext
66
- >[];
67
- private readonly responseHandler = new Map<
68
- number,
69
- {
70
- resolve: (data: unknown) => void;
71
- reject: (error: SocketError) => void;
72
- timeout?: NodeJS.Timeout;
73
- }
74
- >();
75
- private peerAuthorization?: string;
76
- protected nxtRequestId: number;
77
- private connectionTimeout?: NodeJS.Timeout;
78
- // pino library not available in shared
79
- private logger: { error: (message?: string) => void };
80
- private timeouts?: SocketTimeouts;
81
-
82
- constructor(
83
- ws: WebSocket,
84
- requestHandlers: MethodHandlers<
85
- ImplementedMethods,
86
- CallableMethods,
87
- RequestContext
88
- >,
89
- globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[],
90
- timeouts?: SocketTimeouts,
91
- logger?: { error: (message?: string) => void },
92
- ) {
93
- this.ws = ws;
94
- this.requestHandlers = requestHandlers;
95
- this.globalMiddlewares = globalMiddlewares;
96
- this.nxtRequestId = 0;
97
- this.logger = logger ?? { error: console.error };
98
- this.timeouts = timeouts;
99
- // reset connection timeout in each message received. It means connection still active
100
- this.resetConnectionTimeout();
101
-
102
- this.ws.addEventListener(
103
- "message",
104
-
105
- async (event: WebSocket.MessageEvent) => {
106
- const eventData: SocketMessage = JSON.parse(event.data.toString());
107
- return this.handleMessage(eventData);
108
- },
109
- );
110
- }
111
-
112
- protected async handleMessage(message: SocketMessage): Promise<void> {
113
- this.resetConnectionTimeout();
114
- if (message.request) {
115
- // Split the method string into parts
116
- const parts = message.request.method.split(".");
117
- let handlers = this.requestHandlers as Record<string, unknown>;
118
- for (const part of parts) {
119
- handlers = handlers[part] as Record<string, unknown>;
120
- if (!handlers) {
121
- return this.respondError(message.request.id, {
122
- code: 2,
123
- message: `unknown method ${message.request.method}`,
124
- });
125
- }
126
- }
127
-
128
- if (!Array.isArray(handlers)) {
129
- return this.respondError(message.request.id, {
130
- code: 2,
131
- message: "unknown method",
132
- });
133
- }
134
- handlers = [...this.globalMiddlewares, ...handlers] as MethodHandlers<
135
- ImplementedMethods,
136
- CallableMethods,
137
- RequestContext
138
- >;
139
- if (message.request.setAuthorization) {
140
- this.peerAuthorization = message.request.setAuthorization;
141
- }
142
- const reqCtx = {
143
- peerAuthorization: this.peerAuthorization,
144
- method: message.request.method,
145
- requestId: message.request.id,
146
- } as RequestContext;
147
- const client = createISocketClient(this);
148
- const payload = message.request.payload;
149
- let alreadyResponded = false;
150
- const generateNextFn = (idx: number): (() => Promise<unknown>) => {
151
- let wasCalled = false;
152
- return async () => {
153
- if (alreadyResponded) {
154
- throw new SocketErrorException(
155
- 4,
156
- "next() was called after the response was sent",
157
- );
158
- }
159
- const handler = (
160
- handlers as unknown as NonEmptyArray<
161
- MethodHandler<unknown, unknown, CallableMethods, RequestContext>
162
- >
163
- )[idx];
164
- if (!handler) {
165
- throw new SocketErrorException(
166
- 5,
167
- "cannot call past the last handler in the chain",
168
- );
169
- }
170
- if (wasCalled) {
171
- throw new SocketErrorException(
172
- 6,
173
- "next() was called multiple times",
174
- );
175
- }
176
- wasCalled = true;
177
- return this.callHandler(
178
- handler,
179
- payload,
180
- reqCtx,
181
- client,
182
- generateNextFn(idx + 1),
183
- );
184
- };
185
- };
186
- let response: unknown;
187
- try {
188
- // call the first handler in the chain
189
- response = await generateNextFn(0)();
190
- } catch (error) {
191
- const socketError =
192
- error instanceof SocketErrorException
193
- ? { code: error.code, message: error.message }
194
- : { code: 3, message: (error as Error).toString() };
195
- return this.respondError(message.request.id, socketError);
196
- }
197
- this.respond(message.request.id, response);
198
- alreadyResponded = true;
199
- } else if (message.response && message.response.id) {
200
- const responseHandler = this.responseHandler.get(message.response.id);
201
- if (!responseHandler) {
202
- return;
203
- }
204
- if (message.response.error) {
205
- responseHandler.reject(message.response.error);
206
- }
207
-
208
- responseHandler.resolve(message.response.payload as any);
209
- clearTimeout(responseHandler.timeout);
210
- this.responseHandler.delete(message.response.id);
211
- } else {
212
- return this.respondError(-1, {
213
- code: 3,
214
- message: "unknown request id",
215
- });
216
- }
217
- }
218
-
219
- protected async callHandler<
220
- Params,
221
- Result,
222
- CallableMethods,
223
- RequestContext extends RequestContextBase,
224
- >(
225
- handler: MethodHandler<Params, Result, CallableMethods, RequestContext>,
226
- params: Params,
227
- ctx: RequestContext,
228
- client: ISocketClient<CallableMethods>,
229
- next: () => Promise<Result>,
230
- ): Promise<Result> {
231
- return handler(params, ctx, client, next);
232
- }
233
-
234
- public request<Params, Result>(
235
- method: string,
236
- params: Params,
237
- authorization?: string,
238
- ): Promise<Result> {
239
- return new Promise<Result>((resolve, reject) => {
240
- const requestId = ++this.nxtRequestId;
241
- this.responseHandler.set(requestId, {
242
- resolve: (result) => resolve(result as Result),
243
-
244
- reject: (error: SocketError) => reject(error),
245
- });
246
- const toSend: SocketMessage = {
247
- request: {
248
- method,
249
- payload: params,
250
- id: requestId,
251
- setAuthorization: authorization,
252
- },
253
- };
254
- this.ws.send(JSON.stringify(toSend));
255
- this.resetNoResponseTimeout(requestId);
256
- });
257
- }
258
-
259
- protected respond<Result>(requestId: number, result: Result): void {
260
- const toSend: SocketMessage = {
261
- response: {
262
- payload: result,
263
- id: requestId,
264
- error: null,
265
- },
266
- };
267
- return this.ws.send(JSON.stringify(toSend));
268
- }
269
-
270
- protected respondError(requestId: number, error: SocketError): void {
271
- const toSend: SocketMessage = {
272
- response: {
273
- payload: null,
274
- id: requestId,
275
- error: error,
276
- },
277
- };
278
- return this.ws.send(JSON.stringify(toSend));
279
- }
280
-
281
- private resetConnectionTimeout(): void {
282
- if (!this.timeouts?.connectionTimeoutInSeconds) {
283
- return;
284
- }
285
- if (this.connectionTimeout) {
286
- clearTimeout(this.connectionTimeout);
287
- }
288
- // Set a new timeout for the next message
289
- this.connectionTimeout = setTimeout(
290
- this.handleConnectionTimeout(),
291
- this.timeouts?.connectionTimeoutInSeconds * 1000,
292
- );
293
- }
294
-
295
- private handleConnectionTimeout() {
296
- return () => {
297
- this.logger.error(
298
- `Connection timed out after ${this.timeouts?.connectionTimeoutInSeconds} seconds`,
299
- );
300
- this.close();
301
- };
302
- }
303
-
304
- private resetNoResponseTimeout(requestId: number): void {
305
- if (!this.timeouts?.noResponseTimeoutInSeconds) {
306
- return;
307
- }
308
- const responseHandler = this.responseHandler.get(requestId);
309
- if (!responseHandler) {
310
- return;
311
- }
312
- const noResponseTimeout = responseHandler.timeout;
313
- const reject = responseHandler.reject;
314
- if (responseHandler.timeout) {
315
- clearTimeout(noResponseTimeout);
316
- }
317
- // Set a new timeout for the next message
318
- responseHandler.timeout = setTimeout(
319
- this.handleNoResponseTimeout(reject),
320
- this.timeouts?.noResponseTimeoutInSeconds * 1000,
321
- );
322
- }
323
-
324
- private handleNoResponseTimeout(reject: (error: SocketError) => void) {
325
- return () => {
326
- const message = `Request timed out after ${this.timeouts?.noResponseTimeoutInSeconds} seconds`;
327
- this.logger.error(message);
328
- reject({ code: 7, message });
329
- };
330
- }
331
-
332
- public close(): void {
333
- clearTimeout(this.connectionTimeout);
334
- this.responseHandler.forEach((handler, key) => {
335
- clearTimeout(handler.timeout);
336
- this.logger.error(
337
- `Rejecting pending requestId ${key} due to connection close`,
338
- );
339
- handler.reject({ code: 8, message: "Connection closed" });
340
- });
341
- this.ws.close();
342
- }
343
- }
344
-
345
- const proxyTarget = Object.freeze(() => {
346
- /* return nothing */
347
- });
348
-
349
- function createIsocketProxy<
350
- ImplementedMethods,
351
- CallableMethods,
352
- RequestContext extends RequestContextBase,
353
- >(
354
- socket: ISocket<ImplementedMethods, CallableMethods, RequestContext>,
355
- // if path is undefined, it means the current object is the root object
356
- path: string | undefined,
357
- ): unknown {
358
- return new Proxy(proxyTarget, {
359
- get(_target, prop: string) {
360
- const childPath = path ? `${path}.${prop}` : prop;
361
- // sometimes, when `createISocketClient` is called from an async function, JS will implicitly call the `then` method on
362
- // its return value, because promises can be arbitrarily nested
363
- // so return undefined for the `then` method to avoid this
364
- if (childPath === "then") {
365
- return undefined;
366
- }
367
- return createIsocketProxy(socket, childPath);
368
- },
369
-
370
- apply(_target, _thisArg, args: unknown[]) {
371
- if (path === undefined) {
372
- throw new Error("The root object is not callable");
373
- }
374
- if (
375
- path.endsWith(".apply") &&
376
- args.length === 2 &&
377
- Array.isArray(args[1])
378
- ) {
379
- path = path.slice(0, -".apply".length);
380
- args = args[1];
381
- }
382
- return socket.request(path, args[0]);
383
- },
384
- });
385
- }
386
-
387
- export function createISocketClient<
388
- CallableMethods,
389
- ImplementedMethods,
390
- RequestContext extends RequestContextBase,
391
- >(
392
- socket: ISocket<ImplementedMethods, CallableMethods, RequestContext>,
393
- ): ISocketClient<CallableMethods> {
394
- return {
395
- close: () => socket.close(),
396
-
397
- call: createIsocketProxy(socket, undefined) as any,
398
- };
399
- }