@lerret/cli 0.1.8 → 0.1.9

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/src/export.js CHANGED
@@ -1,8 +1,8 @@
1
- // `lerret export` — headless capture of a project's artboards to image files
1
+ // `@lerret/cli export` — headless capture of a project's artboards to image files
2
2
  // (FR37, FR38).
3
3
  //
4
4
  // Renders every artboard in scope through the EXACT same `captureArtboard`
5
- // path the studio uses, so a `lerret export` run produces a
5
+ // path the studio uses, so a `@lerret/cli export` run produces a
6
6
  // pixel-faithful match to what the same project produces from a click in the
7
7
  // in-studio export buttons. The mechanism is:
8
8
  //
@@ -15,7 +15,7 @@
15
15
  // backend), then call `collectArtboards(model, scope)` to
16
16
  // pick which artboards to capture.
17
17
  // 3. Boot a Vite dev server programmatically against the studio source plus
18
- // the same `vite-plugin-lerret-project` `lerret dev` uses — exactly the
18
+ // the same `vite-plugin-lerret-project` `@lerret/cli dev` uses — exactly the
19
19
  // runtime that serves the studio so the project is mounted there.
20
20
  // 4. Launch a headless Chromium through Playwright. Prefer the system
21
21
  // `chrome`/`msedge` channel so `npx`-style invocations stay light; fall
@@ -91,7 +91,7 @@ import { lerretProjectPlugin } from './vite-plugin-lerret-project.js';
91
91
  // ─────────────────────────────────────────────────────────────────────────────
92
92
 
93
93
  /**
94
- * The argv shape `parseArgs` produces for `lerret export`.
94
+ * The argv shape `parseArgs` produces for `@lerret/cli export`.
95
95
  *
96
96
  * @typedef {object} ExportFlags
97
97
  * @property {string | undefined} pathArg
@@ -188,15 +188,15 @@ export const ARTBOARD_SELECTORS = {
188
188
  // ─────────────────────────────────────────────────────────────────────────────
189
189
 
190
190
  /**
191
- * Print `lerret export`'s usage banner.
191
+ * Print `@lerret/cli export`'s usage banner.
192
192
  *
193
193
  * @returns {void}
194
194
  */
195
195
  function printUsage() {
196
196
  const lines = [
197
- 'lerret export — render a project (or page/group) headlessly to image files.',
197
+ '@lerret/cli export — render a project (or page/group) headlessly to image files.',
198
198
  '',
199
- 'Usage: lerret export [path] [options]',
199
+ 'Usage: @lerret/cli export [path] [options]',
200
200
  '',
201
201
  'Arguments:',
202
202
  ' path Project root, or a page/group folder inside `.lerret/`.',
@@ -219,7 +219,7 @@ function printUsage() {
219
219
  }
220
220
 
221
221
  /**
222
- * Parse `lerret export`'s argv. A separate function so tests can verify flag
222
+ * Parse `@lerret/cli export`'s argv. A separate function so tests can verify flag
223
223
  * handling without booting Vite or Playwright.
224
224
  *
225
225
  * @param {string[]} argv Argv slice after the `export` subcommand.
@@ -401,7 +401,7 @@ export async function resolveScope({ pathArg, cwd, fs = createNodeBackend() }) {
401
401
 
402
402
  // Canonicalize both ends so the path-arg comparisons below work even when
403
403
  // the user supplied a symlinked path (the classic macOS `/tmp` →
404
- // `/private/tmp` gotcha that `lerret dev` also has to handle).
404
+ // `/private/tmp` gotcha that `@lerret/cli dev` also has to handle).
405
405
  const projectRoot = toLerretPath(realpathOrSelf(projectResolution.projectRoot));
406
406
  const lerretDir = toLerretPath(realpathOrSelf(projectResolution.lerretDir));
407
407
 
@@ -814,7 +814,7 @@ function readAssetVariants(asset) {
814
814
  * 1. Try `playwright-core`'s `chromium.launch({ channel: 'chrome' })`. If
815
815
  * the user has Google Chrome / Chromium / Edge installed in a standard
816
816
  * location, this succeeds without downloading anything — keeping `npx
817
- * lerret export` light, per the architecture decision.
817
+ * @lerret/cli export` light, per the architecture decision.
818
818
  * 2. If the channel launch fails, try `playwright` (the full package,
819
819
  * which ships its bundled browser when installed). Only present when
820
820
  * the user opts in by installing the full `playwright` package.
@@ -896,7 +896,7 @@ export async function launchHeadlessBrowser() {
896
896
 
897
897
  /**
898
898
  * Boot a Vite dev server programmatically — same plugin / fs.allow shape as
899
- * `lerret dev`, but with `server.open = false` and an undefined port (Vite
899
+ * `@lerret/cli dev`, but with `server.open = false` and an undefined port (Vite
900
900
  * picks a free one). The returned `address` is the URL to navigate to.
901
901
  *
902
902
  * @param {object} opts
@@ -940,7 +940,7 @@ export async function bootViteServer({ projectRoot, lerretDir, dataOverride, con
940
940
  // imports of `react/jsx-dev-runtime`. The user's project has no
941
941
  // `node_modules`, so those imports must resolve against the CLI's own
942
942
  // React. Without these aliases the user's assets fail to load in
943
- // `dist-studio/` mode and the studio renders empty slots — `lerret dev`
943
+ // `dist-studio/` mode and the studio renders empty slots — `@lerret/cli dev`
944
944
  // has the same shape; we keep them in lock-step.
945
945
  const cliRequire = createRequire(import.meta.url);
946
946
  const reactAliases = [
@@ -1092,7 +1092,7 @@ function formatLocation(segments) {
1092
1092
  }
1093
1093
 
1094
1094
  /**
1095
- * Run `lerret export`. Resolves the scope, boots Vite + Chromium, captures
1095
+ * Run `@lerret/cli export`. Resolves the scope, boots Vite + Chromium, captures
1096
1096
  * each artboard, writes the result to disk, and returns an exit code.
1097
1097
  *
1098
1098
  * @param {string[]} argv Argv slice after the `export` subcommand.
@@ -1110,7 +1110,7 @@ function formatLocation(segments) {
1110
1110
  export async function runExport(argv, deps = {}) {
1111
1111
  const { flags, error } = parseExportArgs(argv);
1112
1112
  if (error) {
1113
- process.stderr.write(`lerret export: ${error}\n\n`);
1113
+ process.stderr.write(`@lerret/cli export: ${error}\n\n`);
1114
1114
  printUsage();
1115
1115
  return 1;
1116
1116
  }
@@ -1134,7 +1134,7 @@ export async function runExport(argv, deps = {}) {
1134
1134
  cwd,
1135
1135
  });
1136
1136
  if (!overrideResult.ok) {
1137
- process.stderr.write(`lerret export: ${overrideResult.error}\n`);
1137
+ process.stderr.write(`@lerret/cli export: ${overrideResult.error}\n`);
1138
1138
  return 1;
1139
1139
  }
1140
1140
  const { dataOverride, configOverride } = overrideResult.overrides;
@@ -1142,7 +1142,7 @@ export async function runExport(argv, deps = {}) {
1142
1142
  // 1. Resolve project + scope.
1143
1143
  const scope = await resolveScope({ pathArg: flags.pathArg, cwd });
1144
1144
  if (!scope.found) {
1145
- process.stderr.write(`lerret export: ${scope.error}\n`);
1145
+ process.stderr.write(`@lerret/cli export: ${scope.error}\n`);
1146
1146
  return 1;
1147
1147
  }
1148
1148
 
@@ -1151,14 +1151,14 @@ export async function runExport(argv, deps = {}) {
1151
1151
  try {
1152
1152
  baseArtboards = collectArtboards(scope.model, scope.scopePath);
1153
1153
  } catch (err) {
1154
- process.stderr.write(`lerret export: ${err && err.message ? err.message : String(err)}\n`);
1154
+ process.stderr.write(`@lerret/cli export: ${err && err.message ? err.message : String(err)}\n`);
1155
1155
  return 1;
1156
1156
  }
1157
1157
 
1158
1158
  const expanded = expandArtboardVariants(baseArtboards);
1159
1159
  if (expanded.length === 0) {
1160
1160
  process.stderr.write(
1161
- `lerret export: no artboards found in scope (${scope.scopeKind}). Nothing to export.\n`,
1161
+ `@lerret/cli export: no artboards found in scope (${scope.scopeKind}). Nothing to export.\n`,
1162
1162
  );
1163
1163
  return 1;
1164
1164
  }
@@ -1178,7 +1178,7 @@ export async function runExport(argv, deps = {}) {
1178
1178
  outDirAbs.startsWith(scope.lerretDir + '/')
1179
1179
  ) {
1180
1180
  process.stderr.write(
1181
- `lerret export: refusing to write into the project's \`.lerret/\` directory ` +
1181
+ `@lerret/cli export: refusing to write into the project's \`.lerret/\` directory ` +
1182
1182
  `(${scope.lerretDir}). Pick an --out directory outside the project's .lerret/ tree.\n`,
1183
1183
  );
1184
1184
  return 1;
@@ -1189,7 +1189,7 @@ export async function runExport(argv, deps = {}) {
1189
1189
  await ensureDirFn(outDirAbs);
1190
1190
  } catch (err) {
1191
1191
  process.stderr.write(
1192
- `lerret export: could not create output directory ${outDirAbs}: ` +
1192
+ `@lerret/cli export: could not create output directory ${outDirAbs}: ` +
1193
1193
  `${err && err.message ? err.message : String(err)}\n`,
1194
1194
  );
1195
1195
  return 1;
@@ -1206,10 +1206,10 @@ export async function runExport(argv, deps = {}) {
1206
1206
  ? ' [--config override active]'
1207
1207
  : '';
1208
1208
  process.stdout.write(
1209
- `lerret export: project ${scope.projectRoot}\n` +
1210
- `lerret export: scope ${scope.scopeKind}${scope.scopePath ? ` (${scope.scopePath})` : ''}\n` +
1211
- `lerret export: ${expanded.length} artboard${expanded.length === 1 ? '' : 's'} to capture (${flags.format})${overrideNote}\n` +
1212
- `lerret export: writing to ${outDirAbs}${flags.flat ? ' (flat layout)' : ''}\n`,
1209
+ `@lerret/cli export: project ${scope.projectRoot}\n` +
1210
+ `@lerret/cli export: scope ${scope.scopeKind}${scope.scopePath ? ` (${scope.scopePath})` : ''}\n` +
1211
+ `@lerret/cli export: ${expanded.length} artboard${expanded.length === 1 ? '' : 's'} to capture (${flags.format})${overrideNote}\n` +
1212
+ `@lerret/cli export: writing to ${outDirAbs}${flags.flat ? ' (flat layout)' : ''}\n`,
1213
1213
  );
1214
1214
 
1215
1215
  const bootServer = deps.bootServer || bootViteServer;
@@ -1235,7 +1235,7 @@ export async function runExport(argv, deps = {}) {
1235
1235
  url = booted.url;
1236
1236
  } catch (err) {
1237
1237
  process.stderr.write(
1238
- `lerret export: Vite dev server failed to start: ` +
1238
+ `@lerret/cli export: Vite dev server failed to start: ` +
1239
1239
  `${err && err.message ? err.message : String(err)}\n`,
1240
1240
  );
1241
1241
  return 1;
@@ -1244,10 +1244,10 @@ export async function runExport(argv, deps = {}) {
1244
1244
  try {
1245
1245
  const launched = await launchBrowser();
1246
1246
  browser = launched.browser;
1247
- process.stdout.write(`lerret export: ${launched.launchedVia}\n`);
1247
+ process.stdout.write(`@lerret/cli export: ${launched.launchedVia}\n`);
1248
1248
  } catch (err) {
1249
1249
  process.stderr.write(
1250
- `lerret export: ${err && err.message ? err.message : String(err)}\n`,
1250
+ `@lerret/cli export: ${err && err.message ? err.message : String(err)}\n`,
1251
1251
  );
1252
1252
  return 1;
1253
1253
  }
@@ -1270,7 +1270,7 @@ export async function runExport(argv, deps = {}) {
1270
1270
  await page.waitForSelector(firstSelector, { state: 'attached', timeout: 30000 });
1271
1271
  } catch (err) {
1272
1272
  process.stderr.write(
1273
- `lerret export: studio did not render any artboards within 30s ` +
1273
+ `@lerret/cli export: studio did not render any artboards within 30s ` +
1274
1274
  `(${err && err.message ? err.message : String(err)}). The project may be empty or failed to load.\n`,
1275
1275
  );
1276
1276
  return 1;
@@ -1359,16 +1359,16 @@ export async function runExport(argv, deps = {}) {
1359
1359
  // 7. Summary.
1360
1360
  const summaryLines = [
1361
1361
  '',
1362
- `lerret export: wrote ${writtenCount} of ${expanded.length} image${expanded.length === 1 ? '' : 's'} to ${outDirAbs}`,
1362
+ `@lerret/cli export: wrote ${writtenCount} of ${expanded.length} image${expanded.length === 1 ? '' : 's'} to ${outDirAbs}`,
1363
1363
  ];
1364
1364
  if (failures.length > 0) {
1365
1365
  summaryLines.push(
1366
- `lerret export: ${failures.length} artboard${failures.length === 1 ? '' : 's'} failed (see messages above)`,
1366
+ `@lerret/cli export: ${failures.length} artboard${failures.length === 1 ? '' : 's'} failed (see messages above)`,
1367
1367
  );
1368
1368
  }
1369
1369
  if (allUnembeddedFonts.size > 0) {
1370
1370
  summaryLines.push(
1371
- `lerret export: fonts not embedded: ${[...allUnembeddedFonts].sort().join(', ')}`,
1371
+ `@lerret/cli export: fonts not embedded: ${[...allUnembeddedFonts].sort().join(', ')}`,
1372
1372
  );
1373
1373
  }
1374
1374
  process.stdout.write(summaryLines.join('\n') + '\n');
@@ -325,7 +325,7 @@ export { NODE_CAPABILITIES };
325
325
  // realpath helper — CLI-internal, NOT part of the FilesystemAccess contract
326
326
  // ---------------------------------------------------------------------------
327
327
  //
328
- // `lerret dev` configures Vite's `server.fs.allow`, which Vite enforces by
328
+ // `@lerret/cli dev` configures Vite's `server.fs.allow`, which Vite enforces by
329
329
  // comparing against the *real* (symlink-resolved) path of each request. On
330
330
  // macOS `/tmp` is a symlink to `/private/tmp`, so an `--folder /tmp/foo`
331
331
  // argument must be resolved to `/private/tmp/foo` before being added to
@@ -378,7 +378,7 @@ export function pathExists(path) {
378
378
  /**
379
379
  * Recursively create a directory (no-op if it already exists). Used by
380
380
  * subsystems that need to materialize an output tree on disk — the bulk
381
- * `lerret export` writer lands captured images under a user-
381
+ * `@lerret/cli export` writer lands captured images under a user-
382
382
  * specified `--out` directory and needs to mkdir intermediate folders for the
383
383
  * structured layout. Kept in this file so the `fs` ban for the rest of the
384
384
  * codebase is preserved (this is the sanctioned escape).
@@ -393,7 +393,7 @@ export async function ensureDir(lerretPath) {
393
393
 
394
394
  /**
395
395
  * Canonicalize the deepest existing prefix of a path, then re-attach the
396
- * still-virtual trailing components. Used by `lerret export` to compare a
396
+ * still-virtual trailing components. Used by `@lerret/cli export` to compare a
397
397
  * user-supplied `--out` directory against the project's `.lerret/` path even
398
398
  * when `--out` does not yet exist on disk.
399
399
  *
package/src/lerret.js CHANGED
@@ -5,8 +5,8 @@
5
5
  // node's built-in `util.parseArgs` — the architecture's explicit choice, no
6
6
  // heavy CLI framework. Recognized subcommands:
7
7
  //
8
- // lerret dev [--port <n>] [--folder <path>] [--open | --no-open]
9
- // lerret export [path] [--format png|jpg] [--out <dir>] [--flat]
8
+ // @lerret/cli dev [--port <n>] [--folder <path>] [--open | --no-open]
9
+ // @lerret/cli export [path] [--format png|jpg] [--out <dir>] [--flat]
10
10
  //
11
11
  // Adding a new subcommand is the act of importing one more module and adding
12
12
  // an entry to the `SUBCOMMANDS` table below — the usage banner is derived
@@ -53,16 +53,16 @@ const SUBCOMMANDS = {
53
53
  */
54
54
  function printUsage() {
55
55
  const lines = [
56
- 'lerret — the design-canvas CLI',
56
+ '@lerret/cli — the design-canvas CLI',
57
57
  '',
58
- 'Usage: lerret <command> [options]',
58
+ 'Usage: @lerret/cli <command> [options]',
59
59
  '',
60
60
  'Commands:',
61
61
  ...Object.entries(SUBCOMMANDS).map(
62
62
  ([name, { describe }]) => ` ${name.padEnd(8)} ${describe}`,
63
63
  ),
64
64
  '',
65
- 'Run `lerret <command> --help` for command-specific options.',
65
+ 'Run `@lerret/cli <command> --help` for command-specific options.',
66
66
  ];
67
67
  process.stdout.write(lines.join('\n') + '\n');
68
68
  }
@@ -91,7 +91,7 @@ export async function main(argv = process.argv.slice(2)) {
91
91
  if (!handler) {
92
92
  // An unknown subcommand is a usage error — print the banner so the user
93
93
  // can see what is valid, then exit non-zero.
94
- process.stderr.write(`lerret: unknown command "${command}"\n\n`);
94
+ process.stderr.write(`@lerret/cli: unknown command "${command}"\n\n`);
95
95
  printUsage();
96
96
  return 1;
97
97
  }
@@ -102,7 +102,7 @@ export async function main(argv = process.argv.slice(2)) {
102
102
  } catch (err) {
103
103
  // A genuine runtime failure inside a subcommand — surface a short error and
104
104
  // exit non-zero. The subcommand owns its own error UX otherwise.
105
- process.stderr.write(`lerret ${command}: ${err && err.message ? err.message : String(err)}\n`);
105
+ process.stderr.write(`@lerret/cli ${command}: ${err && err.message ? err.message : String(err)}\n`);
106
106
  return 1;
107
107
  }
108
108
  }
@@ -1,8 +1,8 @@
1
1
  // vite-plugin-lerret-project.js — the Vite plugin that exposes the user's
2
- // `.lerret/` project to the studio in `lerret dev` mode.
2
+ // `.lerret/` project to the studio in `@lerret/cli dev` mode.
3
3
  //
4
4
  // ── Why a Vite plugin ──────────────────────────────────────────────────────
5
- // `lerret dev` boots a Node-side Vite dev server pointed at the studio source
5
+ // `@lerret/cli dev` boots a Node-side Vite dev server pointed at the studio source
6
6
  // (`packages/studio/`). The studio is a normal Vite-served SPA. To swap from
7
7
  // the studio's standalone fixture project to a real user folder we need four
8
8
  // things, and a Vite plugin owns all of them in one place:
@@ -71,7 +71,7 @@ import { startWatcher } from './watcher.js';
71
71
 
72
72
  // ── Cascade-override helpers ─────────────────────────────────────────────────
73
73
  //
74
- // When `--config` is supplied to `lerret export`, its value is deep-merged
74
+ // When `--config` is supplied to `@lerret/cli export`, its value is deep-merged
75
75
  // into every entry of the cascade (the `cascadeEntries` the plugin exposes
76
76
  // via the virtual module). We replicate the same deep-merge semantics that
77
77
  // `computeCascadedConfig`'s internal `deepMerge` uses:
@@ -314,12 +314,12 @@ export function checkWritePath(requestPath, lerretDir) {
314
314
  }
315
315
 
316
316
  /**
317
- * Create the `lerret dev` / `lerret export` Vite plugin.
317
+ * Create the `@lerret/cli dev` / `@lerret/cli export` Vite plugin.
318
318
  *
319
319
  * @param {object} opts
320
320
  * @param {string | null} opts.projectRoot
321
321
  * The user's project root — the folder that directly contains `.lerret/`,
322
- * or `null` if `lerret dev` was invoked outside any project (no-folder
322
+ * or `null` if `@lerret/cli dev` was invoked outside any project (no-folder
323
323
  * fallback).
324
324
  * @param {string | null} opts.lerretDir
325
325
  * The user's `.lerret/` directory path, or `null` matching `projectRoot`.
@@ -433,7 +433,7 @@ export function lerretProjectPlugin({ projectRoot, lerretDir, dataOverride, conf
433
433
  /**
434
434
  * Inject a tiny inline script into the served `index.html` so the
435
435
  * studio's `main.jsx` can synchronously detect that it is running
436
- * under `lerret dev`. Without this signal the studio would have to
436
+ * under `@lerret/cli dev`. Without this signal the studio would have to
437
437
  * try a dynamic import of `virtual:lerret-project` — which the
438
438
  * browser refuses with a CORS error (the bare specifier isn't a URL).
439
439
  *