@format.dev/cli 0.1.1 → 0.1.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.
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { a as readConfigFile, i as findConfigPath, o as writeConfigVersion, r as detectIndent, s as CliError } from "./config-Dq7O4e8N.mjs";
3
- import { C as joinNames, D as commandForPlatform, E as truncateForSpinner, O as detectPackageManager, S as installManifest, T as runInstall$2, c as getDocumentsDir, g as validateDocumentName, i as generateRandomName, k as installCommand, l as readExistingDocumentNames, n as maybeSetupProject, r as writeDocumentDependencies, s as createDocument, w as writeDependenciesToManifest } from "./install-BiDrmMgJ.mjs";
3
+ import { C as joinNames, D as commandForPlatform, E as truncateForSpinner, O as detectPackageManager, S as installManifest, T as runInstall$2, c as getDocumentsDir, g as validateDocumentName, i as generateRandomName, k as installCommand, l as readExistingDocumentNames, n as maybeSetupProject, r as writeDocumentDependencies, s as createDocument, w as writeDependenciesToManifest } from "./install-nInHtWQW.mjs";
4
4
  import { a as rewriteFormatDependencies, i as mayHaveBreakingChanges, n as isExactVersion, r as isNewer, t as loadProjectState } from "./project-pX62Di_9.mjs";
5
5
  import { a as DEFAULT_STYLING, f as STYLING_LABELS, h as SUPPORTED_FRAMEWORKS, l as SCHEMA_KINDS, n as DEFAULT_PAGE_SIZE_ID, s as PAGE_SIZES, u as SCHEMA_LABELS, v as isValidDimension, y as methodsForFramework } from "./shared-CM3vyUlL.mjs";
6
6
  import "./draw-random-name-Dpt6YmUk.mjs";
@@ -250,7 +250,7 @@ var cli_spec_default = { commands: [
250
250
 
251
251
  //#endregion
252
252
  //#region src/versioning/js-version.ts
253
- const jsVersion = "0.1.1";
253
+ const jsVersion = "0.1.3";
254
254
 
255
255
  //#endregion
256
256
  //#region src/versioning/registry.ts
@@ -272,11 +272,43 @@ async function fetchLatestVersion() {
272
272
  return data.version;
273
273
  }
274
274
 
275
+ //#endregion
276
+ //#region src/versioning/changelog.ts
277
+ const CHANGELOG_URL = "https://format.dev/changelog";
278
+ const CHANGELOG_INDEX_URL = process.env.FMT_CHANGELOG_INDEX_URL ?? "https://format.dev/changelog.json";
279
+ const FETCH_TIMEOUT_MS = 3e3;
280
+ function changelogEntriesBetween(args) {
281
+ const { entries, fromVersion, toVersion } = args;
282
+ return entries.filter((entry) => isNewer(entry.version, fromVersion) && !isNewer(entry.version, toVersion)).sort((a, b) => isNewer(a.version, b.version) ? 1 : -1);
283
+ }
284
+ async function fetchChangelogIndex() {
285
+ const controller = new AbortController();
286
+ const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
287
+ try {
288
+ const response = await fetch(CHANGELOG_INDEX_URL, { signal: controller.signal });
289
+ if (!response.ok) throw new Error(`Changelog index returned ${response.status}`);
290
+ return (await response.json()).entries;
291
+ } finally {
292
+ clearTimeout(timeout);
293
+ }
294
+ }
295
+ async function changelogLines(args) {
296
+ const { fromVersion, toVersion, fetchEntries = fetchChangelogIndex } = args;
297
+ const entries = await fetchEntries().catch(() => null);
298
+ if (!entries) return [`See what's changed: ${CHANGELOG_URL}`];
299
+ const inRange = changelogEntriesBetween({
300
+ entries,
301
+ fromVersion,
302
+ toVersion
303
+ });
304
+ if (inRange.length === 0) return [];
305
+ return [`What's changed since ${fromVersion}:`, ...inRange.map((entry) => ` ${entry.version} ${entry.url}`)];
306
+ }
307
+
275
308
  //#endregion
276
309
  //#region src/versioning/update-check.ts
277
310
  const CACHE_FILE_NAME = "update-check.json";
278
311
  const CACHE_MAX_AGE_MS = 1440 * 60 * 1e3;
279
- const CHANGELOG_URL = "https://format.dev/changelog";
280
312
  function cacheDir() {
281
313
  const home = os.homedir();
282
314
  if (process.env.XDG_CACHE_HOME) return join(process.env.XDG_CACHE_HOME, "format");
@@ -395,7 +427,8 @@ async function spawnStudioForProject(state, argv) {
395
427
  return spawnStudio("npm", [
396
428
  "exec",
397
429
  "-y",
398
- "--prefer-offline",
430
+ "--fetch-retries=1",
431
+ "--fetch-retry-mintimeout=1000",
399
432
  "--",
400
433
  `${target.packageName}@${state.pinnedVersion}`,
401
434
  ...argv
@@ -599,11 +632,20 @@ function installArgs(packageManager, packages, dev) {
599
632
  switch (packageManager) {
600
633
  case "npm": return [
601
634
  "install",
635
+ "--no-fund",
636
+ "--save-exact",
602
637
  ...dev ? ["--save-dev"] : [],
603
638
  ...packages
604
639
  ];
640
+ case "pnpm": return [
641
+ "add",
642
+ "--save-exact",
643
+ ...saveFlag ? [saveFlag] : [],
644
+ ...packages
645
+ ];
605
646
  default: return [
606
647
  "add",
648
+ "--exact",
607
649
  ...saveFlag ? [saveFlag] : [],
608
650
  ...packages
609
651
  ];
@@ -1360,6 +1402,94 @@ async function newProjectCommand(cwd, providedDirectory, options) {
1360
1402
  }
1361
1403
  }
1362
1404
 
1405
+ //#endregion
1406
+ //#region src/versioning/cli-package.ts
1407
+ const CLI_PACKAGE_NAME$1 = "@format.dev/cli";
1408
+ async function readCliPackageVersion() {
1409
+ let dir = dirname(fileURLToPath(import.meta.url));
1410
+ for (;;) {
1411
+ const candidate = join(dir, "package.json");
1412
+ if (existsSync(candidate)) {
1413
+ const manifest = JSON.parse(await fs.readFile(candidate, "utf8"));
1414
+ if (manifest.name === CLI_PACKAGE_NAME$1) return manifest.version;
1415
+ }
1416
+ const parent = dirname(dir);
1417
+ if (parent === dir) throw new Error(`Could not find the ${CLI_PACKAGE_NAME$1} package.json above ${fileURLToPath(import.meta.url)}`);
1418
+ dir = parent;
1419
+ }
1420
+ }
1421
+
1422
+ //#endregion
1423
+ //#region src/versioning/handoff.ts
1424
+ const HANDOFF_ENV = "FMT_UPDATE_HANDOFF";
1425
+ const CLI_PACKAGE_NAME = "@format.dev/cli";
1426
+ function readHandoffFromVersion() {
1427
+ return process.env[HANDOFF_ENV] ?? null;
1428
+ }
1429
+ function environmentWithoutHandoff() {
1430
+ const { [HANDOFF_ENV]: _handoff, ...environment } = process.env;
1431
+ return environment;
1432
+ }
1433
+ async function handOffUpdate(args) {
1434
+ const { targetVersion, fromVersion, cwd } = args;
1435
+ const commandArgs = [
1436
+ "exec",
1437
+ "--yes",
1438
+ `--package=${CLI_PACKAGE_NAME}@${targetVersion}`,
1439
+ "--",
1440
+ "format",
1441
+ "update",
1442
+ targetVersion
1443
+ ];
1444
+ return new Promise((resolvePromise, rejectPromise) => {
1445
+ const child = spawn("npm", commandArgs, {
1446
+ cwd,
1447
+ stdio: "inherit",
1448
+ shell: process.platform === "win32",
1449
+ env: {
1450
+ ...process.env,
1451
+ [HANDOFF_ENV]: fromVersion ?? "none"
1452
+ }
1453
+ });
1454
+ child.on("error", (error) => {
1455
+ rejectPromise(new CliError(`Failed to run the Format ${targetVersion} CLI: ${error.message}`));
1456
+ });
1457
+ child.on("exit", (code) => {
1458
+ resolvePromise(code ?? 1);
1459
+ });
1460
+ });
1461
+ }
1462
+
1463
+ //#endregion
1464
+ //#region src/versioning/fresh-install.ts
1465
+ const FORMAT_SCOPE = "@format.dev/";
1466
+ const DEPENDENCY_SECTIONS = [
1467
+ "dependencies",
1468
+ "devDependencies",
1469
+ "optionalDependencies"
1470
+ ];
1471
+ function withoutFormatDependencies(manifest) {
1472
+ const copy = { ...manifest };
1473
+ for (const section of DEPENDENCY_SECTIONS) {
1474
+ const entries = manifest[section];
1475
+ if (!entries) continue;
1476
+ copy[section] = Object.fromEntries(Object.entries(entries).filter(([name, version]) => !name.startsWith(FORMAT_SCOPE) || version.startsWith("workspace:")));
1477
+ }
1478
+ return copy;
1479
+ }
1480
+ async function installWithFreshFormatTree(args) {
1481
+ const { packageJsonPath, install } = args;
1482
+ const targetSource = await fs.readFile(packageJsonPath, "utf8");
1483
+ const withoutFormat = withoutFormatDependencies(JSON.parse(targetSource));
1484
+ try {
1485
+ await fs.writeFile(packageJsonPath, `${JSON.stringify(withoutFormat, null, " ")}\n`, "utf8");
1486
+ await install();
1487
+ } finally {
1488
+ await fs.writeFile(packageJsonPath, targetSource, "utf8");
1489
+ }
1490
+ await install();
1491
+ }
1492
+
1363
1493
  //#endregion
1364
1494
  //#region src/cli/commands/update.ts
1365
1495
  async function updateCommand(cwd, target) {
@@ -1368,6 +1498,13 @@ async function updateCommand(cwd, target) {
1368
1498
  target,
1369
1499
  pinnedVersion: state.pinnedVersion
1370
1500
  });
1501
+ const cliVersion = await readCliPackageVersion();
1502
+ const handoffFromVersion = readHandoffFromVersion();
1503
+ if (handoffFromVersion === null && cliVersion !== targetVersion) return handOffUpdate({
1504
+ targetVersion,
1505
+ fromVersion: state.pinnedVersion,
1506
+ cwd: state.projectDir
1507
+ });
1371
1508
  if (targetVersion !== state.pinnedVersion) {
1372
1509
  await writeConfigVersion({
1373
1510
  filepath: state.configFile.filepath,
@@ -1392,13 +1529,27 @@ async function updateCommand(cwd, target) {
1392
1529
  const { command, args } = installCommand(packageManager);
1393
1530
  console.log("");
1394
1531
  console.log(`Installing with ${packageManager}...`);
1395
- await runInstall({
1396
- command,
1397
- args,
1398
- cwd: state.projectDir
1532
+ await installWithFreshFormatTree({
1533
+ packageJsonPath: state.packageJsonPath,
1534
+ install: () => runInstall({
1535
+ command,
1536
+ args,
1537
+ cwd: state.projectDir
1538
+ })
1399
1539
  });
1400
1540
  console.log("");
1401
1541
  console.log(`Done. Your project is on Format ${targetVersion}.`);
1542
+ const fromVersion = handoffFromVersion ?? state.pinnedVersion;
1543
+ if (fromVersion !== null && fromVersion !== "none" && fromVersion !== targetVersion) {
1544
+ const lines = await changelogLines({
1545
+ fromVersion,
1546
+ toVersion: targetVersion
1547
+ });
1548
+ if (lines.length > 0) {
1549
+ console.log("");
1550
+ lines.forEach((line) => console.log(line));
1551
+ }
1552
+ }
1402
1553
  return 0;
1403
1554
  }
1404
1555
  async function resolveTargetVersion(args) {
@@ -1417,7 +1568,8 @@ async function runInstall(args) {
1417
1568
  const child = spawn(command, commandArgs, {
1418
1569
  cwd,
1419
1570
  stdio: "inherit",
1420
- shell: process.platform === "win32"
1571
+ shell: process.platform === "win32",
1572
+ env: environmentWithoutHandoff()
1421
1573
  });
1422
1574
  child.on("error", (error) => {
1423
1575
  rejectPromise(new CliError(`Failed to run ${command} install: ${error.message}`));
@@ -46,7 +46,7 @@ async function detectPackageManager(projectDir) {
46
46
  function installCommand(packageManager) {
47
47
  if (packageManager === "npm") return {
48
48
  command: "npm",
49
- args: ["install"]
49
+ args: ["install", "--no-fund"]
50
50
  };
51
51
  if (packageManager === "pnpm") return {
52
52
  command: "pnpm",
package/dist/scaffold.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { s as CliError } from "./config-Dq7O4e8N.mjs";
2
- import { _ as RESERVED_WORDS, a as DOCUMENTS_DIR_NAME, b as DEFAULT_TEMPLATE, c as getDocumentsDir, d as resolveStyling, f as STYLING_STRATEGIES, g as validateDocumentName, h as suggestAvailableName, i as generateRandomName, l as readExistingDocumentNames, m as RESERVED_DOCUMENT_NAMES, n as maybeSetupProject, o as buildDocumentPlan, p as readProjectDependencies, s as createDocument, t as maybeInstallDependencies, u as writeDocument, v as buildDocumentExportMap, x as EMPTY_STYLESHEET_COMMENT, y as getDocumentExportName } from "./install-BiDrmMgJ.mjs";
2
+ import { _ as RESERVED_WORDS, a as DOCUMENTS_DIR_NAME, b as DEFAULT_TEMPLATE, c as getDocumentsDir, d as resolveStyling, f as STYLING_STRATEGIES, g as validateDocumentName, h as suggestAvailableName, i as generateRandomName, l as readExistingDocumentNames, m as RESERVED_DOCUMENT_NAMES, n as maybeSetupProject, o as buildDocumentPlan, p as readProjectDependencies, s as createDocument, t as maybeInstallDependencies, u as writeDocument, v as buildDocumentExportMap, x as EMPTY_STYLESHEET_COMMENT, y as getDocumentExportName } from "./install-nInHtWQW.mjs";
3
3
  import { y as methodsForFramework } from "./shared-CM3vyUlL.mjs";
4
4
  import { t as drawRandomName } from "./draw-random-name-Dpt6YmUk.mjs";
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@format.dev/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "license": "MIT",
5
5
  "description": "The Format CLI: run Studio, compile documents, and keep Format packages in lockstep",
6
6
  "author": "the format.dev developers",
@@ -72,8 +72,8 @@
72
72
  "verdaccio": "^6.8.0",
73
73
  "vitest": "^4.0.18",
74
74
  "vue": "^3.5.25",
75
- "@format.dev/vue": "0.1.1",
76
- "@format.dev/react": "0.1.1"
75
+ "@format.dev/react": "0.1.3",
76
+ "@format.dev/vue": "0.1.3"
77
77
  },
78
78
  "engines": {
79
79
  "node": ">=22.12.0"