@superblocksteam/sdk 2.0.83-next.1 → 2.0.83
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 +6 -0
- package/dist/cli-replacement/automatic-upgrades.d.ts.map +1 -1
- package/dist/cli-replacement/automatic-upgrades.js +27 -5
- 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 +217 -260
- package/dist/cli-replacement/dev.mjs.map +1 -1
- package/dist/dev-utils/dev-server.mjs +115 -133
- 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 +64 -92
- package/dist/telemetry/index.js.map +1 -1
- package/dist/telemetry/util.d.ts +2 -1
- package/dist/telemetry/util.d.ts.map +1 -1
- package/dist/telemetry/util.js +4 -26
- package/dist/telemetry/util.js.map +1 -1
- package/package.json +5 -6
- package/src/cli-replacement/automatic-upgrades.ts +42 -10
- package/src/cli-replacement/dev.mts +281 -336
- package/src/dev-utils/dev-server.mts +127 -149
- package/src/telemetry/index.ts +83 -105
- package/src/telemetry/util.ts +4 -27
- package/tsconfig.tsbuildinfo +1 -1
- package/turbo.json +2 -20
- package/dist/cli-replacement/version-detection.d.ts +0 -71
- package/dist/cli-replacement/version-detection.d.ts.map +0 -1
- package/dist/cli-replacement/version-detection.js +0 -186
- package/dist/cli-replacement/version-detection.js.map +0 -1
- package/dist/cli-replacement/version-detection.test.d.ts +0 -5
- package/dist/cli-replacement/version-detection.test.d.ts.map +0 -1
- package/dist/cli-replacement/version-detection.test.js +0 -257
- package/dist/cli-replacement/version-detection.test.js.map +0 -1
- package/dist/telemetry/index.test.d.ts +0 -2
- package/dist/telemetry/index.test.d.ts.map +0 -1
- package/dist/telemetry/index.test.js +0 -93
- package/dist/telemetry/index.test.js.map +0 -1
- package/dist/telemetry/local-obs.d.ts +0 -73
- package/dist/telemetry/local-obs.d.ts.map +0 -1
- package/dist/telemetry/local-obs.js +0 -107
- package/dist/telemetry/local-obs.js.map +0 -1
- package/src/cli-replacement/version-detection.test.ts +0 -336
- package/src/cli-replacement/version-detection.ts +0 -220
- package/src/telemetry/index.test.ts +0 -130
- package/src/telemetry/local-obs.ts +0 -138
|
@@ -23,8 +23,10 @@ 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
|
-
|
|
26
|
+
import {
|
|
27
|
+
checkVersionsAndWritePackageJson,
|
|
28
|
+
getCurrentCliVersion,
|
|
29
|
+
} from "./automatic-upgrades.js";
|
|
28
30
|
import type {
|
|
29
31
|
AuthHotReloadServer,
|
|
30
32
|
TokenManager,
|
|
@@ -282,379 +284,322 @@ export async function dev(options: {
|
|
|
282
284
|
const logger = getLogger(options.logger);
|
|
283
285
|
const skipAutoUpgrade = autoUpgradeMode === DevServerAutoUpgradeMode.SKIP;
|
|
284
286
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
);
|
|
292
|
-
}
|
|
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
|
+
}
|
|
293
293
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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
|
-
);
|
|
294
|
+
const cliVersion = await getCurrentCliVersion();
|
|
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
|
+
);
|
|
307
298
|
|
|
308
|
-
|
|
299
|
+
const port = devServerPort ?? 5173;
|
|
309
300
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
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
|
+
);
|
|
310
|
+
|
|
311
|
+
// Get feature flags for inactivity timeout
|
|
312
|
+
const featureFlags = await sdk.getFeatureFlagsForCurrentUser();
|
|
313
|
+
const lockType =
|
|
314
|
+
process.env.SUPERBLOCKS_IS_CSB === "true" ? LockType.CSB : LockType.LOCAL;
|
|
315
|
+
const inactivityTimeoutMs =
|
|
316
|
+
lockType === LockType.CSB
|
|
317
|
+
? featureFlags.devServerCloudInactivityTimeoutMinutes() * 60 * 1000
|
|
318
|
+
: featureFlags.devServerLocalInactivityTimeoutMinutes() * 60 * 1000;
|
|
319
|
+
|
|
320
|
+
lockService = new LockService({
|
|
321
|
+
superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
|
|
322
|
+
applicationId: applicationConfig.id,
|
|
323
|
+
branchName: applicationConfig.branchName,
|
|
324
|
+
lockType: lockType,
|
|
325
|
+
tracer,
|
|
326
|
+
logger,
|
|
327
|
+
rpcClient,
|
|
328
|
+
inactivityThresholdMs: inactivityTimeoutMs,
|
|
329
|
+
});
|
|
319
330
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
331
|
+
syncService = new SyncService({
|
|
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
|
+
});
|
|
342
|
+
|
|
343
|
+
logger.info("Checking if local files are synced with the server");
|
|
344
|
+
|
|
345
|
+
try {
|
|
346
|
+
await maskUnixSignals(async () => {
|
|
347
|
+
if (lockService) {
|
|
348
|
+
const lockSvc = lockService;
|
|
349
|
+
await tracer.startActiveSpan("acquiringInitialLock", async (span) => {
|
|
324
350
|
try {
|
|
325
|
-
|
|
351
|
+
// If --force-takeover flag is set, immediately force takeover instead of acquiring
|
|
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
|
+
);
|
|
326
381
|
} finally {
|
|
327
382
|
span.end();
|
|
328
383
|
}
|
|
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({
|
|
341
|
-
superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
|
|
342
|
-
applicationId: applicationConfig.id,
|
|
343
|
-
branchName: applicationConfig.branchName,
|
|
344
|
-
lockType: lockType,
|
|
345
|
-
tracer,
|
|
346
|
-
logger,
|
|
347
|
-
rpcClient,
|
|
348
|
-
inactivityThresholdMs: inactivityTimeoutMs,
|
|
349
|
-
});
|
|
384
|
+
});
|
|
385
|
+
}
|
|
350
386
|
|
|
351
|
-
|
|
352
|
-
|
|
387
|
+
const [localContents, serverHash, currentUser] =
|
|
388
|
+
await tracer.startActiveSpan("fetchInitInfo", async (span) => {
|
|
389
|
+
const results = await Promise.all([
|
|
390
|
+
sdk.hashLocalDirectory(cwd),
|
|
391
|
+
getDraftOrLiveEditHash(sdk, applicationConfig, logger),
|
|
392
|
+
sdk.fetchCurrentUser(),
|
|
393
|
+
]);
|
|
394
|
+
span.end();
|
|
395
|
+
return results;
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
aiService = new AiService({
|
|
399
|
+
superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
|
|
400
|
+
appRootDirPath: options.cwd,
|
|
353
401
|
applicationId: applicationConfig.id,
|
|
354
|
-
|
|
402
|
+
organizationId: currentUser.organizations[0].id,
|
|
355
403
|
fsOperationQueue,
|
|
356
|
-
|
|
357
|
-
tracer,
|
|
358
|
-
superblocksBaseUrl: tokenConfig.superblocksBaseUrl,
|
|
404
|
+
draftInterface: syncService as DraftInterface,
|
|
359
405
|
rpcClient,
|
|
406
|
+
tracer,
|
|
360
407
|
logger,
|
|
408
|
+
tokenManager,
|
|
409
|
+
features: AiServiceFeatureFlags.create(
|
|
410
|
+
currentUser.flagBootstrap as Record<string, unknown> | undefined,
|
|
411
|
+
),
|
|
412
|
+
pluginExecutionVersions:
|
|
413
|
+
currentUser.organizations[0].pluginExecutionVersions,
|
|
361
414
|
});
|
|
362
415
|
|
|
363
|
-
|
|
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
|
-
}
|
|
416
|
+
await aiService.initialize();
|
|
414
417
|
|
|
415
|
-
|
|
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
|
-
});
|
|
418
|
+
const isSynced = localContents.hash === serverHash;
|
|
428
419
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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
|
-
);
|
|
420
|
+
if (isSynced) {
|
|
421
|
+
logger.info(
|
|
422
|
+
`Local files are in sync with the server on branch '${applicationConfig.branchName}', local hash: ${localContents.hash}, server hash: ${serverHash}`,
|
|
423
|
+
);
|
|
424
|
+
} else {
|
|
425
|
+
logger.info(
|
|
426
|
+
`Local files are out of sync with the server on branch '${applicationConfig.branchName}', local hash: ${localContents.hash}, server hash: ${serverHash}`,
|
|
427
|
+
);
|
|
428
|
+
}
|
|
459
429
|
|
|
460
|
-
|
|
430
|
+
if (!(downloadFirst || uploadFirst)) {
|
|
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
|
+
}
|
|
461
438
|
|
|
462
|
-
|
|
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
|
-
}
|
|
439
|
+
let hasPackageChanged = false;
|
|
471
440
|
|
|
472
|
-
|
|
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
|
-
}
|
|
441
|
+
const packageJsonBefore = await readPkgJson(cwd);
|
|
482
442
|
|
|
483
|
-
|
|
443
|
+
if (downloadFirst && !isSynced) {
|
|
444
|
+
await tracer.startActiveSpan("downloadFirst", async (span) => {
|
|
445
|
+
logger.info(
|
|
446
|
+
`Starting download of branch '${applicationConfig.branchName}'`,
|
|
447
|
+
);
|
|
484
448
|
|
|
485
|
-
|
|
449
|
+
await syncService!.downloadDirectory();
|
|
450
|
+
span.end();
|
|
451
|
+
});
|
|
452
|
+
}
|
|
486
453
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
454
|
+
let hasCliUpdated = false;
|
|
455
|
+
let upgradePromises: Promise<void>[] = [];
|
|
456
|
+
const forceUpgrade =
|
|
457
|
+
options.autoUpgradeMode === DevServerAutoUpgradeMode.FORCE;
|
|
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,
|
|
491
479
|
);
|
|
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
|
+
}
|
|
492
491
|
|
|
493
|
-
|
|
494
|
-
span.end();
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
|
|
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
|
-
}
|
|
535
|
-
|
|
536
|
-
const packageJsonAfter = await readPkgJson(cwd);
|
|
492
|
+
const packageJsonAfter = await readPkgJson(cwd);
|
|
537
493
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
494
|
+
if (packageJsonBefore && packageJsonAfter) {
|
|
495
|
+
hasPackageChanged =
|
|
496
|
+
JSON.stringify(packageJsonBefore, null, 2) !==
|
|
497
|
+
JSON.stringify(packageJsonAfter, null, 2);
|
|
498
|
+
} else if (packageJsonAfter) {
|
|
499
|
+
hasPackageChanged = true;
|
|
500
|
+
logger.info("package.json was created, installing packages…");
|
|
501
|
+
}
|
|
546
502
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
"package.json has not changed, skipping package installation",
|
|
563
|
-
);
|
|
564
|
-
}
|
|
503
|
+
if (hasPackageChanged || upgradePromises.length > 0) {
|
|
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
|
+
}
|
|
565
518
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
519
|
+
if (hasPackageChanged || uploadFirst) {
|
|
520
|
+
logger.info(
|
|
521
|
+
`Uploading local files to branch '${applicationConfig.branchName}' on server before starting`,
|
|
522
|
+
);
|
|
523
|
+
await tracer.startActiveSpan(
|
|
524
|
+
"uploadFirstOrPackageChanged",
|
|
525
|
+
async (span) => {
|
|
526
|
+
await syncService!.uploadDirectory("cli:sdk");
|
|
527
|
+
await syncService!.uploadDirectoryNowIfNeeded("cli:sdk");
|
|
528
|
+
span.end();
|
|
529
|
+
},
|
|
530
|
+
);
|
|
531
|
+
}
|
|
579
532
|
|
|
580
|
-
|
|
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);
|
|
533
|
+
if (hasCliUpdated) {
|
|
597
534
|
try {
|
|
535
|
+
logger.info("Releasing lock before restarting the dev server");
|
|
598
536
|
await aiService?.removeIntegrationCache();
|
|
599
|
-
await lockService?.
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
|
|
537
|
+
await lockService?.shutdown({ serverInitiated: false });
|
|
538
|
+
} catch (e) {
|
|
539
|
+
logger.error(
|
|
540
|
+
"Error releasing lock before restarting the dev server",
|
|
541
|
+
getErrorMeta(e),
|
|
542
|
+
);
|
|
603
543
|
}
|
|
544
|
+
logger.info("CLI was updated, restarting the dev server…");
|
|
545
|
+
process.exit(AUTO_UPGRADE_EXIT_CODE);
|
|
604
546
|
}
|
|
605
|
-
}
|
|
606
|
-
|
|
547
|
+
});
|
|
548
|
+
} catch (error: any) {
|
|
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);
|
|
607
556
|
}
|
|
557
|
+
}
|
|
558
|
+
} else {
|
|
559
|
+
logger.info("Skipping directory sync");
|
|
560
|
+
}
|
|
608
561
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
});
|
|
623
|
-
span.end();
|
|
624
|
-
return result;
|
|
625
|
-
},
|
|
626
|
-
);
|
|
627
|
-
|
|
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
|
-
});
|
|
562
|
+
const httpServer = await tracer.startActiveSpan(
|
|
563
|
+
"createDevServer",
|
|
564
|
+
async (span) => {
|
|
565
|
+
const result = await createDevServer({
|
|
566
|
+
root: options.cwd,
|
|
567
|
+
mode: "development",
|
|
568
|
+
port: port,
|
|
569
|
+
fsOperationQueue,
|
|
570
|
+
syncService: syncService,
|
|
571
|
+
lockService: lockService,
|
|
572
|
+
aiService: aiService,
|
|
573
|
+
logger: options.logger,
|
|
574
|
+
sdk,
|
|
645
575
|
});
|
|
576
|
+
span.end();
|
|
577
|
+
return result;
|
|
578
|
+
},
|
|
579
|
+
);
|
|
646
580
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
throw error;
|
|
581
|
+
options.signal?.addEventListener("abort", () => {
|
|
582
|
+
logger.info("Server closed");
|
|
583
|
+
httpServer.close();
|
|
584
|
+
// Stop auth hot-reload server on abort
|
|
585
|
+
if (authHotReloadServer) {
|
|
586
|
+
authHotReloadServer.stop().catch((error: any) => {
|
|
587
|
+
logger.warn(`Error stopping auth hot-reload server: ${error}`);
|
|
588
|
+
});
|
|
656
589
|
}
|
|
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
|
+
});
|
|
657
598
|
});
|
|
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}`));
|
|
658
603
|
}
|
|
659
604
|
async function getDraftOrLiveEditHash(
|
|
660
605
|
sdk: SuperblocksSdk,
|