@superblocksteam/sdk 1.14.2 → 2.0.3-next.46

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 (152) hide show
  1. package/.mocharc.json +7 -0
  2. package/.prettierrc +18 -0
  3. package/dist/cli-replacement/dev.d.mts +19 -0
  4. package/dist/cli-replacement/dev.d.mts.map +1 -0
  5. package/dist/cli-replacement/dev.mjs +122 -0
  6. package/dist/cli-replacement/dev.mjs.map +1 -0
  7. package/dist/cli-replacement/init.d.ts +14 -0
  8. package/dist/cli-replacement/init.d.ts.map +1 -0
  9. package/dist/cli-replacement/init.js +26 -0
  10. package/dist/cli-replacement/init.js.map +1 -0
  11. package/dist/client.d.ts +31 -17
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/client.js +137 -155
  14. package/dist/client.js.map +1 -0
  15. package/dist/dbfs/client.d.ts +6 -0
  16. package/dist/dbfs/client.d.ts.map +1 -0
  17. package/dist/dbfs/client.js +117 -0
  18. package/dist/dbfs/client.js.map +1 -0
  19. package/dist/dbfs/local.d.ts +15 -0
  20. package/dist/dbfs/local.d.ts.map +1 -0
  21. package/dist/dbfs/local.js +126 -0
  22. package/dist/dbfs/local.js.map +1 -0
  23. package/dist/dev-utils/custom-build.d.mts +4 -0
  24. package/dist/dev-utils/custom-build.d.mts.map +1 -0
  25. package/dist/dev-utils/custom-build.mjs +99 -0
  26. package/dist/dev-utils/custom-build.mjs.map +1 -0
  27. package/dist/dev-utils/custom-config.d.mts +2 -0
  28. package/dist/dev-utils/custom-config.d.mts.map +1 -0
  29. package/dist/dev-utils/custom-config.mjs +57 -0
  30. package/dist/dev-utils/custom-config.mjs.map +1 -0
  31. package/dist/dev-utils/dev-logger.d.mts +8 -0
  32. package/dist/dev-utils/dev-logger.d.mts.map +1 -0
  33. package/dist/dev-utils/dev-logger.mjs +25 -0
  34. package/dist/dev-utils/dev-logger.mjs.map +1 -0
  35. package/dist/dev-utils/dev-server.d.mts +18 -0
  36. package/dist/dev-utils/dev-server.d.mts.map +1 -0
  37. package/dist/dev-utils/dev-server.mjs +265 -0
  38. package/dist/dev-utils/dev-server.mjs.map +1 -0
  39. package/dist/dev-utils/dev-tracer.d.ts +3 -0
  40. package/dist/dev-utils/dev-tracer.d.ts.map +1 -0
  41. package/dist/dev-utils/dev-tracer.js +28 -0
  42. package/dist/dev-utils/dev-tracer.js.map +1 -0
  43. package/dist/dev-utils/vite-plugin-dd-rum.d.mts +10 -0
  44. package/dist/dev-utils/vite-plugin-dd-rum.d.mts.map +1 -0
  45. package/dist/dev-utils/vite-plugin-dd-rum.mjs +34 -0
  46. package/dist/dev-utils/vite-plugin-dd-rum.mjs.map +1 -0
  47. package/dist/dev-utils/vite-plugin-react-transform.d.mts +7 -0
  48. package/dist/dev-utils/vite-plugin-react-transform.d.mts.map +1 -0
  49. package/dist/dev-utils/vite-plugin-react-transform.mjs +110 -0
  50. package/dist/dev-utils/vite-plugin-react-transform.mjs.map +1 -0
  51. package/dist/dev-utils/vite-plugin-sb-cdn.d.mts +34 -0
  52. package/dist/dev-utils/vite-plugin-sb-cdn.d.mts.map +1 -0
  53. package/dist/dev-utils/vite-plugin-sb-cdn.mjs +720 -0
  54. package/dist/dev-utils/vite-plugin-sb-cdn.mjs.map +1 -0
  55. package/dist/errors.d.ts +1 -0
  56. package/dist/errors.d.ts.map +1 -0
  57. package/dist/errors.js +4 -9
  58. package/dist/errors.js.map +1 -0
  59. package/dist/flag.d.ts +2 -2
  60. package/dist/flag.d.ts.map +1 -0
  61. package/dist/flag.js +5 -9
  62. package/dist/flag.js.map +1 -0
  63. package/dist/index.d.ts +10 -4
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +10 -20
  66. package/dist/index.js.map +1 -0
  67. package/dist/sdk.d.ts +42 -18
  68. package/dist/sdk.d.ts.map +1 -0
  69. package/dist/sdk.js +47 -43
  70. package/dist/sdk.js.map +1 -0
  71. package/dist/socket/handlers.d.ts +3 -128
  72. package/dist/socket/handlers.d.ts.map +1 -0
  73. package/dist/socket/handlers.js +7 -9
  74. package/dist/socket/handlers.js.map +1 -0
  75. package/dist/socket/index.d.ts +4 -3
  76. package/dist/socket/index.d.ts.map +1 -0
  77. package/dist/socket/index.js +12 -21
  78. package/dist/socket/index.js.map +1 -0
  79. package/dist/socket/signing.d.ts +3 -1
  80. package/dist/socket/signing.d.ts.map +1 -0
  81. package/dist/socket/signing.js +8 -17
  82. package/dist/socket/signing.js.map +1 -0
  83. package/dist/socket/socket.d.ts +3 -2
  84. package/dist/socket/socket.d.ts.map +1 -0
  85. package/dist/socket/socket.js +9 -19
  86. package/dist/socket/socket.js.map +1 -0
  87. package/dist/types/common.d.ts +2 -103
  88. package/dist/types/common.d.ts.map +1 -0
  89. package/dist/types/common.js +8 -24
  90. package/dist/types/common.js.map +1 -0
  91. package/dist/types/index.d.ts +5 -4
  92. package/dist/types/index.d.ts.map +1 -0
  93. package/dist/types/index.js +5 -20
  94. package/dist/types/index.js.map +1 -0
  95. package/dist/types/plugin.d.ts +1 -0
  96. package/dist/types/plugin.d.ts.map +1 -0
  97. package/dist/types/plugin.js +3 -5
  98. package/dist/types/plugin.js.map +1 -0
  99. package/dist/types/signing.d.ts +2 -1
  100. package/dist/types/signing.d.ts.map +1 -0
  101. package/dist/types/signing.js +2 -2
  102. package/dist/types/signing.js.map +1 -0
  103. package/dist/types/socket.d.ts +1 -0
  104. package/dist/types/socket.d.ts.map +1 -0
  105. package/dist/types/socket.js +2 -5
  106. package/dist/types/socket.js.map +1 -0
  107. package/dist/utils.d.ts +3 -1
  108. package/dist/utils.d.ts.map +1 -0
  109. package/dist/utils.js +14 -23
  110. package/dist/utils.js.map +1 -0
  111. package/dist/version-control.d.mts +59 -0
  112. package/dist/version-control.d.mts.map +1 -0
  113. package/dist/version-control.mjs +899 -0
  114. package/dist/version-control.mjs.map +1 -0
  115. package/eslint.config.js +85 -0
  116. package/package.json +72 -32
  117. package/src/cli-replacement/dev.mts +182 -0
  118. package/src/cli-replacement/init.ts +47 -0
  119. package/src/client.ts +114 -38
  120. package/src/dbfs/client.ts +162 -0
  121. package/src/dbfs/local.ts +163 -0
  122. package/src/dev-utils/custom-build.mts +113 -0
  123. package/src/dev-utils/custom-config.mts +66 -0
  124. package/src/dev-utils/dev-logger.mts +39 -0
  125. package/src/dev-utils/dev-server.mts +342 -0
  126. package/src/dev-utils/dev-tracer.ts +31 -0
  127. package/src/dev-utils/vite-plugin-dd-rum.mts +47 -0
  128. package/src/dev-utils/vite-plugin-react-transform.mts +130 -0
  129. package/src/dev-utils/vite-plugin-sb-cdn.mts +988 -0
  130. package/src/flag.ts +2 -3
  131. package/src/index.ts +119 -4
  132. package/src/sdk.ts +91 -17
  133. package/src/socket/handlers.ts +9 -147
  134. package/src/socket/index.ts +6 -9
  135. package/src/socket/signing.ts +7 -8
  136. package/src/socket/socket.ts +8 -9
  137. package/src/types/common.ts +2 -119
  138. package/src/types/index.ts +4 -4
  139. package/src/types/signing.ts +1 -1
  140. package/src/types/socket.ts +1 -1
  141. package/src/utils.ts +5 -6
  142. package/src/version-control.mts +1351 -0
  143. package/test/dev-utils/fixture/index.html +12 -0
  144. package/test/dev-utils/fixture/main.jsx +22 -0
  145. package/test/dev-utils/fixture/package-lock.json +25 -0
  146. package/test/dev-utils/fixture/package.json +9 -0
  147. package/test/dev-utils/vite-plugin-sb-cdn.test.mts +74 -0
  148. package/test/tsconfig.json +9 -0
  149. package/test/version-control.test.mts +1412 -0
  150. package/tsconfig.json +15 -4
  151. package/tsconfig.tsbuildinfo +1 -1
  152. package/.eslintrc.json +0 -55
@@ -0,0 +1,66 @@
1
+ import path from "node:path";
2
+ import react from "@vitejs/plugin-react";
3
+ import glob from "fast-glob";
4
+ import { defineConfig } from "vite";
5
+
6
+ export function getLegacyComponentsConfig(componentsFolder: string) {
7
+ const entries = glob.sync("**/*.{jsx,tsx}", {
8
+ cwd: componentsFolder,
9
+ absolute: true,
10
+ ignore: ["node_modules/**", "dist/**"],
11
+ });
12
+
13
+ const entryPoints = entries.reduce(
14
+ (acc, entry) => {
15
+ const relativePath = path.relative(path.join(componentsFolder), entry);
16
+ const entryName = relativePath.replace(/\.(jsx|tsx)$/, "");
17
+ acc[entryName] = relativePath;
18
+ return acc;
19
+ },
20
+ {} as Record<string, string>,
21
+ );
22
+
23
+ // we build a copy of react and react-dom because we need to import the old versions
24
+ // inside our vite plugins virtual wrapper
25
+ entryPoints["react"] = path.join(componentsFolder, "node_modules/react");
26
+ entryPoints["react-dom"] = path.join(
27
+ componentsFolder,
28
+ "node_modules/react-dom",
29
+ );
30
+
31
+ return defineConfig({
32
+ root: componentsFolder,
33
+ logLevel: "warn",
34
+ resolve: {
35
+ preserveSymlinks: true,
36
+ alias: {
37
+ react: path.join(componentsFolder, "node_modules/react"),
38
+ "react-dom": path.join(componentsFolder, "node_modules/react-dom"),
39
+ },
40
+ },
41
+ build: {
42
+ sourcemap: true,
43
+ outDir: path.resolve(componentsFolder, "dist"),
44
+ lib: {
45
+ entry: entryPoints,
46
+ formats: ["es"],
47
+ fileName: (format, entryName) => `${entryName}.js`,
48
+ },
49
+ modulePreload: false,
50
+ minify: false,
51
+ rollupOptions: {
52
+ output: {
53
+ preserveModules: true,
54
+ preserveModulesRoot: ".",
55
+ entryFileNames: "[name].js",
56
+ },
57
+ },
58
+ },
59
+ optimizeDeps: {
60
+ include: ["react", "react-dom"],
61
+ force: true,
62
+ },
63
+ // TODO(omar): there is a type mismatch in the monorepo
64
+ plugins: [react() as any],
65
+ });
66
+ }
@@ -0,0 +1,39 @@
1
+ import { createLogger, format, transports } from "winston";
2
+
3
+ export type DevLogger = {
4
+ debug: (message: string, ...meta: any[]) => void;
5
+ info: (message: string, ...meta: any[]) => void;
6
+ warn: (message: string, ...meta: any[]) => void;
7
+ error: (message: string, ...meta: any[]) => void;
8
+ };
9
+
10
+ const winstonLogger = createLogger({
11
+ level: "info",
12
+ exitOnError: false,
13
+ format: format.json(),
14
+ transports: [
15
+ new transports.File({ filename: `/tmp/dev-server.log`, level: "info" }),
16
+ new transports.Console({
17
+ format: format.combine(
18
+ format.printf(({ message }) => `${message}`),
19
+ format.colorize({ message: true }),
20
+ ),
21
+ level: "debug",
22
+ }),
23
+ ],
24
+ });
25
+
26
+ export function getLogger(
27
+ loggerOverride?: (message: string) => void,
28
+ ): DevLogger {
29
+ if (!loggerOverride) {
30
+ return winstonLogger;
31
+ }
32
+
33
+ return {
34
+ debug: loggerOverride,
35
+ info: loggerOverride,
36
+ warn: loggerOverride,
37
+ error: loggerOverride,
38
+ };
39
+ }
@@ -0,0 +1,342 @@
1
+ // Tracer has to be imported after the express import
2
+ // eslint-disable-next-line import/order
3
+ import tracer from "./dev-tracer.js";
4
+
5
+ import net from "node:net";
6
+ import path from "node:path";
7
+ import { getSuperblocksResourceConfigIfExists } from "@superblocksteam/util";
8
+ import { fileSyncVitePlugin } from "@superblocksteam/vite-plugin-file-sync";
9
+ import react from "@vitejs/plugin-react";
10
+ import { red, yellow } from "colorette";
11
+ import express from "express";
12
+ import { createLogger, createServer, loadEnv } from "vite";
13
+ import tsconfigPaths from "vite-tsconfig-paths";
14
+ import pkg from "../../package.json" with { type: "json" };
15
+ import {
16
+ customComponentsPlugin,
17
+ isCustomComponentsEnabled,
18
+ } from "./custom-build.mjs";
19
+ import { getLogger } from "./dev-logger.mjs";
20
+ import { ddRumPlugin } from "./vite-plugin-dd-rum.mjs";
21
+ import { superblocksCdnPlugin } from "./vite-plugin-sb-cdn.mjs";
22
+ import type { AiService } from "@superblocksteam/vite-plugin-file-sync/ai-service";
23
+ import type { LockService } from "@superblocksteam/vite-plugin-file-sync/lock-service";
24
+ import type { OperationQueue } from "@superblocksteam/vite-plugin-file-sync/operation-queue";
25
+ import type { SyncService } from "@superblocksteam/vite-plugin-file-sync/sync-service";
26
+ import type http from "node:http";
27
+ import type { ViteDevServer } from "vite";
28
+ import type { Plugin } from "vite";
29
+ interface CreateDevServerOptions {
30
+ root: string;
31
+ mode: "development" | "production";
32
+ port?: number;
33
+ fsOperationQueue: OperationQueue;
34
+ syncService?: SyncService;
35
+ lockService?: LockService;
36
+ aiService?: AiService;
37
+ /* For redirecting output, like when running outside of the CLI */
38
+ logger?: (message: string) => void;
39
+ }
40
+
41
+ let httpServer: http.Server;
42
+
43
+ // The "Dev Server" is a long-running HTTP server that manages the Vite server
44
+ export async function createDevServer({
45
+ root,
46
+ mode,
47
+ fsOperationQueue,
48
+ syncService,
49
+ lockService,
50
+ aiService,
51
+ logger: loggerOverride,
52
+ port,
53
+ }: CreateDevServerOptions) {
54
+ const logger = getLogger(loggerOverride);
55
+ if (httpServer) {
56
+ logger.debug("Dev server already running");
57
+ return httpServer;
58
+ }
59
+
60
+ // even if Vite is not running, we can receive requests
61
+ const resourceConfig = await getSuperblocksResourceConfigIfExists();
62
+ if (resourceConfig?.configType !== "APPLICATION_V2") {
63
+ throw new Error("Invalid resource configuration type");
64
+ }
65
+
66
+ const healthResponse = {
67
+ status: "healthy",
68
+ applicationId: resourceConfig.id,
69
+ // TODO(code-mode): add branch name
70
+ cliVersion: pkg.version,
71
+ };
72
+
73
+ let viteServer: ViteDevServer | null;
74
+ const app = express();
75
+
76
+ let isViteServerInitialized = false;
77
+ let viteResolve: (value: void | PromiseLike<void>) => void;
78
+ let viteReject: (reason?: any) => void;
79
+ const vitePromise = new Promise((resolve, reject) => {
80
+ viteResolve = resolve;
81
+ viteReject = reject;
82
+ });
83
+
84
+ async function gracefulShutdown(logger: ReturnType<typeof getLogger>) {
85
+ try {
86
+ if (lockService?.isLocked) {
87
+ await syncService?.uploadDirectoryNowIfNeeded(); // Perform a final sync before disconnecting
88
+ await lockService.releaseLock(); // Release the lock before closing the vite server
89
+ }
90
+ // Cleanup the vite server
91
+ if (viteServer) {
92
+ await viteServer?.close();
93
+ viteServer = null;
94
+ isViteServerInitialized = false;
95
+ }
96
+ } catch (e) {
97
+ logger.error(`Error during graceful shutdown: ${e}`);
98
+ } finally {
99
+ const closeTimeout = setTimeout(() => {
100
+ logger.info("Dev server closed");
101
+ process.exit(0);
102
+ }, 1000); // Fallback to exit if the HTTP server doesn't close within 1 second
103
+
104
+ // Then close the HTTP server
105
+ httpServer.close(() => {
106
+ logger.info("Dev server closed");
107
+ clearTimeout(closeTimeout);
108
+ process.exit(0);
109
+ });
110
+ }
111
+ }
112
+
113
+ app.use((req, res, next) => {
114
+ res.setHeader("Access-Control-Allow-Origin", "*");
115
+
116
+ if (
117
+ req.url === "/_sb_connect" ||
118
+ req.url === "/_sb_disconnect" ||
119
+ req.url === "/_sb_health" ||
120
+ req.url === "/_sb_status"
121
+ ) {
122
+ return next();
123
+ }
124
+
125
+ // hold the request until the vite server is initialized
126
+ vitePromise.then(() => {
127
+ // If the server is already closed, don't hold the request
128
+ if (isViteServerInitialized) {
129
+ next();
130
+ } else {
131
+ res.status(500).send("Dev server is not running");
132
+ }
133
+ });
134
+ });
135
+
136
+ app.get("/_sb_health", async (_req, res) => {
137
+ res.setHeader("Content-Type", "application/json");
138
+ res.setHeader("Access-Control-Allow-Origin", "*");
139
+ res.send(JSON.stringify(healthResponse));
140
+ });
141
+
142
+ // Attach the vite server to the express app
143
+ app.get("/_sb_connect", async (_req, res) => {
144
+ res.setHeader("Content-Type", "application/json");
145
+ res.setHeader("Access-Control-Allow-Origin", "*");
146
+ if (isViteServerInitialized) {
147
+ res.send(JSON.stringify(healthResponse));
148
+ return;
149
+ }
150
+ isViteServerInitialized = true;
151
+ // TODO(code-mode): should this include any validation checks, such as getting a token?
152
+ startVite({
153
+ app,
154
+ root,
155
+ mode,
156
+ fsOperationQueue,
157
+ syncService,
158
+ lockService,
159
+ aiService,
160
+ logger: loggerOverride,
161
+ httpServer,
162
+ }).then((server) => {
163
+ viteResolve();
164
+ viteServer = server;
165
+ res.send(JSON.stringify(healthResponse));
166
+ }, viteReject);
167
+ });
168
+
169
+ app.get("/_sb_disconnect", async (_req, res) => {
170
+ // TODO(code-mode): should this include any validation checks, such as getting a token?
171
+ await gracefulShutdown(logger);
172
+ res.send("ok");
173
+ });
174
+
175
+ app.get("/_sb_status", async (_req, res) => {
176
+ res.setHeader("Content-Type", "application/json");
177
+ res.setHeader("Access-Control-Allow-Origin", "*");
178
+ if (lockService?.isLocked) {
179
+ res.send({
180
+ connectedUsers: lockService.connectedUsers,
181
+ });
182
+ } else {
183
+ res.send({
184
+ connectedUsers: [],
185
+ });
186
+ }
187
+ });
188
+
189
+ process.on("SIGINT", async () => {
190
+ logger.info("SIGINT received");
191
+ await gracefulShutdown(logger);
192
+ });
193
+
194
+ process.on("SIGTERM", async () => {
195
+ logger.info("SIGTERM received");
196
+ await gracefulShutdown(logger);
197
+ });
198
+
199
+ process.on("SIGABRT", async () => {
200
+ logger.info("SIGABRT received");
201
+ await gracefulShutdown(logger);
202
+ });
203
+
204
+ httpServer = await app.listen(port);
205
+ return httpServer;
206
+ }
207
+
208
+ async function startVite({
209
+ app,
210
+ httpServer,
211
+ root,
212
+ mode,
213
+ fsOperationQueue,
214
+ syncService,
215
+ lockService,
216
+ aiService,
217
+ logger: loggerOverride,
218
+ }: CreateDevServerOptions & {
219
+ app: express.Express;
220
+ httpServer: http.Server;
221
+ }) {
222
+ const viteLogger = createLogger();
223
+ const logger = getLogger(loggerOverride);
224
+ viteLogger.info = logger.info;
225
+ viteLogger.warn = (msg: string) => {
226
+ logger.warn(yellow(msg));
227
+ };
228
+ viteLogger.warnOnce = (msg: string) => {
229
+ logger.warn(yellow(msg));
230
+ };
231
+ viteLogger.error = (msg: string) => {
232
+ logger.error(red(msg));
233
+ };
234
+
235
+ viteLogger.clearScreen = () => {};
236
+
237
+ const isCustomBuildEnabled = await isCustomComponentsEnabled();
238
+ const customFolder = path.join(root, "custom");
239
+
240
+ const cdnUrl = process.env.SUPERBLOCKS_CDN_URL ?? "http://localhost:4040/cdn";
241
+
242
+ const env = loadEnv(mode, root, "");
243
+
244
+ const hmrPort = await getFreePort();
245
+
246
+ const viteServer = await createServer({
247
+ root,
248
+ mode,
249
+ resolve: {
250
+ alias: {
251
+ "react-router": "@superblocksteam/library",
252
+ },
253
+ },
254
+ clearScreen: process.env.SUPERBLOCKS_CLI_ENV !== "local",
255
+ optimizeDeps: {
256
+ include: ["lodash", "react-is"],
257
+ exclude: [],
258
+ },
259
+ // See https://vite.dev/config/server-options.html#server-middlewaremode
260
+ // appType: "custom",
261
+ server: {
262
+ middlewareMode: true,
263
+ // port: port,
264
+ watch: {
265
+ ignored: [`${customFolder}/**/*`],
266
+ },
267
+ hmr: {
268
+ port: hmrPort,
269
+ },
270
+ },
271
+ build: {
272
+ commonjsOptions: {
273
+ include: ["react-is"],
274
+ },
275
+ rollupOptions: {
276
+ external: [`${customFolder}/**/*`],
277
+ },
278
+ },
279
+ plugins: [
280
+ tsconfigPaths(),
281
+ customComponentsPlugin(),
282
+
283
+ // TODO(omar): there is a type mismatch in the monorepo
284
+ fileSyncVitePlugin(
285
+ {
286
+ fsOperationQueue,
287
+ syncService,
288
+ lockService,
289
+ aiService,
290
+ httpServer,
291
+ tracer,
292
+ logger,
293
+ },
294
+ { isCustomBuildEnabled },
295
+ ) as Plugin,
296
+
297
+ // for now, only use the CDN locally
298
+ superblocksCdnPlugin({
299
+ imports: {
300
+ "@superblocksteam/library": `${cdnUrl}/index.js`,
301
+ },
302
+ cssImports: {
303
+ "@superblocksteam/library/index.css": `${cdnUrl}/index.css`,
304
+ },
305
+ }),
306
+
307
+ react(),
308
+ ddRumPlugin({
309
+ clientToken: env.SUPERBLOCKS_LIBRARY_DD_CLIENT_TOKEN ?? "",
310
+ applicationId: env.SUPERBLOCKS_LIBRARY_DD_APPLICATION_ID ?? "",
311
+ env: env.SUPERBLOCKS_LIBRARY_ENV ?? "prod",
312
+ // TODO: Version should be injected from the library. Replace once we have the autoupgrade feature.
313
+ version: "1.0.0",
314
+ }),
315
+ ],
316
+ });
317
+
318
+ app.use(viteServer.middlewares);
319
+
320
+ return viteServer;
321
+ }
322
+
323
+ const DEFAULT_HMR_PORT = 24678;
324
+
325
+ function getFreePort() {
326
+ return new Promise<number>((resolve) => {
327
+ const server = net.createServer();
328
+ server.listen(0, () => {
329
+ const address = server.address();
330
+ if (typeof address === "string") {
331
+ resolve(DEFAULT_HMR_PORT);
332
+ return;
333
+ }
334
+ const port = address?.port;
335
+ if (!port) {
336
+ resolve(DEFAULT_HMR_PORT);
337
+ return;
338
+ }
339
+ server.close(() => resolve(port));
340
+ });
341
+ });
342
+ }
@@ -0,0 +1,31 @@
1
+ import tracer from "dd-trace";
2
+ import packageJson from "../../package.json" with { type: "json" };
3
+
4
+ tracer.init({
5
+ service: "sdk-dev-server",
6
+ version: packageJson.version,
7
+ env: "prod",
8
+ logInjection: true,
9
+ });
10
+
11
+ tracer.use("http", {
12
+ hooks: {
13
+ request: (span, req) => {
14
+ let resource = "GET";
15
+ if (req) {
16
+ resource = `${req?.method} ${"path" in req ? req?.path : req?.url}`;
17
+ }
18
+ span?.setTag("resource.name", resource);
19
+ },
20
+ },
21
+ });
22
+
23
+ tracer.use("express", {
24
+ hooks: {
25
+ request: (span, req) => {
26
+ span?.setTag("resource.name", `${req?.method} ${req?.url}`);
27
+ },
28
+ },
29
+ });
30
+
31
+ export default tracer;
@@ -0,0 +1,47 @@
1
+ import type { Plugin } from "vite";
2
+
3
+ type DdRumPluginOptions = {
4
+ clientToken: string;
5
+ applicationId: string;
6
+ env: string;
7
+ version: string;
8
+ };
9
+
10
+ export function ddRumPlugin(options: DdRumPluginOptions): Plugin {
11
+ return {
12
+ name: "vite-plugin-dd-rum",
13
+ transformIndexHtml(html) {
14
+ if (
15
+ process.env.SUPERBLOCKS_CLI_ENV === "local" ||
16
+ !options.clientToken ||
17
+ !options.applicationId
18
+ ) {
19
+ return html;
20
+ }
21
+ return html.replace(
22
+ "</head>",
23
+ `<script>
24
+ (function(h,o,u,n,d) {
25
+ h=h[d]=h[d]||{q:[],onReady:function(c){h.q.push(c)}}
26
+ d=o.createElement(u);d.async=1;d.src=n
27
+ n=o.getElementsByTagName(u)[0];n.parentNode.insertBefore(d,n)
28
+ })(window,document,'script','https://www.datadoghq-browser-agent.com/us1/v6/datadog-rum.js','DD_RUM')
29
+ window.DD_RUM.onReady(function() {
30
+ window.DD_RUM.init({
31
+ clientToken: "${options.clientToken ?? ""}",
32
+ applicationId: "${options.applicationId ?? ""}",
33
+ site: 'datadoghq.com',
34
+ service: 'superblocks-library',
35
+ env: "${options.env ?? ""}",
36
+ version: "${options.version ?? ""}",
37
+ sessionSampleRate: 100,
38
+ sessionReplaySampleRate: 100,
39
+ enablePrivacyForActionName: true
40
+ });
41
+ })
42
+ </script>
43
+ </head>`,
44
+ );
45
+ },
46
+ };
47
+ }
@@ -0,0 +1,130 @@
1
+ import baseDebug from "debug";
2
+ import type { Plugin } from "vite";
3
+
4
+ const debug = baseDebug("sb:sdk:vite-plugin-react-transform");
5
+
6
+ /**
7
+ * Vite plugin to transform React modules to actual ESM with named exports.
8
+ * This ensures React and React DOM can be properly consumed by browsers when used in import maps.
9
+ */
10
+ export function reactTransformPlugin(): Plugin {
11
+ return {
12
+ name: "vite-plugin-react-transform",
13
+ enforce: "pre", // Run before other plugins
14
+ async transform(code, id) {
15
+ // Check for React modules
16
+ if (id.includes("node_modules/.vite/deps/react.js")) {
17
+ debug(`Adding named exports to React: ${id}`);
18
+
19
+ // We're going to assume this is using the require_react pattern
20
+ // Let's first check if the original React bundle is accessible
21
+ try {
22
+ // Parse the code to find exports
23
+ // For Vite bundled React, the code likely uses the format:
24
+ // import { require_react } from "/chunk-XYZ.js";
25
+ // export default require_react();
26
+
27
+ // Let's use regex to find all possible export names from the bundle
28
+ // This pattern looks for property accesses on require_react() in the code
29
+ const requireReactPattern = /require_react\(\)\.([a-zA-Z0-9_]+)/g;
30
+ const reactExports = new Set<string>();
31
+
32
+ // Find all matches
33
+ let match;
34
+ while ((match = requireReactPattern.exec(code)) !== null) {
35
+ if (match[1]) {
36
+ reactExports.add(match[1]);
37
+ }
38
+ }
39
+
40
+ // Add known React exports that might not be directly accessed in the bundle
41
+ // prettier-ignore
42
+ const knownReactExports = [
43
+ "Children", "Component", "Fragment", "Profiler", "PureComponent",
44
+ "StrictMode", "Suspense", "cloneElement", "createContext",
45
+ "createElement", "createFactory", "createRef", "forwardRef",
46
+ "isValidElement", "lazy", "memo", "useCallback", "useContext",
47
+ "useDebugValue", "useEffect", "useImperativeHandle",
48
+ "useLayoutEffect", "useMemo", "useReducer", "useRef", "useState",
49
+ "useSyncExternalStore", "startTransition", "useTransition",
50
+ "useDeferredValue", "useId", "useInsertionEffect", "version",
51
+ "__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED",
52
+ ] as const;
53
+
54
+ // Add all known exports to our set
55
+ for (const namedExport of knownReactExports) {
56
+ reactExports.add(namedExport);
57
+ }
58
+
59
+ debug("Found exports: %O", reactExports);
60
+ debug(`Found ${reactExports.size} React exports to add`);
61
+
62
+ // Generate named export statements for all found properties
63
+ const exportStatements = Array.from(reactExports)
64
+ .map((name) => `export const ${name} = require_react().${name};`)
65
+ .join("\n");
66
+
67
+ // Return the original code plus the generated exports
68
+ return `${code}\n\n${exportStatements}`;
69
+ } catch (err) {
70
+ console.error(err);
71
+ throw err;
72
+ }
73
+ }
74
+
75
+ // Check for React DOM modules
76
+ if (id.includes("node_modules/.vite/deps/react-dom.js")) {
77
+ debug(`Adding named exports to React DOM: ${id}`);
78
+
79
+ try {
80
+ // Similar approach for React DOM
81
+ const requireReactDomPattern =
82
+ /require_react_dom\(\)\.([a-zA-Z0-9_]+)/g;
83
+ const reactDomExports = new Set<string>();
84
+
85
+ // Find all matches
86
+ let match;
87
+ while ((match = requireReactDomPattern.exec(code)) !== null) {
88
+ if (match[1]) {
89
+ reactDomExports.add(match[1]);
90
+ }
91
+ }
92
+
93
+ // Add known React DOM exports
94
+ const knownReactDomExports = [
95
+ "createPortal",
96
+ "findDOMNode",
97
+ "flushSync",
98
+ "hydrate",
99
+ "render",
100
+ "unmountComponentAtNode",
101
+ "unstable_batchedUpdates",
102
+ "createRoot",
103
+ "hydrateRoot",
104
+ ];
105
+
106
+ // Add all known exports to our set
107
+ knownReactDomExports.forEach((exp) => reactDomExports.add(exp));
108
+
109
+ debug(`Found ${reactDomExports.size} React DOM exports to add`);
110
+ debug("React DOM exports: %O", reactDomExports);
111
+
112
+ // Generate export statements for all found properties
113
+ const exportStatements = Array.from(reactDomExports)
114
+ .map(
115
+ (name) => `export const ${name} = require_react_dom().${name};`,
116
+ )
117
+ .join("\n");
118
+
119
+ // Return the original code plus the generated exports
120
+ return `${code}\n\n// Add named exports for remote library consumption\n${exportStatements}`;
121
+ } catch (err) {
122
+ console.error(err);
123
+ throw err;
124
+ }
125
+ }
126
+
127
+ return null; // Let Vite handle other modules
128
+ },
129
+ };
130
+ }