@superblocksteam/sdk 2.0.83 → 2.0.84-next.0
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/.turbo/turbo-build.log +1 -1
- package/dist/cli-replacement/automatic-upgrades.d.ts +0 -6
- package/dist/cli-replacement/automatic-upgrades.d.ts.map +1 -1
- package/dist/cli-replacement/automatic-upgrades.js +5 -27
- package/dist/cli-replacement/automatic-upgrades.js.map +1 -1
- package/dist/cli-replacement/dev.d.mts.map +1 -1
- package/dist/cli-replacement/dev.mjs +260 -217
- package/dist/cli-replacement/dev.mjs.map +1 -1
- package/dist/cli-replacement/version-detection.d.ts +71 -0
- package/dist/cli-replacement/version-detection.d.ts.map +1 -0
- package/dist/cli-replacement/version-detection.js +186 -0
- package/dist/cli-replacement/version-detection.js.map +1 -0
- package/dist/cli-replacement/version-detection.test.d.ts +5 -0
- package/dist/cli-replacement/version-detection.test.d.ts.map +1 -0
- package/dist/cli-replacement/version-detection.test.js +257 -0
- package/dist/cli-replacement/version-detection.test.js.map +1 -0
- package/dist/dev-utils/dev-server.mjs +133 -115
- package/dist/dev-utils/dev-server.mjs.map +1 -1
- package/dist/telemetry/index.d.ts +4 -4
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/index.js +92 -64
- package/dist/telemetry/index.js.map +1 -1
- package/dist/telemetry/index.test.d.ts +2 -0
- package/dist/telemetry/index.test.d.ts.map +1 -0
- package/dist/telemetry/index.test.js +93 -0
- package/dist/telemetry/index.test.js.map +1 -0
- package/dist/telemetry/local-obs.d.ts +73 -0
- package/dist/telemetry/local-obs.d.ts.map +1 -0
- package/dist/telemetry/local-obs.js +107 -0
- package/dist/telemetry/local-obs.js.map +1 -0
- package/dist/telemetry/util.d.ts +1 -2
- package/dist/telemetry/util.d.ts.map +1 -1
- package/dist/telemetry/util.js +26 -4
- package/dist/telemetry/util.js.map +1 -1
- package/package.json +6 -5
- package/src/cli-replacement/automatic-upgrades.ts +10 -42
- package/src/cli-replacement/dev.mts +336 -281
- package/src/cli-replacement/version-detection.test.ts +336 -0
- package/src/cli-replacement/version-detection.ts +220 -0
- package/src/dev-utils/dev-server.mts +149 -127
- package/src/telemetry/index.test.ts +130 -0
- package/src/telemetry/index.ts +105 -83
- package/src/telemetry/local-obs.ts +138 -0
- package/src/telemetry/util.ts +27 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/turbo.json +20 -2
|
@@ -23,10 +23,8 @@ import { detect } from "package-manager-detector/detect";
|
|
|
23
23
|
import { AUTO_UPGRADE_EXIT_CODE, createDevServer } from "../index.js";
|
|
24
24
|
import { getTracer } from "../telemetry/index.js";
|
|
25
25
|
import { getErrorMeta, getLogger, type Logger } from "../telemetry/logging.js";
|
|
26
|
-
import {
|
|
27
|
-
|
|
28
|
-
getCurrentCliVersion,
|
|
29
|
-
} from "./automatic-upgrades.js";
|
|
26
|
+
import { checkVersionsAndWritePackageJson } from "./automatic-upgrades.js";
|
|
27
|
+
import { getCurrentCliVersion } from "./version-detection.js";
|
|
30
28
|
import type {
|
|
31
29
|
AuthHotReloadServer,
|
|
32
30
|
TokenManager,
|
|
@@ -284,322 +282,379 @@ export async function dev(options: {
|
|
|
284
282
|
const logger = getLogger(options.logger);
|
|
285
283
|
const skipAutoUpgrade = autoUpgradeMode === DevServerAutoUpgradeMode.SKIP;
|
|
286
284
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
logger.info(
|
|
296
|
-
`Running command: ${options.superblocksPath} dev${options.uploadFirst ? " --upload-first" : ""}${options.downloadFirst ? " --download-first" : ""} with baseUrl: ${tokenConfig.superblocksBaseUrl}, cliVersion: ${cliVersion?.version}${cliVersion?.alias ? ` (${cliVersion.alias})` : ""}`,
|
|
297
|
-
);
|
|
298
|
-
|
|
299
|
-
const port = devServerPort ?? 5173;
|
|
300
|
-
|
|
301
|
-
const fsOperationQueue = new OperationQueue();
|
|
302
|
-
if (applicationConfig && !skipSync) {
|
|
303
|
-
const rpcClient = new AutoConnectingRpcClient(
|
|
304
|
-
tokenConfig.superblocksBaseUrl,
|
|
305
|
-
tokenConfig.token,
|
|
306
|
-
tracer,
|
|
307
|
-
tokenManager,
|
|
308
|
-
logger,
|
|
309
|
-
);
|
|
285
|
+
await tracer.startActiveSpan("devServerStartup", async (startupSpan) => {
|
|
286
|
+
try {
|
|
287
|
+
// Add check for node_modules
|
|
288
|
+
if (!fs.existsSync(path.join(cwd, "node_modules"))) {
|
|
289
|
+
throw new Error(
|
|
290
|
+
'node_modules folder is missing. Please run "npm install" first.',
|
|
291
|
+
);
|
|
292
|
+
}
|
|
310
293
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
lockType: lockType,
|
|
325
|
-
tracer,
|
|
326
|
-
logger,
|
|
327
|
-
rpcClient,
|
|
328
|
-
inactivityThresholdMs: inactivityTimeoutMs,
|
|
329
|
-
});
|
|
294
|
+
const cliVersion = await tracer.startActiveSpan(
|
|
295
|
+
"getCurrentCliVersion",
|
|
296
|
+
async (span) => {
|
|
297
|
+
try {
|
|
298
|
+
return await getCurrentCliVersion();
|
|
299
|
+
} finally {
|
|
300
|
+
span.end();
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
);
|
|
304
|
+
logger.info(
|
|
305
|
+
`Running command: ${options.superblocksPath} dev${options.uploadFirst ? " --upload-first" : ""}${options.downloadFirst ? " --download-first" : ""} with baseUrl: ${tokenConfig.superblocksBaseUrl}, cliVersion: ${cliVersion?.version}${cliVersion?.alias ? ` (${cliVersion.alias})` : ""}`,
|
|
306
|
+
);
|
|
330
307
|
|
|
331
|
-
|
|
332
|
-
appRootDirPath: cwd,
|
|
333
|
-
applicationId: applicationConfig.id,
|
|
334
|
-
branchName: applicationConfig.branchName,
|
|
335
|
-
fsOperationQueue,
|
|
336
|
-
lockService: lockService,
|
|
337
|
-
tracer,
|
|
338
|
-
superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
|
|
339
|
-
rpcClient,
|
|
340
|
-
logger,
|
|
341
|
-
});
|
|
308
|
+
const port = devServerPort ?? 5173;
|
|
342
309
|
|
|
343
|
-
|
|
310
|
+
const fsOperationQueue = new OperationQueue();
|
|
311
|
+
if (applicationConfig && !skipSync) {
|
|
312
|
+
const rpcClient = new AutoConnectingRpcClient(
|
|
313
|
+
tokenConfig.superblocksBaseUrl,
|
|
314
|
+
tokenConfig.token,
|
|
315
|
+
tracer,
|
|
316
|
+
tokenManager,
|
|
317
|
+
logger,
|
|
318
|
+
);
|
|
344
319
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
await tracer.startActiveSpan("acquiringInitialLock", async (span) => {
|
|
320
|
+
// Get feature flags for inactivity timeout
|
|
321
|
+
const featureFlags = await tracer.startActiveSpan(
|
|
322
|
+
"getFeatureFlags",
|
|
323
|
+
async (span) => {
|
|
350
324
|
try {
|
|
351
|
-
|
|
352
|
-
if (options.forceTakeover) {
|
|
353
|
-
logger.info("Force takeover requested, taking over lock...");
|
|
354
|
-
await lockSvc.forceTakeover();
|
|
355
|
-
logger.info("Lock acquired successfully via force takeover.");
|
|
356
|
-
} else {
|
|
357
|
-
await lockSvc.acquireLock();
|
|
358
|
-
}
|
|
359
|
-
} catch (error) {
|
|
360
|
-
// If we got a conflict error (409), inspect the lock for more information
|
|
361
|
-
if (error instanceof ConflictError) {
|
|
362
|
-
await handleLockConflict(error, lockSvc, span, logger);
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
logger.error(
|
|
367
|
-
"Failed to acquire lock on application",
|
|
368
|
-
getErrorMeta(error),
|
|
369
|
-
);
|
|
370
|
-
span.setStatus({
|
|
371
|
-
code: SpanStatusCode.ERROR,
|
|
372
|
-
message: JSON.stringify(error),
|
|
373
|
-
});
|
|
374
|
-
passErrorToVSCode(
|
|
375
|
-
(error as { context?: { message: string } }).context?.message,
|
|
376
|
-
logger,
|
|
377
|
-
);
|
|
378
|
-
throw new Error(
|
|
379
|
-
`Failed to acquire lock on application: ${error}`,
|
|
380
|
-
);
|
|
325
|
+
return await sdk.getFeatureFlagsForCurrentUser();
|
|
381
326
|
} finally {
|
|
382
327
|
span.end();
|
|
383
328
|
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
aiService = new AiService({
|
|
329
|
+
},
|
|
330
|
+
);
|
|
331
|
+
const lockType =
|
|
332
|
+
process.env.SUPERBLOCKS_IS_CSB === "true"
|
|
333
|
+
? LockType.CSB
|
|
334
|
+
: LockType.LOCAL;
|
|
335
|
+
const inactivityTimeoutMs =
|
|
336
|
+
lockType === LockType.CSB
|
|
337
|
+
? featureFlags.devServerCloudInactivityTimeoutMinutes() * 60 * 1000
|
|
338
|
+
: featureFlags.devServerLocalInactivityTimeoutMinutes() * 60 * 1000;
|
|
339
|
+
|
|
340
|
+
lockService = new LockService({
|
|
399
341
|
superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
|
|
400
|
-
appRootDirPath: options.cwd,
|
|
401
342
|
applicationId: applicationConfig.id,
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
343
|
+
branchName: applicationConfig.branchName,
|
|
344
|
+
lockType: lockType,
|
|
345
|
+
tracer,
|
|
346
|
+
logger,
|
|
405
347
|
rpcClient,
|
|
348
|
+
inactivityThresholdMs: inactivityTimeoutMs,
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
syncService = new SyncService({
|
|
352
|
+
appRootDirPath: cwd,
|
|
353
|
+
applicationId: applicationConfig.id,
|
|
354
|
+
branchName: applicationConfig.branchName,
|
|
355
|
+
fsOperationQueue,
|
|
356
|
+
lockService: lockService,
|
|
406
357
|
tracer,
|
|
358
|
+
superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
|
|
359
|
+
rpcClient,
|
|
407
360
|
logger,
|
|
408
|
-
tokenManager,
|
|
409
|
-
features: AiServiceFeatureFlags.create(
|
|
410
|
-
currentUser.flagBootstrap as Record<string, unknown> | undefined,
|
|
411
|
-
),
|
|
412
|
-
pluginExecutionVersions:
|
|
413
|
-
currentUser.organizations[0].pluginExecutionVersions,
|
|
414
361
|
});
|
|
415
362
|
|
|
416
|
-
|
|
363
|
+
logger.info("Checking if local files are synced with the server");
|
|
364
|
+
|
|
365
|
+
try {
|
|
366
|
+
await maskUnixSignals(async () => {
|
|
367
|
+
if (lockService) {
|
|
368
|
+
const lockSvc = lockService;
|
|
369
|
+
await tracer.startActiveSpan(
|
|
370
|
+
"acquiringInitialLock",
|
|
371
|
+
async (span) => {
|
|
372
|
+
try {
|
|
373
|
+
// If --force-takeover flag is set, immediately force takeover instead of acquiring
|
|
374
|
+
if (options.forceTakeover) {
|
|
375
|
+
logger.info(
|
|
376
|
+
"Force takeover requested, taking over lock...",
|
|
377
|
+
);
|
|
378
|
+
await lockSvc.forceTakeover();
|
|
379
|
+
logger.info(
|
|
380
|
+
"Lock acquired successfully via force takeover.",
|
|
381
|
+
);
|
|
382
|
+
} else {
|
|
383
|
+
await lockSvc.acquireLock();
|
|
384
|
+
}
|
|
385
|
+
} catch (error) {
|
|
386
|
+
// If we got a conflict error (409), inspect the lock for more information
|
|
387
|
+
if (error instanceof ConflictError) {
|
|
388
|
+
await handleLockConflict(error, lockSvc, span, logger);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
logger.error(
|
|
393
|
+
"Failed to acquire lock on application",
|
|
394
|
+
getErrorMeta(error),
|
|
395
|
+
);
|
|
396
|
+
span.setStatus({
|
|
397
|
+
code: SpanStatusCode.ERROR,
|
|
398
|
+
message: JSON.stringify(error),
|
|
399
|
+
});
|
|
400
|
+
passErrorToVSCode(
|
|
401
|
+
(error as { context?: { message: string } }).context
|
|
402
|
+
?.message,
|
|
403
|
+
logger,
|
|
404
|
+
);
|
|
405
|
+
throw new Error(
|
|
406
|
+
`Failed to acquire lock on application: ${error}`,
|
|
407
|
+
);
|
|
408
|
+
} finally {
|
|
409
|
+
span.end();
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
);
|
|
413
|
+
}
|
|
417
414
|
|
|
418
|
-
|
|
415
|
+
const [localContents, serverHash, currentUser] =
|
|
416
|
+
await tracer.startActiveSpan("fetchInitInfo", async (span) => {
|
|
417
|
+
try {
|
|
418
|
+
const results = await Promise.all([
|
|
419
|
+
sdk.hashLocalDirectory(cwd),
|
|
420
|
+
getDraftOrLiveEditHash(sdk, applicationConfig, logger),
|
|
421
|
+
sdk.fetchCurrentUser(),
|
|
422
|
+
]);
|
|
423
|
+
return results;
|
|
424
|
+
} finally {
|
|
425
|
+
span.end();
|
|
426
|
+
}
|
|
427
|
+
});
|
|
419
428
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
+
aiService = new AiService({
|
|
430
|
+
superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
|
|
431
|
+
appRootDirPath: options.cwd,
|
|
432
|
+
applicationId: applicationConfig.id,
|
|
433
|
+
organizationId: currentUser.organizations[0].id,
|
|
434
|
+
fsOperationQueue,
|
|
435
|
+
draftInterface: syncService as DraftInterface,
|
|
436
|
+
rpcClient,
|
|
437
|
+
tracer,
|
|
438
|
+
logger,
|
|
439
|
+
tokenManager,
|
|
440
|
+
features: AiServiceFeatureFlags.create(
|
|
441
|
+
currentUser.flagBootstrap as
|
|
442
|
+
| Record<string, unknown>
|
|
443
|
+
| undefined,
|
|
444
|
+
),
|
|
445
|
+
pluginExecutionVersions:
|
|
446
|
+
currentUser.organizations[0].pluginExecutionVersions,
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
await tracer.startActiveSpan(
|
|
450
|
+
"aiServiceInitialize",
|
|
451
|
+
async (span) => {
|
|
452
|
+
try {
|
|
453
|
+
await aiService!.initialize();
|
|
454
|
+
} finally {
|
|
455
|
+
span.end();
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
);
|
|
429
459
|
|
|
430
|
-
|
|
431
|
-
throw new Error(
|
|
432
|
-
"You must choose --download-first or --upload-first to use the dev command",
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
if (downloadFirst && uploadFirst) {
|
|
436
|
-
throw new Error("Choose either --download-first or --upload-first");
|
|
437
|
-
}
|
|
460
|
+
const isSynced = localContents.hash === serverHash;
|
|
438
461
|
|
|
439
|
-
|
|
462
|
+
if (isSynced) {
|
|
463
|
+
logger.info(
|
|
464
|
+
`Local files are in sync with the server on branch '${applicationConfig.branchName}', local hash: ${localContents.hash}, server hash: ${serverHash}`,
|
|
465
|
+
);
|
|
466
|
+
} else {
|
|
467
|
+
logger.info(
|
|
468
|
+
`Local files are out of sync with the server on branch '${applicationConfig.branchName}', local hash: ${localContents.hash}, server hash: ${serverHash}`,
|
|
469
|
+
);
|
|
470
|
+
}
|
|
440
471
|
|
|
441
|
-
|
|
472
|
+
if (!(downloadFirst || uploadFirst)) {
|
|
473
|
+
throw new Error(
|
|
474
|
+
"You must choose --download-first or --upload-first to use the dev command",
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
if (downloadFirst && uploadFirst) {
|
|
478
|
+
throw new Error(
|
|
479
|
+
"Choose either --download-first or --upload-first",
|
|
480
|
+
);
|
|
481
|
+
}
|
|
442
482
|
|
|
443
|
-
|
|
444
|
-
await tracer.startActiveSpan("downloadFirst", async (span) => {
|
|
445
|
-
logger.info(
|
|
446
|
-
`Starting download of branch '${applicationConfig.branchName}'`,
|
|
447
|
-
);
|
|
483
|
+
let hasPackageChanged = false;
|
|
448
484
|
|
|
449
|
-
await
|
|
450
|
-
span.end();
|
|
451
|
-
});
|
|
452
|
-
}
|
|
485
|
+
const packageJsonBefore = await readPkgJson(cwd);
|
|
453
486
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
// Determine whether we must try to auto-upgrade the CLI
|
|
459
|
-
if (!skipAutoUpgrade || forceUpgrade) {
|
|
460
|
-
await tracer.startActiveSpan(
|
|
461
|
-
"versionCheckAndUpgrade",
|
|
462
|
-
async (span) => {
|
|
463
|
-
if (lockService) {
|
|
464
|
-
const applicationConfigWithTokenConfigAndUserInfo: ApplicationConfigWithTokenConfigAndUserInfo =
|
|
465
|
-
{
|
|
466
|
-
...applicationConfig,
|
|
467
|
-
superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
|
|
468
|
-
token: tokenConfig.token,
|
|
469
|
-
userId: currentUser.user.id,
|
|
470
|
-
userEmail: currentUser.user.email,
|
|
471
|
-
organizationId: currentUser.user.currentOrganizationId,
|
|
472
|
-
featureFlags: sdk.getFeatureFlagsForUser(currentUser),
|
|
473
|
-
};
|
|
474
|
-
|
|
475
|
-
const result = await checkVersionsAndWritePackageJson(
|
|
476
|
-
lockService,
|
|
477
|
-
applicationConfigWithTokenConfigAndUserInfo,
|
|
478
|
-
forceUpgrade,
|
|
487
|
+
if (downloadFirst && !isSynced) {
|
|
488
|
+
await tracer.startActiveSpan("downloadFirst", async (span) => {
|
|
489
|
+
logger.info(
|
|
490
|
+
`Starting download of branch '${applicationConfig.branchName}'`,
|
|
479
491
|
);
|
|
480
|
-
hasCliUpdated = result.cliUpdated;
|
|
481
|
-
upgradePromises = result.upgradePromises;
|
|
482
|
-
} else {
|
|
483
|
-
logger.warn(
|
|
484
|
-
"Lock service is not available, skipping version check and upgrade",
|
|
485
|
-
);
|
|
486
|
-
}
|
|
487
|
-
span.end();
|
|
488
|
-
},
|
|
489
|
-
);
|
|
490
|
-
}
|
|
491
492
|
|
|
492
|
-
|
|
493
|
+
await syncService!.downloadDirectory();
|
|
494
|
+
span.end();
|
|
495
|
+
});
|
|
496
|
+
}
|
|
493
497
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
498
|
+
let hasCliUpdated = false;
|
|
499
|
+
let upgradePromises: Promise<void>[] = [];
|
|
500
|
+
const forceUpgrade =
|
|
501
|
+
options.autoUpgradeMode === DevServerAutoUpgradeMode.FORCE;
|
|
502
|
+
// Determine whether we must try to auto-upgrade the CLI
|
|
503
|
+
if (!skipAutoUpgrade || forceUpgrade) {
|
|
504
|
+
await tracer.startActiveSpan(
|
|
505
|
+
"versionCheckAndUpgrade",
|
|
506
|
+
async (span) => {
|
|
507
|
+
if (lockService) {
|
|
508
|
+
const applicationConfigWithTokenConfigAndUserInfo: ApplicationConfigWithTokenConfigAndUserInfo =
|
|
509
|
+
{
|
|
510
|
+
...applicationConfig,
|
|
511
|
+
superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
|
|
512
|
+
token: tokenConfig.token,
|
|
513
|
+
userId: currentUser.user.id,
|
|
514
|
+
userEmail: currentUser.user.email,
|
|
515
|
+
organizationId: currentUser.user.currentOrganizationId,
|
|
516
|
+
featureFlags: sdk.getFeatureFlagsForUser(currentUser),
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
const result = await checkVersionsAndWritePackageJson(
|
|
520
|
+
lockService,
|
|
521
|
+
applicationConfigWithTokenConfigAndUserInfo,
|
|
522
|
+
forceUpgrade,
|
|
523
|
+
);
|
|
524
|
+
hasCliUpdated = result.cliUpdated;
|
|
525
|
+
upgradePromises = result.upgradePromises;
|
|
526
|
+
} else {
|
|
527
|
+
logger.warn(
|
|
528
|
+
"Lock service is not available, skipping version check and upgrade",
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
span.end();
|
|
532
|
+
},
|
|
533
|
+
);
|
|
534
|
+
}
|
|
502
535
|
|
|
503
|
-
|
|
504
|
-
logger.info("Installing packages…");
|
|
505
|
-
await tracer.startActiveSpan("installPackages", async (span) => {
|
|
506
|
-
// Upgrade global CLI and local packages in parallel - improves performance
|
|
507
|
-
await Promise.all([
|
|
508
|
-
...upgradePromises,
|
|
509
|
-
installPackages(cwd, logger),
|
|
510
|
-
]);
|
|
511
|
-
span.end();
|
|
512
|
-
});
|
|
513
|
-
} else {
|
|
514
|
-
logger.info(
|
|
515
|
-
"package.json has not changed, skipping package installation",
|
|
516
|
-
);
|
|
517
|
-
}
|
|
536
|
+
const packageJsonAfter = await readPkgJson(cwd);
|
|
518
537
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
538
|
+
if (packageJsonBefore && packageJsonAfter) {
|
|
539
|
+
hasPackageChanged =
|
|
540
|
+
JSON.stringify(packageJsonBefore, null, 2) !==
|
|
541
|
+
JSON.stringify(packageJsonAfter, null, 2);
|
|
542
|
+
} else if (packageJsonAfter) {
|
|
543
|
+
hasPackageChanged = true;
|
|
544
|
+
logger.info("package.json was created, installing packages…");
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (hasPackageChanged || upgradePromises.length > 0) {
|
|
548
|
+
logger.info("Installing packages…");
|
|
549
|
+
await tracer.startActiveSpan("installPackages", async (span) => {
|
|
550
|
+
try {
|
|
551
|
+
// Upgrade global CLI and local packages in parallel - improves performance
|
|
552
|
+
await Promise.all([
|
|
553
|
+
...upgradePromises,
|
|
554
|
+
installPackages(cwd, logger),
|
|
555
|
+
]);
|
|
556
|
+
} finally {
|
|
557
|
+
span.end();
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
} else {
|
|
561
|
+
logger.info(
|
|
562
|
+
"package.json has not changed, skipping package installation",
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (hasPackageChanged || uploadFirst) {
|
|
567
|
+
logger.info(
|
|
568
|
+
`Uploading local files to branch '${applicationConfig.branchName}' on server before starting`,
|
|
569
|
+
);
|
|
570
|
+
await tracer.startActiveSpan(
|
|
571
|
+
"uploadFirstOrPackageChanged",
|
|
572
|
+
async (span) => {
|
|
573
|
+
await syncService!.uploadDirectory("cli:sdk");
|
|
574
|
+
await syncService!.uploadDirectoryNowIfNeeded("cli:sdk");
|
|
575
|
+
span.end();
|
|
576
|
+
},
|
|
577
|
+
);
|
|
578
|
+
}
|
|
532
579
|
|
|
533
|
-
|
|
580
|
+
if (hasCliUpdated) {
|
|
581
|
+
try {
|
|
582
|
+
logger.info("Releasing lock before restarting the dev server");
|
|
583
|
+
await aiService?.removeIntegrationCache();
|
|
584
|
+
await lockService?.shutdown({ serverInitiated: false });
|
|
585
|
+
} catch (e) {
|
|
586
|
+
logger.error(
|
|
587
|
+
"Error releasing lock before restarting the dev server",
|
|
588
|
+
getErrorMeta(e),
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
logger.info("CLI was updated, restarting the dev server…");
|
|
592
|
+
process.exit(AUTO_UPGRADE_EXIT_CODE);
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
} catch (error: any) {
|
|
596
|
+
logger.error(error.message);
|
|
534
597
|
try {
|
|
535
|
-
logger.info("Releasing lock before restarting the dev server");
|
|
536
598
|
await aiService?.removeIntegrationCache();
|
|
537
|
-
await lockService?.
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
getErrorMeta(e),
|
|
542
|
-
);
|
|
599
|
+
await lockService?.shutdownAndExit();
|
|
600
|
+
} finally {
|
|
601
|
+
// this is redundant, but it's here to make sure the lock service is shutdown and the process exits
|
|
602
|
+
process.exit(1);
|
|
543
603
|
}
|
|
544
|
-
logger.info("CLI was updated, restarting the dev server…");
|
|
545
|
-
process.exit(AUTO_UPGRADE_EXIT_CODE);
|
|
546
604
|
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
logger.error(error.message);
|
|
550
|
-
try {
|
|
551
|
-
await aiService?.removeIntegrationCache();
|
|
552
|
-
await lockService?.shutdownAndExit();
|
|
553
|
-
} finally {
|
|
554
|
-
// this is redundant, but it's here to make sure the lock service is shutdown and the process exits
|
|
555
|
-
process.exit(1);
|
|
605
|
+
} else {
|
|
606
|
+
logger.info("Skipping directory sync");
|
|
556
607
|
}
|
|
557
|
-
}
|
|
558
|
-
} else {
|
|
559
|
-
logger.info("Skipping directory sync");
|
|
560
|
-
}
|
|
561
608
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
609
|
+
const httpServer = await tracer.startActiveSpan(
|
|
610
|
+
"createDevServer",
|
|
611
|
+
async (span) => {
|
|
612
|
+
const result = await createDevServer({
|
|
613
|
+
root: options.cwd,
|
|
614
|
+
mode: "development",
|
|
615
|
+
port: port,
|
|
616
|
+
fsOperationQueue,
|
|
617
|
+
syncService: syncService,
|
|
618
|
+
lockService: lockService,
|
|
619
|
+
aiService: aiService,
|
|
620
|
+
logger: options.logger,
|
|
621
|
+
sdk,
|
|
622
|
+
});
|
|
623
|
+
span.end();
|
|
624
|
+
return result;
|
|
625
|
+
},
|
|
626
|
+
);
|
|
580
627
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
628
|
+
options.signal?.addEventListener("abort", () => {
|
|
629
|
+
logger.info("Server closed");
|
|
630
|
+
httpServer.close();
|
|
631
|
+
// Stop auth hot-reload server on abort
|
|
632
|
+
if (authHotReloadServer) {
|
|
633
|
+
authHotReloadServer.stop().catch((error: any) => {
|
|
634
|
+
logger.warn(`Error stopping auth hot-reload server: ${error}`);
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
// Clean up AI service cache (must happen before app switches directories)
|
|
638
|
+
aiService?.removeIntegrationCache().catch((error: any) => {
|
|
639
|
+
logger.warn(`Error removing integration cache: ${error}`);
|
|
640
|
+
});
|
|
641
|
+
lockService?.shutdownAndExit().catch(() => {
|
|
642
|
+
// this is redundant, but it's here to make sure the lock service is shutdown and the process exits
|
|
643
|
+
process.exit(1);
|
|
644
|
+
});
|
|
588
645
|
});
|
|
646
|
+
|
|
647
|
+
logger.debug(green(`Local server started at port ${port}`));
|
|
648
|
+
logger.debug(green(`Visit your application at:`));
|
|
649
|
+
logger.debug(green(`http://localhost:${port}`));
|
|
650
|
+
|
|
651
|
+
startupSpan.end();
|
|
652
|
+
} catch (error) {
|
|
653
|
+
startupSpan.setStatus({ code: SpanStatusCode.ERROR });
|
|
654
|
+
startupSpan.end();
|
|
655
|
+
throw error;
|
|
589
656
|
}
|
|
590
|
-
// Clean up AI service cache (must happen before app switches directories)
|
|
591
|
-
aiService?.removeIntegrationCache().catch((error: any) => {
|
|
592
|
-
logger.warn(`Error removing integration cache: ${error}`);
|
|
593
|
-
});
|
|
594
|
-
lockService?.shutdownAndExit().catch(() => {
|
|
595
|
-
// this is redundant, but it's here to make sure the lock service is shutdown and the process exits
|
|
596
|
-
process.exit(1);
|
|
597
|
-
});
|
|
598
657
|
});
|
|
599
|
-
|
|
600
|
-
logger.debug(green(`Local server started at port ${port}`));
|
|
601
|
-
logger.debug(green(`Visit your application at:`));
|
|
602
|
-
logger.debug(green(`http://localhost:${port}`));
|
|
603
658
|
}
|
|
604
659
|
async function getDraftOrLiveEditHash(
|
|
605
660
|
sdk: SuperblocksSdk,
|