everything-dev 1.16.2 → 1.16.3

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 (56) hide show
  1. package/dist/api-contract.cjs +16 -5
  2. package/dist/api-contract.cjs.map +1 -1
  3. package/dist/api-contract.mjs +16 -5
  4. package/dist/api-contract.mjs.map +1 -1
  5. package/dist/cli/timing.cjs +30 -0
  6. package/dist/cli/timing.cjs.map +1 -0
  7. package/dist/cli/timing.mjs +27 -0
  8. package/dist/cli/timing.mjs.map +1 -0
  9. package/dist/cli/upgrade.cjs +66 -47
  10. package/dist/cli/upgrade.cjs.map +1 -1
  11. package/dist/cli/upgrade.mjs +66 -47
  12. package/dist/cli/upgrade.mjs.map +1 -1
  13. package/dist/cli.cjs +9 -0
  14. package/dist/cli.cjs.map +1 -1
  15. package/dist/cli.mjs +9 -0
  16. package/dist/cli.mjs.map +1 -1
  17. package/dist/components/dev-view.cjs +1 -1
  18. package/dist/components/dev-view.mjs +1 -1
  19. package/dist/components/streaming-view.cjs +1 -1
  20. package/dist/components/streaming-view.mjs +1 -1
  21. package/dist/contract.cjs +7 -0
  22. package/dist/contract.cjs.map +1 -1
  23. package/dist/contract.d.cts +24 -3
  24. package/dist/contract.d.cts.map +1 -1
  25. package/dist/contract.d.mts +24 -3
  26. package/dist/contract.d.mts.map +1 -1
  27. package/dist/contract.mjs +7 -1
  28. package/dist/contract.mjs.map +1 -1
  29. package/dist/dev-session.cjs +5 -3
  30. package/dist/dev-session.cjs.map +1 -1
  31. package/dist/dev-session.mjs +3 -3
  32. package/dist/dev-session.mjs.map +1 -1
  33. package/dist/index.cjs +1 -0
  34. package/dist/index.d.cts +2 -2
  35. package/dist/index.d.mts +2 -2
  36. package/dist/index.mjs +2 -2
  37. package/dist/orchestrator.cjs +1 -1
  38. package/dist/orchestrator.mjs +1 -1
  39. package/dist/plugin.cjs +38 -24
  40. package/dist/plugin.cjs.map +1 -1
  41. package/dist/plugin.d.cts +10 -2
  42. package/dist/plugin.d.cts.map +1 -1
  43. package/dist/plugin.d.mts +10 -2
  44. package/dist/plugin.d.mts.map +1 -1
  45. package/dist/plugin.mjs +37 -23
  46. package/dist/plugin.mjs.map +1 -1
  47. package/dist/types.d.cts +2 -2
  48. package/dist/types.d.mts +2 -2
  49. package/package.json +1 -1
  50. package/src/api-contract.ts +21 -3
  51. package/src/cli/timing.ts +36 -0
  52. package/src/cli/upgrade.ts +82 -53
  53. package/src/cli.ts +15 -0
  54. package/src/contract.ts +8 -0
  55. package/src/dev-session.ts +1 -1
  56. package/src/plugin.ts +75 -38
@@ -3,12 +3,13 @@ import { join } from "node:path";
3
3
  import process from "node:process";
4
4
  import * as p from "@clack/prompts";
5
5
  import { glob } from "glob";
6
- import type { UpgradeOptions, UpgradeResult } from "../contract";
6
+ import type { PhaseTiming, UpgradeOptions, UpgradeResult } from "../contract";
7
7
  import { resolveExtendsRef } from "../merge";
8
8
  import { saveBosConfig } from "../utils/save-config";
9
9
  import { readInstalledFrameworkVersion } from "./framework-version";
10
10
  import { fetchParentConfig, runBunInstall, runTypesGen } from "./init";
11
11
  import { syncTemplate } from "./sync";
12
+ import { timePhase } from "./timing";
12
13
 
13
14
  const FRAMEWORK_PACKAGES = ["everything-dev", "every-plugin"];
14
15
 
@@ -333,38 +334,52 @@ export async function upgradeTemplate(
333
334
  projectDir: string,
334
335
  options: UpgradeOptions,
335
336
  ): Promise<UpgradeResult> {
337
+ const timings: PhaseTiming[] = [];
336
338
  const pkgPath = join(projectDir, "package.json");
337
339
  if (!existsSync(pkgPath)) {
338
340
  return {
339
341
  status: "error",
340
342
  packages: [],
343
+ timings,
341
344
  error: "No package.json found in current directory",
342
345
  };
343
346
  }
344
347
 
345
- const packages: UpgradeResult["packages"] = [];
348
+ const { packages, catalogVersionUpdates } = await timePhase(
349
+ timings,
350
+ "check package versions",
351
+ async () => {
352
+ const nextPackages: UpgradeResult["packages"] = [];
346
353
 
347
- for (const name of FRAMEWORK_PACKAGES) {
348
- const installed = readInstalledVersion(projectDir, name);
349
- const latest = await fetchLatestNpmVersion(name);
354
+ for (const name of FRAMEWORK_PACKAGES) {
355
+ const installed = readInstalledVersion(projectDir, name);
356
+ const latest = await fetchLatestNpmVersion(name);
350
357
 
351
- if (!latest) {
352
- packages.push({ name, from: installed, to: installed ?? "unknown" });
353
- continue;
354
- }
358
+ if (!latest) {
359
+ nextPackages.push({ name, from: installed, to: installed ?? "unknown" });
360
+ continue;
361
+ }
355
362
 
356
- packages.push({ name, from: installed, to: latest });
357
- }
363
+ nextPackages.push({ name, from: installed, to: latest });
364
+ }
358
365
 
359
- const catalogVersionUpdates: Array<{ name: string; from: string | undefined; to: string }> = [];
360
- for (const name of CATALOG_TOOL_PACKAGES) {
361
- const installed = readInstalledVersion(projectDir, name);
362
- if (!installed) continue;
363
- const latest = await fetchLatestNpmVersion(name);
364
- if (!latest) continue;
365
- if (installed === latest) continue;
366
- catalogVersionUpdates.push({ name, from: installed, to: latest });
367
- }
366
+ const nextCatalogVersionUpdates: Array<{
367
+ name: string;
368
+ from: string | undefined;
369
+ to: string;
370
+ }> = [];
371
+ for (const name of CATALOG_TOOL_PACKAGES) {
372
+ const installed = readInstalledVersion(projectDir, name);
373
+ if (!installed) continue;
374
+ const latest = await fetchLatestNpmVersion(name);
375
+ if (!latest) continue;
376
+ if (installed === latest) continue;
377
+ nextCatalogVersionUpdates.push({ name, from: installed, to: latest });
378
+ }
379
+
380
+ return { packages: nextPackages, catalogVersionUpdates: nextCatalogVersionUpdates };
381
+ },
382
+ );
368
383
 
369
384
  const hasFrameworkUpdates = packages.some((p) => p.from !== p.to && p.from !== undefined);
370
385
  const hasCatalogUpdates = catalogVersionUpdates.length > 0;
@@ -372,7 +387,11 @@ export async function upgradeTemplate(
372
387
 
373
388
  if (options.dryRun) {
374
389
  let changelogUrl: string | undefined;
375
- const pluginOptions = options.noSync ? null : await loadParentPluginOptions(projectDir);
390
+ const pluginOptions = options.noSync
391
+ ? null
392
+ : await timePhase(timings, "discover parent plugins", () =>
393
+ loadParentPluginOptions(projectDir),
394
+ );
376
395
  if (hasUpdates) {
377
396
  const configPath = join(projectDir, "bos.config.json");
378
397
  let parentConfig: Record<string, unknown> | null = null;
@@ -394,59 +413,68 @@ export async function upgradeTemplate(
394
413
  ...catalogVersionUpdates.map((u) => ({ name: u.name, from: u.from, to: u.to })),
395
414
  ],
396
415
  availablePlugins: pluginOptions?.newPluginKeys,
416
+ timings,
397
417
  changelogUrl,
398
418
  };
399
419
  }
400
420
 
401
- for (const pkg of packages) {
402
- if (pkg.from !== undefined && pkg.from !== pkg.to) {
403
- updateRootPackageVersion(projectDir, pkg.name, pkg.to);
404
- }
405
- }
406
-
407
- for (const update of catalogVersionUpdates) {
408
- updateRootCatalogVersion(projectDir, update.name, update.to);
409
- }
410
-
411
- const workspacePkgPaths = await findWorkspacePackageJsons(projectDir);
412
- for (const pkgPath of workspacePkgPaths) {
421
+ await timePhase(timings, "apply package updates", async () => {
413
422
  for (const pkg of packages) {
414
423
  if (pkg.from !== undefined && pkg.from !== pkg.to) {
415
- updateWorkspacePackageRefInFile(pkgPath, pkg.name);
424
+ updateRootPackageVersion(projectDir, pkg.name, pkg.to);
416
425
  }
417
426
  }
427
+
418
428
  for (const update of catalogVersionUpdates) {
419
- updateWorkspacePackageRefInFile(pkgPath, update.name);
429
+ updateRootCatalogVersion(projectDir, update.name, update.to);
420
430
  }
421
- }
431
+
432
+ const workspacePkgPaths = await findWorkspacePackageJsons(projectDir);
433
+ for (const pkgPath of workspacePkgPaths) {
434
+ for (const pkg of packages) {
435
+ if (pkg.from !== undefined && pkg.from !== pkg.to) {
436
+ updateWorkspacePackageRefInFile(pkgPath, pkg.name);
437
+ }
438
+ }
439
+ for (const update of catalogVersionUpdates) {
440
+ updateWorkspacePackageRefInFile(pkgPath, update.name);
441
+ }
442
+ }
443
+ });
422
444
 
423
445
  let syncResult: UpgradeResult["sync"];
424
446
  let addedPlugins: string[] = [];
425
447
  if (!options.noSync) {
426
- if (!options.dryRun) {
427
- addedPlugins = await addSelectedParentPlugins(projectDir);
428
- }
429
-
430
- syncResult = await syncTemplate(projectDir, {
431
- dryRun: false,
432
- force: options.force,
433
- noInstall: true,
448
+ addedPlugins = await timePhase(timings, "discover parent plugins", async () => {
449
+ if (options.dryRun) return [];
450
+ return addSelectedParentPlugins(projectDir);
434
451
  });
452
+
453
+ syncResult = await timePhase(timings, "sync template", () =>
454
+ syncTemplate(projectDir, {
455
+ dryRun: false,
456
+ force: options.force,
457
+ noInstall: true,
458
+ }),
459
+ );
435
460
  }
436
461
 
437
462
  if ((hasUpdates || addedPlugins.length > 0) && !options.noInstall) {
438
- await runBunInstall(projectDir);
439
- await runTypesGen(projectDir);
463
+ await timePhase(timings, "install dependencies", () => runBunInstall(projectDir));
464
+ await timePhase(timings, "generate types", () => runTypesGen(projectDir));
440
465
  }
441
466
 
442
- const migratedFiles = await rewriteLegacyUiImports(projectDir);
443
- for (const file of OBSOLETE_FILES) {
444
- const filePath = join(projectDir, file);
445
- if (existsSync(filePath)) {
446
- rmSync(filePath);
447
- migratedFiles.push(file);
467
+ const migratedFiles = await timePhase(timings, "clean obsolete files", async () => {
468
+ const nextMigratedFiles = await rewriteLegacyUiImports(projectDir);
469
+ for (const file of OBSOLETE_FILES) {
470
+ const filePath = join(projectDir, file);
471
+ if (existsSync(filePath)) {
472
+ rmSync(filePath);
473
+ nextMigratedFiles.push(file);
474
+ }
448
475
  }
449
- }
476
+ return nextMigratedFiles;
477
+ });
450
478
 
451
479
  let changelogUrl: string | undefined;
452
480
  const mainPkg = packages.find((p) => p.name === "everything-dev");
@@ -470,6 +498,7 @@ export async function upgradeTemplate(
470
498
  sync: syncResult,
471
499
  migrated: migratedFiles.length > 0 ? migratedFiles : undefined,
472
500
  selectedPlugins: addedPlugins.length > 0 ? addedPlugins : undefined,
501
+ timings,
473
502
  changelogUrl,
474
503
  };
475
504
  }
package/src/cli.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  import { findCommandDescriptor } from "./cli/catalog";
3
3
  import { printHelp } from "./cli/help";
4
4
  import { parseCommandInput } from "./cli/parse";
5
+ import { formatDuration, sumPhaseDurations } from "./cli/timing";
5
6
  import { findConfigPath } from "./config";
6
7
  import bosPlugin from "./plugin";
7
8
  import { createPluginRuntime } from "./sdk";
@@ -50,6 +51,18 @@ function normalizeVersion(v: string): string {
50
51
  return v.replace(/^[\^~>=v]+/, "").trim();
51
52
  }
52
53
 
54
+ function printTimingSummary(timings: Array<{ name: string; durationMs: number }> | undefined) {
55
+ if (!timings || timings.length === 0) return;
56
+
57
+ console.log(` ${colors.dim("Timings:")}`);
58
+ for (const timing of timings) {
59
+ console.log(` ${colors.dim(timing.name.padEnd(22))} ${formatDuration(timing.durationMs)}`);
60
+ }
61
+ console.log(
62
+ ` ${colors.dim("total".padEnd(22))} ${formatDuration(sumPhaseDurations(timings))}`,
63
+ );
64
+ }
65
+
53
66
  async function warnIfOutdated(client: any, command: string): Promise<void> {
54
67
  if (!["dev", "build", "start"].includes(command)) return;
55
68
 
@@ -152,6 +165,7 @@ async function main() {
152
165
  if (result.plugins && result.plugins.length > 0)
153
166
  console.log(` ${colors.dim("Plugins:")} ${result.plugins.join(", ")}`);
154
167
  console.log(` ${colors.dim("Files copied:")} ${result.filesCopied}`);
168
+ printTimingSummary(result.timings);
155
169
  console.log();
156
170
  console.log(colors.dim(" Next steps:"));
157
171
  console.log(colors.dim(` cd ${result.directory}`));
@@ -246,6 +260,7 @@ async function main() {
246
260
  if (result.selectedPlugins && result.selectedPlugins.length > 0) {
247
261
  console.log(` ${colors.dim("Added plugins:")} ${result.selectedPlugins.join(", ")}`);
248
262
  }
263
+ printTimingSummary(result.timings);
249
264
  if (result.sync) {
250
265
  const sync = result.sync;
251
266
  if (sync.updated.length > 0) {
package/src/contract.ts CHANGED
@@ -156,6 +156,11 @@ export const InitOptionsSchema = z.object({
156
156
  noInstall: z.boolean().default(false),
157
157
  });
158
158
 
159
+ export const PhaseTimingSchema = z.object({
160
+ name: z.string(),
161
+ durationMs: z.number(),
162
+ });
163
+
159
164
  export const InitResultSchema = z.object({
160
165
  status: z.enum(["initialized", "error"]),
161
166
  directory: z.string(),
@@ -166,6 +171,7 @@ export const InitResultSchema = z.object({
166
171
  extends: z.string(),
167
172
  plugins: z.array(z.string()).optional(),
168
173
  filesCopied: z.number(),
174
+ timings: z.array(PhaseTimingSchema).optional(),
169
175
  error: z.string().optional(),
170
176
  });
171
177
 
@@ -203,6 +209,7 @@ export const UpgradeResultSchema = z.object({
203
209
  migrated: z.array(z.string()).optional(),
204
210
  availablePlugins: z.array(z.string()).optional(),
205
211
  selectedPlugins: z.array(z.string()).optional(),
212
+ timings: z.array(PhaseTimingSchema).optional(),
206
213
  changelogUrl: z.string().optional(),
207
214
  error: z.string().optional(),
208
215
  });
@@ -307,6 +314,7 @@ export type KeyPublishOptions = z.infer<typeof KeyPublishOptionsSchema>;
307
314
  export type KeyPublishResult = z.infer<typeof KeyPublishResultSchema>;
308
315
  export type InitOptions = z.infer<typeof InitOptionsSchema>;
309
316
  export type InitResult = z.infer<typeof InitResultSchema>;
317
+ export type PhaseTiming = z.infer<typeof PhaseTimingSchema>;
310
318
  export type SyncOptions = z.infer<typeof SyncOptionsSchema>;
311
319
  export type SyncResult = z.infer<typeof SyncResultSchema>;
312
320
  export type UpgradeOptions = z.infer<typeof UpgradeOptionsSchema>;
@@ -1,4 +1,4 @@
1
- import { NodeContext } from "@effect/platform-node";
1
+ import * as NodeContext from "@effect/platform-node/NodeContext";
2
2
  import { Deferred, Effect, Exit } from "effect";
3
3
  import {
4
4
  type DevViewHandle,
package/src/plugin.ts CHANGED
@@ -20,6 +20,7 @@ import {
20
20
  import { promptInitOptions } from "./cli/prompts";
21
21
  import { getStatus } from "./cli/status";
22
22
  import { syncTemplate } from "./cli/sync";
23
+ import { timePhase } from "./cli/timing";
23
24
  import { upgradeTemplate } from "./cli/upgrade";
24
25
  import {
25
26
  buildRuntimePluginsForConfig,
@@ -30,8 +31,12 @@ import {
30
31
  resolveLocalDevelopmentPath,
31
32
  writeResolvedConfig,
32
33
  } from "./config";
33
- import { type BosConfigResult, bosContract, type PluginListResult } from "./contract";
34
- import { devApp, startApp } from "./dev-session";
34
+ import {
35
+ type BosConfigResult,
36
+ bosContract,
37
+ type PhaseTiming,
38
+ type PluginListResult,
39
+ } from "./contract";
35
40
  import {
36
41
  buildRegistryConfigUrl,
37
42
  buildRegistryConfigUrlForNetwork,
@@ -58,6 +63,10 @@ import { run } from "./utils/run";
58
63
  import { saveBosConfig } from "./utils/save-config";
59
64
  import { colors } from "./utils/theme";
60
65
 
66
+ async function loadDevSession() {
67
+ return import("./dev-session");
68
+ }
69
+
61
70
  const buildCommands: Record<string, { cmd: string; args: string[] }> = {
62
71
  host: { cmd: "bun", args: ["run", "build"] },
63
72
  ui: { cmd: "bun", args: ["run", "build"] },
@@ -838,6 +847,7 @@ export default createPlugin({
838
847
  interactive: input.interactive,
839
848
  };
840
849
 
850
+ const { devApp } = await loadDevSession();
841
851
  devApp(orchestrator, services, runtimeConfig);
842
852
 
843
853
  return {
@@ -998,6 +1008,7 @@ export default createPlugin({
998
1008
  noLogs: true,
999
1009
  };
1000
1010
 
1011
+ const { startApp } = await loadDevSession();
1001
1012
  startApp(orchestrator, services, runtimeConfig);
1002
1013
  return {
1003
1014
  status: "running" as const,
@@ -1261,6 +1272,7 @@ export default createPlugin({
1261
1272
 
1262
1273
  init: builder.init.handler(async ({ input }) => {
1263
1274
  try {
1275
+ const timings: PhaseTiming[] = [];
1264
1276
  let extendsAccount = input.extendsAccount;
1265
1277
  let extendsGateway = input.extendsGateway;
1266
1278
  let directory = input.directory;
@@ -1283,7 +1295,9 @@ export default createPlugin({
1283
1295
  let parentPluginKeys: string[] = [];
1284
1296
  let parentConfig: BosConfig | null = null;
1285
1297
  try {
1286
- parentConfig = await fetchParentConfig(extendsAccount, extendsGateway);
1298
+ parentConfig = await timePhase(timings, "parent config", () =>
1299
+ fetchParentConfig(extendsAccount!, extendsGateway!),
1300
+ );
1287
1301
  if (parentConfig?.plugins && typeof parentConfig.plugins === "object") {
1288
1302
  parentPluginKeys = Object.keys(parentConfig.plugins);
1289
1303
  }
@@ -1316,7 +1330,9 @@ export default createPlugin({
1316
1330
 
1317
1331
  if (!parentConfig) {
1318
1332
  try {
1319
- parentConfig = await fetchParentConfig(extendsAccount, extendsGateway);
1333
+ parentConfig = await timePhase(timings, "parent config", () =>
1334
+ fetchParentConfig(extendsAccount!, extendsGateway!),
1335
+ );
1320
1336
  } catch {
1321
1337
  return {
1322
1338
  status: "error" as const,
@@ -1328,6 +1344,7 @@ export default createPlugin({
1328
1344
  extends: `bos://${extendsAccount}/${extendsGateway}`,
1329
1345
  plugins: plugins ?? [],
1330
1346
  filesCopied: 0,
1347
+ timings,
1331
1348
  error: `No config found at bos://${extendsAccount}/${extendsGateway} — are you sure this is the right parent?`,
1332
1349
  };
1333
1350
  }
@@ -1337,11 +1354,13 @@ export default createPlugin({
1337
1354
  sourceDir,
1338
1355
  parentConfig: resolvedParentConfig,
1339
1356
  cleanup,
1340
- } = await resolveSourceDir({
1341
- extendsAccount,
1342
- extendsGateway,
1343
- source: input.source,
1344
- });
1357
+ } = await timePhase(timings, "template source", () =>
1358
+ resolveSourceDir({
1359
+ extendsAccount,
1360
+ extendsGateway,
1361
+ source: input.source,
1362
+ }),
1363
+ );
1345
1364
 
1346
1365
  parentConfig = resolvedParentConfig;
1347
1366
 
@@ -1375,43 +1394,59 @@ export default createPlugin({
1375
1394
  const s = p.spinner();
1376
1395
  s.start("Setting up project");
1377
1396
 
1378
- const filesCopied = await copyFilteredFiles(sourceDir, targetDir, patterns, {
1379
- withHost,
1380
- plugins,
1381
- pluginRoutes,
1382
- });
1397
+ const filesCopied = await timePhase(timings, "copy files", () =>
1398
+ copyFilteredFiles(sourceDir, targetDir, patterns, {
1399
+ withHost,
1400
+ plugins,
1401
+ pluginRoutes,
1402
+ }),
1403
+ );
1383
1404
 
1384
- await personalizeConfig(targetDir, {
1385
- extendsAccount,
1386
- extendsGateway,
1387
- account: account || extendsAccount,
1388
- domain: domain || extendsGateway,
1389
- plugins,
1390
- pluginRoutes,
1391
- workspaceOpts: { sourceDir },
1392
- withHost,
1393
- });
1405
+ await timePhase(timings, "personalize config", () =>
1406
+ personalizeConfig(targetDir, {
1407
+ extendsAccount,
1408
+ extendsGateway,
1409
+ account: account || extendsAccount,
1410
+ domain: domain || extendsGateway,
1411
+ plugins,
1412
+ pluginRoutes,
1413
+ workspaceOpts: { sourceDir },
1414
+ withHost,
1415
+ }),
1416
+ );
1394
1417
 
1395
- await writeInitSnapshot(targetDir, extendsAccount, extendsGateway, sourceDir, patterns, {
1396
- withHost,
1397
- plugins,
1398
- pluginRoutes,
1399
- });
1418
+ await timePhase(timings, "write snapshot", () =>
1419
+ writeInitSnapshot(targetDir, extendsAccount, extendsGateway, sourceDir, patterns, {
1420
+ withHost,
1421
+ plugins,
1422
+ pluginRoutes,
1423
+ }),
1424
+ );
1400
1425
 
1401
- const initConfig = await loadConfig({ cwd: targetDir });
1426
+ const initConfig = await timePhase(timings, "resolve config", () =>
1427
+ loadConfig({ cwd: targetDir }),
1428
+ );
1402
1429
  if (initConfig?.runtime) {
1403
- writeGeneratedInfra(targetDir, initConfig.runtime);
1430
+ await timePhase(timings, "generate env/docker", async () => {
1431
+ writeGeneratedInfra(targetDir, initConfig.runtime);
1432
+ });
1404
1433
  }
1405
- ensureEnvFile(targetDir);
1434
+ await timePhase(timings, "create env file", async () => {
1435
+ ensureEnvFile(targetDir);
1436
+ });
1406
1437
 
1407
1438
  if (!input.noInstall) {
1408
- await runBunInstall(targetDir);
1409
- await runTypesGen(targetDir);
1410
- await generateDatabaseMigrations(targetDir);
1439
+ await timePhase(timings, "install dependencies", () => runBunInstall(targetDir));
1440
+ await timePhase(timings, "generate types", () => runTypesGen(targetDir));
1441
+ await timePhase(timings, "generate migrations", () =>
1442
+ generateDatabaseMigrations(targetDir),
1443
+ );
1411
1444
  }
1412
1445
 
1413
- if (initConfig?.config) {
1414
- await generateCodeArtifacts(targetDir, initConfig.config);
1446
+ if (input.noInstall && initConfig?.config) {
1447
+ await timePhase(timings, "generate code artifacts", () =>
1448
+ generateCodeArtifacts(targetDir, initConfig.config),
1449
+ );
1415
1450
  }
1416
1451
 
1417
1452
  s.stop("Project initialized");
@@ -1426,7 +1461,7 @@ export default createPlugin({
1426
1461
  const dockerSpinner = p.spinner();
1427
1462
  dockerSpinner.start("Starting Docker services");
1428
1463
  try {
1429
- await runDockerComposeUp(targetDir);
1464
+ await timePhase(timings, "docker compose up", () => runDockerComposeUp(targetDir));
1430
1465
  dockerSpinner.stop("Docker services ready");
1431
1466
  } catch (error) {
1432
1467
  dockerSpinner.stop("Docker services not started");
@@ -1447,6 +1482,7 @@ export default createPlugin({
1447
1482
  extends: `bos://${extendsAccount}/${extendsGateway}`,
1448
1483
  plugins,
1449
1484
  filesCopied,
1485
+ timings,
1450
1486
  };
1451
1487
  } finally {
1452
1488
  await cleanup();
@@ -1465,6 +1501,7 @@ export default createPlugin({
1465
1501
  : "",
1466
1502
  plugins: input.plugins ?? [],
1467
1503
  filesCopied: 0,
1504
+ timings: [],
1468
1505
  error: error instanceof Error ? error.message : "Unknown error",
1469
1506
  };
1470
1507
  }