@superblocksteam/sdk 2.0.6-next.44 → 2.0.6-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 (30) hide show
  1. package/dist/application-build.mjs +2 -2
  2. package/dist/application-build.mjs.map +1 -1
  3. package/dist/cli-replacement/automatic-upgrades.d.ts +5 -2
  4. package/dist/cli-replacement/automatic-upgrades.d.ts.map +1 -1
  5. package/dist/cli-replacement/automatic-upgrades.js +69 -26
  6. package/dist/cli-replacement/automatic-upgrades.js.map +1 -1
  7. package/dist/cli-replacement/dev.d.mts +1 -2
  8. package/dist/cli-replacement/dev.d.mts.map +1 -1
  9. package/dist/cli-replacement/dev.mjs +53 -28
  10. package/dist/cli-replacement/dev.mjs.map +1 -1
  11. package/dist/dev-utils/dev-logger.d.mts +17 -7
  12. package/dist/dev-utils/dev-logger.d.mts.map +1 -1
  13. package/dist/dev-utils/dev-logger.mjs +50 -9
  14. package/dist/dev-utils/dev-logger.mjs.map +1 -1
  15. package/dist/dev-utils/dev-server.d.mts.map +1 -1
  16. package/dist/dev-utils/dev-server.mjs +3 -11
  17. package/dist/dev-utils/dev-server.mjs.map +1 -1
  18. package/dist/vite-plugin-generate-build-manifest.mjs +1 -1
  19. package/dist/vite-plugin-generate-build-manifest.mjs.map +1 -1
  20. package/dist/vite-plugin-inject-sb-ids-transform.mjs +1 -1
  21. package/dist/vite-plugin-inject-sb-ids-transform.mjs.map +1 -1
  22. package/package.json +5 -5
  23. package/src/application-build.mts +2 -2
  24. package/src/cli-replacement/automatic-upgrades.ts +101 -27
  25. package/src/cli-replacement/dev.mts +67 -41
  26. package/src/dev-utils/dev-logger.mts +94 -20
  27. package/src/dev-utils/dev-server.mts +3 -11
  28. package/src/vite-plugin-generate-build-manifest.mts +1 -1
  29. package/src/vite-plugin-inject-sb-ids-transform.mts +1 -1
  30. package/tsconfig.tsbuildinfo +1 -1
@@ -1,7 +1,6 @@
1
1
  import "../dev-utils/dev-tracer.js";
2
2
 
3
3
  import * as child_process from "node:child_process";
4
- import * as fsp from "node:fs/promises";
5
4
  import path from "node:path";
6
5
  import { promisify } from "node:util";
7
6
  import { maskUnixSignals } from "@superblocksteam/util";
@@ -18,7 +17,7 @@ import fs from "fs-extra";
18
17
  import { resolveCommand } from "package-manager-detector";
19
18
  import { detect } from "package-manager-detector/detect";
20
19
 
21
- import { getLogger } from "../dev-utils/dev-logger.mjs";
20
+ import { getErrorMeta, getLogger } from "../dev-utils/dev-logger.mjs";
22
21
  import { createDevServer } from "../dev-utils/dev-server.mjs";
23
22
  import tracer from "../dev-utils/dev-tracer.js";
24
23
  import { SuperblocksSdk } from "../sdk.js";
@@ -27,6 +26,7 @@ import {
27
26
  getCurrentCliVersion,
28
27
  getCurrentLibraryVersionWithoutPM,
29
28
  } from "./automatic-upgrades.js";
29
+ import { AUTO_UPGRADE_EXIT_CODE } from "./automatic-upgrades.js";
30
30
  import type { DevLogger } from "../dev-utils/dev-logger.mjs";
31
31
  import type { ApplicationConfig } from "../types/common.js";
32
32
  import type { DraftInterface } from "@superblocksteam/vite-plugin-file-sync/draft-interface";
@@ -93,7 +93,6 @@ async function installPackages(cwd: string, logger: DevLogger) {
93
93
  export async function dev(options: {
94
94
  /* cwd is required */
95
95
  cwd: string;
96
- pidfilePath?: string;
97
96
  devServerPort?: number;
98
97
 
99
98
  /* user control of sync operations */
@@ -107,7 +106,7 @@ export async function dev(options: {
107
106
  /* For debugging purposes to get location of the cli */
108
107
  superblocksPath?: string;
109
108
  /* For redirecting output, like when running outside of the CLI */
110
- logger?: (message: string) => void;
109
+ logger?: (...messages: (string | Error)[]) => void;
111
110
 
112
111
  /* For a child process when restarting the dev server for automatic upgrades */
113
112
  skipAutoUpgrade?: boolean;
@@ -119,7 +118,6 @@ export async function dev(options: {
119
118
 
120
119
  const {
121
120
  cwd,
122
- pidfilePath,
123
121
  devServerPort,
124
122
  downloadFirst,
125
123
  uploadFirst,
@@ -128,12 +126,6 @@ export async function dev(options: {
128
126
  skipAutoUpgrade,
129
127
  } = options;
130
128
 
131
- const cliVersion = await getCurrentCliVersion();
132
- const libraryVersion = await getCurrentLibraryVersionWithoutPM();
133
- logger.info(
134
- `Running command: ${options.superblocksPath} dev${options.uploadFirst ? " --upload-first" : ""}${options.downloadFirst ? " --download-first" : ""} with baseUrl: ${applicationConfig?.superblocksBaseUrl}, cliVersion: ${cliVersion}, libraryVersion: ${libraryVersion?.alias} ${libraryVersion?.version}`,
135
- );
136
-
137
129
  // Add check for node_modules
138
130
  if (!fs.existsSync(path.join(cwd, "node_modules"))) {
139
131
  throw new Error(
@@ -141,9 +133,13 @@ export async function dev(options: {
141
133
  );
142
134
  }
143
135
 
144
- if (pidfilePath) {
145
- await fsp.writeFile(pidfilePath, `${process.pid}\n`);
146
- }
136
+ logger.info("Starting dev server");
137
+
138
+ const cliVersion = await getCurrentCliVersion();
139
+ const libraryVersion = await getCurrentLibraryVersionWithoutPM();
140
+ logger.info(
141
+ `Running command: ${options.superblocksPath} dev${options.uploadFirst ? " --upload-first" : ""}${options.downloadFirst ? " --download-first" : ""} with baseUrl: ${applicationConfig?.superblocksBaseUrl}, cliVersion: ${cliVersion}, libraryVersion: ${libraryVersion?.alias} ${libraryVersion?.version}`,
142
+ );
147
143
 
148
144
  const port = devServerPort ?? 5173;
149
145
 
@@ -188,17 +184,11 @@ export async function dev(options: {
188
184
  if (lockService) {
189
185
  try {
190
186
  await lockService!.acquireLock();
191
-
192
- // TODO(code-mode): package naming is preventing upgrade in ephemeral environments
193
- if (
194
- !process.env.PACKAGE_SUFFIX ||
195
- process.env.PACKAGE_SUFFIX === "" ||
196
- !skipAutoUpgrade
197
- ) {
198
- await checkVersionsAndUpgrade(lockService, applicationConfig);
199
- }
200
187
  } catch (error) {
201
- logger.error("Failed to acquire lock on application", error);
188
+ logger.error(
189
+ "Failed to acquire lock on application",
190
+ getErrorMeta(error),
191
+ );
202
192
  passErrorToVSCode(
203
193
  (error as { context?: { message: string } }).context?.message,
204
194
  logger,
@@ -232,11 +222,10 @@ export async function dev(options: {
232
222
 
233
223
  if (isSynced) {
234
224
  logger.info("Local files are in sync with the server");
235
- return;
225
+ } else {
226
+ logger.info("Local files are out of sync with the server");
236
227
  }
237
228
 
238
- logger.info("Local files are out of sync with the server");
239
-
240
229
  if (!(downloadFirst || uploadFirst)) {
241
230
  throw new Error(
242
231
  "You must choose --download-first or --upload-first to use the dev command",
@@ -246,37 +235,70 @@ export async function dev(options: {
246
235
  throw new Error("Choose either --download-first or --upload-first");
247
236
  }
248
237
 
238
+ let hasPackageChanged = false;
239
+
249
240
  if (downloadFirst) {
250
- logger.info(
251
- "Starting directory sync from server before starting the local server",
252
- );
241
+ logger.info("Starting download");
253
242
 
254
- // Read package.json before download
255
243
  const packageJsonBefore = await readPkgJson(cwd);
256
-
257
244
  await syncService!.downloadDirectory();
258
-
259
- // Read package.json after download and compare
260
245
  const packageJsonAfter = await readPkgJson(cwd);
261
246
 
262
- // Check if package.json changed
263
247
  if (packageJsonBefore && packageJsonAfter) {
264
248
  const diff = diffJson(packageJsonBefore, packageJsonAfter);
265
- const hasChanges = diff.some((part) => part.added || part.removed);
249
+ hasPackageChanged = diff.some((part) => part.added || part.removed);
250
+ } else if (packageJsonAfter) {
251
+ hasPackageChanged = true;
252
+ logger.info("package.json was created, installing packages…");
253
+ }
254
+ }
266
255
 
267
- if (hasChanges) {
268
- logger.info("package.json has changed, installing packages…");
269
- await installPackages(cwd, logger);
256
+ let hasCliUpdated = false;
257
+ if (
258
+ !process.env.PACKAGE_SUFFIX ||
259
+ process.env.PACKAGE_SUFFIX === "" ||
260
+ !skipAutoUpgrade
261
+ ) {
262
+ if (lockService) {
263
+ const result = await checkVersionsAndUpgrade(
264
+ lockService,
265
+ applicationConfig,
266
+ );
267
+ if (result?.libraryUpdated) {
268
+ hasPackageChanged = true;
270
269
  }
270
+ hasCliUpdated = result?.cliUpdated ?? false;
271
+ } else {
272
+ logger.warn(
273
+ "Lock service is not available, skipping version check and upgrade",
274
+ );
271
275
  }
272
- } else if (uploadFirst) {
276
+ }
277
+
278
+ if (hasPackageChanged) {
279
+ logger.info("Installing packages…");
280
+ await installPackages(cwd, logger);
281
+ }
282
+
283
+ if (hasPackageChanged || uploadFirst) {
273
284
  logger.info("Uploading local files to server before starting");
274
285
  await syncService!.uploadDirectory();
286
+ await syncService!.uploadDirectoryNowIfNeeded();
287
+ }
288
+
289
+ if (hasCliUpdated) {
290
+ logger.info("CLI was updated, restarting the dev server…");
291
+ process.exit(AUTO_UPGRADE_EXIT_CODE);
275
292
  }
276
293
  });
277
294
  } catch (error: any) {
278
295
  logger.error(error.message);
279
- process.exit(1);
296
+ try {
297
+ await lockService?.shutdownAndExit();
298
+ } finally {
299
+ // this is redundant, but it's here to make sure the lock service is shutdown and the process exits
300
+ process.exit(1);
301
+ }
280
302
  }
281
303
  } else {
282
304
  logger.info("Skipping directory sync");
@@ -296,6 +318,10 @@ export async function dev(options: {
296
318
  options.signal?.addEventListener("abort", () => {
297
319
  logger.info("Server closed");
298
320
  httpServer.close();
321
+ lockService?.shutdownAndExit().catch(() => {
322
+ // this is redundant, but it's here to make sure the lock service is shutdown and the process exits
323
+ process.exit(1);
324
+ });
299
325
  });
300
326
 
301
327
  logger.debug(green(`Local server started at port ${port}`));
@@ -1,39 +1,113 @@
1
1
  import { createLogger, format, transports } from "winston";
2
+ import type winston from "winston";
2
3
 
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
- };
4
+ const activeTransports: winston.transport[] = [];
5
+
6
+ if (process.env.SUPERBLOCKS_IS_CSB === "true") {
7
+ activeTransports.push(
8
+ new transports.File({
9
+ format: format.json(),
10
+ filename: `/tmp/dev-server.log`,
11
+ level: "info",
12
+ }),
13
+ );
14
+ }
15
+
16
+ activeTransports.push(
17
+ new transports.Console({
18
+ format: format.combine(
19
+ format.colorize(),
20
+ format.timestamp({
21
+ format: "HH:mm:ss.SSS",
22
+ }),
23
+ format.printf((props) => {
24
+ const { message, timestamp, error, level } = props;
25
+ const base =
26
+ process.env.SUPERBLOCKS_IS_CSB === "true"
27
+ ? `${timestamp} ${message}`
28
+ : `${message}`;
29
+ if (level === "error") {
30
+ return `${base} ${(error as ErrorMeta["error"]).message} ${(error as ErrorMeta["error"]).stack}`;
31
+ }
32
+ return base;
33
+ }),
34
+ ),
35
+ }),
36
+ );
9
37
 
10
38
  const winstonLogger = createLogger({
11
- level: "info",
39
+ level: "debug",
12
40
  exitOnError: false,
13
41
  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
- ],
42
+ transports: activeTransports,
43
+ });
44
+
45
+ interface ErrorMeta {
46
+ error: {
47
+ kind: string;
48
+ message: string;
49
+ stack?: string;
50
+ };
51
+ }
52
+
53
+ export interface DevLogger {
54
+ log: (...messages: string[]) => void;
55
+ debug: (...messages: string[]) => void;
56
+ info: (...messages: string[]) => void;
57
+ warn: (...messages: string[]) => void;
58
+ error: (message: string, meta?: ErrorMeta) => void;
59
+ }
60
+ const logger: DevLogger = Object.freeze({
61
+ debug: (...messages: string[]) =>
62
+ winstonLogger.debug(
63
+ messages.length > 0 ? messages.join(" ") : (messages[0] as string),
64
+ ),
65
+ log: (...messages: string[]) =>
66
+ winstonLogger.info(
67
+ messages.length > 0 ? messages.join(" ") : (messages[0] as string),
68
+ ),
69
+ info: (...messages: string[]) =>
70
+ winstonLogger.info(
71
+ messages.length > 0 ? messages.join(" ") : (messages[0] as string),
72
+ ),
73
+ warn: (...messages: string[]) =>
74
+ winstonLogger.warn(
75
+ messages.length > 0 ? messages.join(" ") : (messages[0] as string),
76
+ ),
77
+ error: (message: string, meta?: ErrorMeta) =>
78
+ winstonLogger.error(message, meta),
24
79
  });
25
80
 
26
81
  export function getLogger(
27
- loggerOverride?: (message: string) => void,
82
+ loggerOverride?: (...messages: string[]) => void,
28
83
  ): DevLogger {
29
84
  if (!loggerOverride) {
30
- return winstonLogger;
85
+ return logger;
31
86
  }
32
87
 
33
88
  return {
34
89
  debug: loggerOverride,
35
90
  info: loggerOverride,
36
91
  warn: loggerOverride,
37
- error: loggerOverride,
92
+ log: loggerOverride,
93
+ error: loggerOverride as any,
94
+ };
95
+ }
96
+
97
+ export function getErrorMeta(error: unknown): ErrorMeta {
98
+ if (error instanceof Error) {
99
+ return {
100
+ error: {
101
+ kind: error.name,
102
+ message: error.message,
103
+ stack: error.stack,
104
+ },
105
+ };
106
+ }
107
+ return {
108
+ error: {
109
+ kind: "Unknown Error",
110
+ message: JSON.stringify(error),
111
+ },
38
112
  };
39
113
  }
@@ -18,7 +18,7 @@ import {
18
18
  customComponentsPlugin,
19
19
  isCustomComponentsEnabled,
20
20
  } from "./custom-build.mjs";
21
- import { getLogger } from "./dev-logger.mjs";
21
+ import { getErrorMeta, getLogger } from "./dev-logger.mjs";
22
22
  import { buildManifestStubPlugin } from "./vite-plugin-build-manifest-stub.mjs";
23
23
  import { ddRumPlugin } from "./vite-plugin-dd-rum.mjs";
24
24
  import { superblocksCdnPlugin } from "./vite-plugin-sb-cdn.mjs";
@@ -188,13 +188,6 @@ export async function createDevServer({
188
188
  }, viteReject);
189
189
  });
190
190
 
191
- // TODO(code-mode): remove this soon
192
- app.get("/_sb_disconnect", async (_req, res) => {
193
- console.log("GET /_sb_disconnect");
194
- // TODO(code-mode): should this include any validation checks, such as getting a token?
195
- await gracefulShutdown({ logger, serverInitiated: false });
196
- res.send("ok");
197
- });
198
191
  app.post("/_sb_disconnect", async (req, res) => {
199
192
  const { initiatedByEmail, switchingTo } = req.body;
200
193
  // TODO(code-mode): should this include any validation checks, such as getting a token?
@@ -207,7 +200,7 @@ export async function createDevServer({
207
200
  });
208
201
  res.send("ok");
209
202
  } catch (e) {
210
- console.error("Error disconnecting from dev server", e);
203
+ logger.error("Error disconnecting from dev server", getErrorMeta(e));
211
204
  res.status(500).send("Error disconnecting from dev server");
212
205
  }
213
206
  });
@@ -261,7 +254,7 @@ async function startVite({
261
254
  }) {
262
255
  const viteLogger = createLogger();
263
256
  const logger = getLogger(loggerOverride);
264
- viteLogger.info = logger.info;
257
+ viteLogger.info = (msg: string) => logger.info(msg);
265
258
  viteLogger.warn = (msg: string) => {
266
259
  logger.warn(yellow(msg));
267
260
  };
@@ -345,7 +338,6 @@ async function startVite({
345
338
  aiService,
346
339
  httpServer,
347
340
  tracer,
348
- logger,
349
341
  },
350
342
  { isCustomBuildEnabled },
351
343
  ) as Plugin,
@@ -53,7 +53,7 @@ type ApiDependency = {
53
53
  export function generateBuildManifestPlugin(root: string) {
54
54
  const viteLogger = createLogger();
55
55
  const logger = getLogger();
56
- viteLogger.info = logger.info;
56
+ viteLogger.info = (msg: string) => logger.info(msg);
57
57
  viteLogger.warn = (msg: string) => {
58
58
  logger.warn(yellow(msg));
59
59
  };
@@ -29,7 +29,7 @@ const routesFileBaseName = "routes.json";
29
29
  export async function injectSuperblocksIdsPlugin(root: string) {
30
30
  const viteLogger = createLogger();
31
31
  const logger = getLogger();
32
- viteLogger.info = logger.info;
32
+ viteLogger.info = (msg: string) => logger.info(msg);
33
33
  viteLogger.warn = (msg: string) => {
34
34
  logger.warn(yellow(msg));
35
35
  };