@superblocksteam/sdk 2.0.0-next.11 → 2.0.0-next.111

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 (51) 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.map +1 -1
  6. package/dist/cli-replacement/automatic-upgrades.js +17 -5
  7. package/dist/cli-replacement/automatic-upgrades.js.map +1 -1
  8. package/dist/cli-replacement/dev.d.mts.map +1 -1
  9. package/dist/cli-replacement/dev.mjs +7 -0
  10. package/dist/cli-replacement/dev.mjs.map +1 -1
  11. package/dist/client.d.ts +2 -1
  12. package/dist/client.d.ts.map +1 -1
  13. package/dist/client.js +7 -5
  14. package/dist/client.js.map +1 -1
  15. package/dist/dev-utils/dev-tracer.d.ts.map +1 -1
  16. package/dist/dev-utils/dev-tracer.js +19 -0
  17. package/dist/dev-utils/dev-tracer.js.map +1 -1
  18. package/dist/dev-utils/vite-plugin-react-transform.d.mts.map +1 -1
  19. package/dist/dev-utils/vite-plugin-react-transform.mjs +1 -0
  20. package/dist/dev-utils/vite-plugin-react-transform.mjs.map +1 -1
  21. package/dist/dev-utils/vite-plugin-sb-cdn.d.mts.map +1 -1
  22. package/dist/dev-utils/vite-plugin-sb-cdn.mjs +28 -7
  23. package/dist/dev-utils/vite-plugin-sb-cdn.mjs.map +1 -1
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +1 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/socket/handlers.d.ts +2 -2
  29. package/dist/socket/handlers.d.ts.map +1 -1
  30. package/dist/socket/handlers.js.map +1 -1
  31. package/dist/socket/index.d.ts +1 -11
  32. package/dist/socket/index.d.ts.map +1 -1
  33. package/dist/socket/index.js +11 -43
  34. package/dist/socket/index.js.map +1 -1
  35. package/dist/vite-plugin-inject-sb-ids-transform.d.mts +15 -0
  36. package/dist/vite-plugin-inject-sb-ids-transform.d.mts.map +1 -0
  37. package/dist/vite-plugin-inject-sb-ids-transform.mjs +86 -0
  38. package/dist/vite-plugin-inject-sb-ids-transform.mjs.map +1 -0
  39. package/package.json +16 -7
  40. package/src/application-build.mts +160 -0
  41. package/src/cli-replacement/automatic-upgrades.ts +20 -8
  42. package/src/cli-replacement/dev.mts +10 -0
  43. package/src/client.ts +13 -4
  44. package/src/dev-utils/dev-tracer.ts +18 -0
  45. package/src/dev-utils/vite-plugin-react-transform.mts +1 -0
  46. package/src/dev-utils/vite-plugin-sb-cdn.mts +35 -7
  47. package/src/index.ts +2 -0
  48. package/src/socket/handlers.ts +109 -105
  49. package/src/socket/index.ts +21 -101
  50. package/src/vite-plugin-inject-sb-ids-transform.mts +104 -0
  51. package/tsconfig.tsbuildinfo +1 -1
@@ -1,14 +1,16 @@
1
- import { createISocketClient, ISocket } from "@superblocksteam/shared";
2
- import WebSocket from "ws";
1
+ import {
2
+ connectWebSocket,
3
+ createISocketClient,
4
+ ISocketWithClientAuth,
5
+ } from "@superblocksteam/shared";
6
+ import tracer from "../dev-utils/dev-tracer.js";
3
7
  import { createRequestHandlers } from "./handlers.js";
8
+ import type { ISocketClient } from "../types/index.js";
4
9
  import type {
5
- GenericMiddleware,
6
- ISocketClient,
7
- MethodHandlers,
10
+ ClientMethods,
8
11
  RequestContextBase,
9
- SocketTimeouts,
10
- } from "../types/index.js";
11
- import type { ClientMethods, ServerMethods } from "@superblocksteam/shared";
12
+ ServerMethods,
13
+ } from "@superblocksteam/shared";
12
14
 
13
15
  export type StdISocketRPCClient = ISocketClient<ServerMethods>;
14
16
 
@@ -39,101 +41,19 @@ export async function connectToISocketRPCServer({
39
41
  wsUrl.hostname = "127.0.0.1";
40
42
  }
41
43
 
42
- return await connectISocket<ServerMethods, ClientMethods>(
43
- wsUrl.href,
44
- authorization,
45
- requestHandlers,
46
- [],
47
- {
44
+ const ws = await connectWebSocket(wsUrl.href);
45
+ const isocket = new ISocketWithClientAuth<
46
+ ClientMethods,
47
+ ServerMethods,
48
+ RequestContextBase
49
+ >(ws, authorization, requestHandlers, [], tracer, {
50
+ timeouts: {
48
51
  connectionTimeoutInSeconds: 6 * 60, // 6 minutes
49
52
  noResponseTimeoutInSeconds: 5 * 60, // 5 minutes
50
53
  },
51
- );
52
- }
53
-
54
- // a subclass of ISocket that sends an auth token on the first request
55
- // this is useful for client-side sockets that need to authenticate
56
- // TODO(george): if we start using this for long-lived connections, we should add a way to refresh the token
57
- export class ISocketWithClientAuth<
58
- ImplementedMethods,
59
- CallableMethods,
60
- RequestContext extends RequestContextBase,
61
- > extends ISocket<ImplementedMethods, CallableMethods, RequestContext> {
62
- private readonly authorization?: string;
63
- private hasSentAuth = false;
64
-
65
- constructor(
66
- ws: WebSocket,
67
- authorization: string | undefined,
68
- requestHandlers: MethodHandlers<
69
- ImplementedMethods,
70
- CallableMethods,
71
- RequestContext
72
- >,
73
- globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[],
74
- timeouts?: SocketTimeouts,
75
- ) {
76
- super(ws, requestHandlers, globalMiddlewares, timeouts);
77
- this.authorization = authorization;
78
- }
79
-
80
- // override `request` from the base class to send `authorization` when appropriate
81
- async request<Params, Result>(
82
- method: string,
83
- params: Params,
84
- ): Promise<Result> {
85
- // only send `authorization` on the first request
86
- const authorization = this.hasSentAuth ? undefined : this.authorization;
87
- const result = await super.request<Params, Result>(
88
- method,
89
- params,
90
- authorization,
91
- );
92
- this.hasSentAuth = true;
93
- return result;
94
- }
95
- }
96
-
97
- export async function connectISocket<
98
- CallableMethods,
99
- ImplementedMethods,
100
- RequestContext extends RequestContextBase = RequestContextBase,
101
- >(
102
- wsUrl: string,
103
- authorization: string | undefined,
104
- requestHandlers: MethodHandlers<
105
- ImplementedMethods,
106
- CallableMethods,
107
- RequestContext
108
- >,
109
- globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[],
110
- timeouts?: SocketTimeouts,
111
- ): Promise<ISocketClient<CallableMethods>> {
112
- const ws = await connectWebSocket(wsUrl);
113
- const isocket = new ISocketWithClientAuth(
114
- ws,
115
- authorization,
116
- requestHandlers,
117
- globalMiddlewares,
118
- timeouts,
119
- );
120
- return createISocketClient(isocket);
121
- }
122
-
123
- export function connectWebSocket(wsUrl: string): Promise<WebSocket> {
124
- return new Promise((resolve, reject) => {
125
- const ws = new WebSocket(wsUrl);
126
-
127
- ws.addEventListener("open", () => {
128
- // Resolve the promise with the WebSocket instance when the connection is open
129
- resolve(ws);
130
- });
131
-
132
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
133
- // @ts-ignore
134
- ws.addEventListener("error", (error: Error) => {
135
- // Reject the promise if there's an error
136
- reject(error);
137
- });
54
+ onClose: () => {
55
+ // Noop
56
+ },
138
57
  });
58
+ return createISocketClient(isocket);
139
59
  }
@@ -0,0 +1,104 @@
1
+ import path from "node:path";
2
+ import babelGenerate from "@babel/generator";
3
+ import { parse } from "@babel/parser";
4
+ import {
5
+ supplementElementIds,
6
+ generateRootSource,
7
+ } from "@superblocksteam/vite-plugin-file-sync";
8
+ import { yellow, red } from "colorette";
9
+ import fs from "fs-extra";
10
+ import { createLogger } from "vite";
11
+ import { getLogger } from "./dev-utils/dev-logger.mjs";
12
+ import type { HydratedRoute } from "@superblocksteam/vite-plugin-file-sync";
13
+ import type { Logger, Plugin } from "vite";
14
+
15
+ const routesFileBaseName = "routes.json";
16
+
17
+ /**
18
+ * Creates a Vite plugin that injects Superblocks IDs into the application.
19
+ * This will primarily be used during builds, as the dev server leverages the
20
+ * file sync manager to inject and keep the IDs up to date.
21
+ *
22
+ * Features:
23
+ * - Injects the root component with the routes data
24
+ * - Injects Superblocks IDs into all components
25
+ *
26
+ * @param root - The root directory of the application
27
+ * @returns A Vite plugin that injects Superblocks IDs into the application's components
28
+ */
29
+ export async function injectSuperblocksIdsPlugin(root: string) {
30
+ const viteLogger = createLogger();
31
+ const logger = getLogger();
32
+ viteLogger.info = logger.info;
33
+ viteLogger.warn = (msg: string) => {
34
+ logger.warn(yellow(msg));
35
+ };
36
+ viteLogger.warnOnce = (msg: string) => {
37
+ logger.warn(yellow(msg));
38
+ };
39
+ viteLogger.error = (msg: string) => {
40
+ logger.error(red(msg));
41
+ };
42
+
43
+ viteLogger.clearScreen = () => {};
44
+
45
+ const routes: HydratedRoute[] = await getRoutes(root, viteLogger);
46
+
47
+ return {
48
+ name: "sb-inject-superblocks-ids",
49
+ enforce: "pre",
50
+
51
+ transform(code, id) {
52
+ const relativePath = path.relative(root, id);
53
+
54
+ if (relativePath === "root.tsx") {
55
+ const source = generateRootSource(code, routes);
56
+ return {
57
+ code: source,
58
+ map: null,
59
+ };
60
+ } else if (id.endsWith(".tsx")) {
61
+ const ast = parse(code, {
62
+ sourceType: "module",
63
+ sourceFilename: id,
64
+ plugins: ["jsx"],
65
+ });
66
+
67
+ supplementElementIds({
68
+ fileName: id,
69
+ ast,
70
+ shouldModifyAst: true,
71
+ });
72
+
73
+ const result = babelGenerate.default(ast);
74
+ return result.code;
75
+ }
76
+
77
+ return code;
78
+ },
79
+ } as Plugin;
80
+ }
81
+
82
+ async function getRoutes(root: string, logger: Logger) {
83
+ const routesFile = path.join(root, routesFileBaseName);
84
+ if (!(await fs.pathExists(routesFile))) {
85
+ logger.warn(`routes file not found at expected location: ${routesFile}`);
86
+ return [];
87
+ }
88
+
89
+ try {
90
+ const routesData = await fs.readFile(routesFile, "utf-8");
91
+ const routes = JSON.parse(routesData) as Record<string, { file: string }>;
92
+
93
+ return Object.entries(routes).map(([path, { file }]) => ({
94
+ path,
95
+ component: file,
96
+ }));
97
+ } catch (err) {
98
+ logger.error(
99
+ `error reading routes file: ${routesFile}. error=[${JSON.stringify(err)}]`,
100
+ );
101
+ }
102
+
103
+ return [];
104
+ }