@lerret/cli 0.1.7 → 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/README.md +2 -2
- package/dist-studio/.bundle-stamp +8 -8
- package/dist-studio/assets/{asset-runtime-BkKE6v8L.js → asset-runtime-B5cPbIor.js} +1 -1
- package/dist-studio/assets/cli-project-source-BmwR4FYM.js +1 -0
- package/dist-studio/assets/{dev-harness-DXos2Ufq.js → dev-harness-C-jJxqqM.js} +2 -2
- package/dist-studio/assets/{hosted-project-source-BGPTmqgx.js → hosted-project-source-DYHsf9ks.js} +1 -1
- package/dist-studio/assets/{index-DDZr-wEU.js → index-CXzX4BtL.js} +2 -2
- package/dist-studio/assets/{open-folder-BwK8FWeb.js → open-folder-BBui4dbb.js} +1 -1
- package/dist-studio/assets/{project-studio-Cu9lqG-F.js → project-studio-C2LvtlHD.js} +3 -3
- package/dist-studio/index.html +2 -2
- package/package.json +1 -1
- package/src/dev.js +14 -14
- package/src/export.js +74 -39
- package/src/fs/node-backend.js +3 -3
- package/src/lerret.js +7 -7
- package/src/vite-plugin-lerret-project.js +6 -6
- package/dist-studio/assets/cli-project-source-CcMekGqD.js +0 -1
package/src/export.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
//
|
|
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
|
|
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`
|
|
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
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
import { parseArgs } from 'node:util';
|
|
71
71
|
import { dirname, resolve as resolvePath } from 'node:path';
|
|
72
72
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
73
|
+
import { createRequire } from 'node:module';
|
|
73
74
|
|
|
74
75
|
import { scan, collectArtboards } from '@lerret/core';
|
|
75
76
|
|
|
@@ -90,7 +91,7 @@ import { lerretProjectPlugin } from './vite-plugin-lerret-project.js';
|
|
|
90
91
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
91
92
|
|
|
92
93
|
/**
|
|
93
|
-
* The argv shape `parseArgs` produces for
|
|
94
|
+
* The argv shape `parseArgs` produces for `@lerret/cli export`.
|
|
94
95
|
*
|
|
95
96
|
* @typedef {object} ExportFlags
|
|
96
97
|
* @property {string | undefined} pathArg
|
|
@@ -187,15 +188,15 @@ export const ARTBOARD_SELECTORS = {
|
|
|
187
188
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
188
189
|
|
|
189
190
|
/**
|
|
190
|
-
* Print
|
|
191
|
+
* Print `@lerret/cli export`'s usage banner.
|
|
191
192
|
*
|
|
192
193
|
* @returns {void}
|
|
193
194
|
*/
|
|
194
195
|
function printUsage() {
|
|
195
196
|
const lines = [
|
|
196
|
-
'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.',
|
|
197
198
|
'',
|
|
198
|
-
'Usage: lerret export [path] [options]',
|
|
199
|
+
'Usage: @lerret/cli export [path] [options]',
|
|
199
200
|
'',
|
|
200
201
|
'Arguments:',
|
|
201
202
|
' path Project root, or a page/group folder inside `.lerret/`.',
|
|
@@ -218,7 +219,7 @@ function printUsage() {
|
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
/**
|
|
221
|
-
* Parse
|
|
222
|
+
* Parse `@lerret/cli export`'s argv. A separate function so tests can verify flag
|
|
222
223
|
* handling without booting Vite or Playwright.
|
|
223
224
|
*
|
|
224
225
|
* @param {string[]} argv Argv slice after the `export` subcommand.
|
|
@@ -400,7 +401,7 @@ export async function resolveScope({ pathArg, cwd, fs = createNodeBackend() }) {
|
|
|
400
401
|
|
|
401
402
|
// Canonicalize both ends so the path-arg comparisons below work even when
|
|
402
403
|
// the user supplied a symlinked path (the classic macOS `/tmp` →
|
|
403
|
-
// `/private/tmp` gotcha that
|
|
404
|
+
// `/private/tmp` gotcha that `@lerret/cli dev` also has to handle).
|
|
404
405
|
const projectRoot = toLerretPath(realpathOrSelf(projectResolution.projectRoot));
|
|
405
406
|
const lerretDir = toLerretPath(realpathOrSelf(projectResolution.lerretDir));
|
|
406
407
|
|
|
@@ -813,7 +814,7 @@ function readAssetVariants(asset) {
|
|
|
813
814
|
* 1. Try `playwright-core`'s `chromium.launch({ channel: 'chrome' })`. If
|
|
814
815
|
* the user has Google Chrome / Chromium / Edge installed in a standard
|
|
815
816
|
* location, this succeeds without downloading anything — keeping `npx
|
|
816
|
-
* lerret export` light, per the architecture decision.
|
|
817
|
+
* @lerret/cli export` light, per the architecture decision.
|
|
817
818
|
* 2. If the channel launch fails, try `playwright` (the full package,
|
|
818
819
|
* which ships its bundled browser when installed). Only present when
|
|
819
820
|
* the user opts in by installing the full `playwright` package.
|
|
@@ -895,7 +896,7 @@ export async function launchHeadlessBrowser() {
|
|
|
895
896
|
|
|
896
897
|
/**
|
|
897
898
|
* Boot a Vite dev server programmatically — same plugin / fs.allow shape as
|
|
898
|
-
*
|
|
899
|
+
* `@lerret/cli dev`, but with `server.open = false` and an undefined port (Vite
|
|
899
900
|
* picks a free one). The returned `address` is the URL to navigate to.
|
|
900
901
|
*
|
|
901
902
|
* @param {object} opts
|
|
@@ -935,10 +936,26 @@ export async function bootViteServer({ projectRoot, lerretDir, dataOverride, con
|
|
|
935
936
|
plugins.unshift(reactPlugin());
|
|
936
937
|
}
|
|
937
938
|
|
|
939
|
+
// The user's `.jsx`/`.tsx` assets get transformed by Vite/esbuild into
|
|
940
|
+
// imports of `react/jsx-dev-runtime`. The user's project has no
|
|
941
|
+
// `node_modules`, so those imports must resolve against the CLI's own
|
|
942
|
+
// React. Without these aliases the user's assets fail to load in
|
|
943
|
+
// `dist-studio/` mode and the studio renders empty slots — `@lerret/cli dev`
|
|
944
|
+
// has the same shape; we keep them in lock-step.
|
|
945
|
+
const cliRequire = createRequire(import.meta.url);
|
|
946
|
+
const reactAliases = [
|
|
947
|
+
{ find: 'react/jsx-dev-runtime', replacement: cliRequire.resolve('react/jsx-dev-runtime') },
|
|
948
|
+
{ find: 'react/jsx-runtime', replacement: cliRequire.resolve('react/jsx-runtime') },
|
|
949
|
+
{ find: 'react-dom/client', replacement: cliRequire.resolve('react-dom/client') },
|
|
950
|
+
{ find: /^react-dom$/, replacement: cliRequire.resolve('react-dom') },
|
|
951
|
+
{ find: /^react$/, replacement: cliRequire.resolve('react') },
|
|
952
|
+
];
|
|
953
|
+
|
|
938
954
|
const server = await createServer({
|
|
939
955
|
configFile: false,
|
|
940
956
|
root: studioRoot,
|
|
941
957
|
plugins,
|
|
958
|
+
resolve: { alias: reactAliases },
|
|
942
959
|
server: {
|
|
943
960
|
open: false, // headless — never open a real browser
|
|
944
961
|
fs: {
|
|
@@ -989,13 +1006,16 @@ export async function bootViteServer({ projectRoot, lerretDir, dataOverride, con
|
|
|
989
1006
|
* @returns {Promise<{ ok: boolean, bytesB64?: string, unembeddedFonts?: string[], error?: string }>}
|
|
990
1007
|
*/
|
|
991
1008
|
export async function evaluateCaptureInPage(page, domId, format) {
|
|
992
|
-
// The capture import path inside the studio's served bundle. Vite serves
|
|
993
|
-
// the studio source so we can `import()` the same module the studio uses.
|
|
994
|
-
//
|
|
995
1009
|
// The arrow below executes INSIDE the Chromium page — `document`, `btoa`,
|
|
996
|
-
// and
|
|
1010
|
+
// and `window.__lerret_capture` are browser-side and the lint
|
|
997
1011
|
// (which sees this file as Node-only) cannot tell. The targeted disable
|
|
998
1012
|
// covers only that callback.
|
|
1013
|
+
//
|
|
1014
|
+
// `window.__lerret_capture` is published by the studio's CLI-mode entry
|
|
1015
|
+
// (`cli-project-source.jsx`) — a stable hook that survives production
|
|
1016
|
+
// bundling. The old dynamic `import('/src/export/capture.js')` only worked
|
|
1017
|
+
// when Vite served the studio from source; against the pre-built
|
|
1018
|
+
// `dist-studio/` (hashed chunks) the source path 404s.
|
|
999
1019
|
return await page.evaluate(
|
|
1000
1020
|
/* eslint-disable no-undef */
|
|
1001
1021
|
async ({ domId, format, slotSelector, innerCardSelector }) => {
|
|
@@ -1005,11 +1025,26 @@ export async function evaluateCaptureInPage(page, domId, format) {
|
|
|
1005
1025
|
const card = slot.querySelector(innerCardSelector);
|
|
1006
1026
|
if (!card) return { ok: false, error: `inner card not found inside slot "${domId}"` };
|
|
1007
1027
|
|
|
1008
|
-
//
|
|
1009
|
-
// The studio
|
|
1010
|
-
//
|
|
1011
|
-
|
|
1012
|
-
|
|
1028
|
+
// Wait for the studio's CLI-mode entry to publish `__lerret_capture`.
|
|
1029
|
+
// The studio loads `cli-project-source.jsx` asynchronously from
|
|
1030
|
+
// `main.jsx`, so on a fast-navigating page the global may not be
|
|
1031
|
+
// present yet when this callback first fires. Poll briefly with a
|
|
1032
|
+
// generous ceiling — in practice it appears within the first frame
|
|
1033
|
+
// after the studio root mounts.
|
|
1034
|
+
const deadline = Date.now() + 10000;
|
|
1035
|
+
while (typeof window.__lerret_capture !== 'function') {
|
|
1036
|
+
if (Date.now() > deadline) {
|
|
1037
|
+
return {
|
|
1038
|
+
ok: false,
|
|
1039
|
+
error:
|
|
1040
|
+
'`window.__lerret_capture` was not published by the studio ' +
|
|
1041
|
+
'— the bundled studio may be out of date with this CLI',
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
const { blob, unembeddedFonts } = await window.__lerret_capture(card, { format });
|
|
1013
1048
|
|
|
1014
1049
|
// Transfer the blob as base64 — Playwright `evaluate` serializes
|
|
1015
1050
|
// primitives but cannot pass Blobs across the bridge.
|
|
@@ -1057,7 +1092,7 @@ function formatLocation(segments) {
|
|
|
1057
1092
|
}
|
|
1058
1093
|
|
|
1059
1094
|
/**
|
|
1060
|
-
* Run
|
|
1095
|
+
* Run `@lerret/cli export`. Resolves the scope, boots Vite + Chromium, captures
|
|
1061
1096
|
* each artboard, writes the result to disk, and returns an exit code.
|
|
1062
1097
|
*
|
|
1063
1098
|
* @param {string[]} argv Argv slice after the `export` subcommand.
|
|
@@ -1075,7 +1110,7 @@ function formatLocation(segments) {
|
|
|
1075
1110
|
export async function runExport(argv, deps = {}) {
|
|
1076
1111
|
const { flags, error } = parseExportArgs(argv);
|
|
1077
1112
|
if (error) {
|
|
1078
|
-
process.stderr.write(
|
|
1113
|
+
process.stderr.write(`@lerret/cli export: ${error}\n\n`);
|
|
1079
1114
|
printUsage();
|
|
1080
1115
|
return 1;
|
|
1081
1116
|
}
|
|
@@ -1099,7 +1134,7 @@ export async function runExport(argv, deps = {}) {
|
|
|
1099
1134
|
cwd,
|
|
1100
1135
|
});
|
|
1101
1136
|
if (!overrideResult.ok) {
|
|
1102
|
-
process.stderr.write(
|
|
1137
|
+
process.stderr.write(`@lerret/cli export: ${overrideResult.error}\n`);
|
|
1103
1138
|
return 1;
|
|
1104
1139
|
}
|
|
1105
1140
|
const { dataOverride, configOverride } = overrideResult.overrides;
|
|
@@ -1107,7 +1142,7 @@ export async function runExport(argv, deps = {}) {
|
|
|
1107
1142
|
// 1. Resolve project + scope.
|
|
1108
1143
|
const scope = await resolveScope({ pathArg: flags.pathArg, cwd });
|
|
1109
1144
|
if (!scope.found) {
|
|
1110
|
-
process.stderr.write(
|
|
1145
|
+
process.stderr.write(`@lerret/cli export: ${scope.error}\n`);
|
|
1111
1146
|
return 1;
|
|
1112
1147
|
}
|
|
1113
1148
|
|
|
@@ -1116,14 +1151,14 @@ export async function runExport(argv, deps = {}) {
|
|
|
1116
1151
|
try {
|
|
1117
1152
|
baseArtboards = collectArtboards(scope.model, scope.scopePath);
|
|
1118
1153
|
} catch (err) {
|
|
1119
|
-
process.stderr.write(
|
|
1154
|
+
process.stderr.write(`@lerret/cli export: ${err && err.message ? err.message : String(err)}\n`);
|
|
1120
1155
|
return 1;
|
|
1121
1156
|
}
|
|
1122
1157
|
|
|
1123
1158
|
const expanded = expandArtboardVariants(baseArtboards);
|
|
1124
1159
|
if (expanded.length === 0) {
|
|
1125
1160
|
process.stderr.write(
|
|
1126
|
-
|
|
1161
|
+
`@lerret/cli export: no artboards found in scope (${scope.scopeKind}). Nothing to export.\n`,
|
|
1127
1162
|
);
|
|
1128
1163
|
return 1;
|
|
1129
1164
|
}
|
|
@@ -1143,7 +1178,7 @@ export async function runExport(argv, deps = {}) {
|
|
|
1143
1178
|
outDirAbs.startsWith(scope.lerretDir + '/')
|
|
1144
1179
|
) {
|
|
1145
1180
|
process.stderr.write(
|
|
1146
|
-
|
|
1181
|
+
`@lerret/cli export: refusing to write into the project's \`.lerret/\` directory ` +
|
|
1147
1182
|
`(${scope.lerretDir}). Pick an --out directory outside the project's .lerret/ tree.\n`,
|
|
1148
1183
|
);
|
|
1149
1184
|
return 1;
|
|
@@ -1154,7 +1189,7 @@ export async function runExport(argv, deps = {}) {
|
|
|
1154
1189
|
await ensureDirFn(outDirAbs);
|
|
1155
1190
|
} catch (err) {
|
|
1156
1191
|
process.stderr.write(
|
|
1157
|
-
|
|
1192
|
+
`@lerret/cli export: could not create output directory ${outDirAbs}: ` +
|
|
1158
1193
|
`${err && err.message ? err.message : String(err)}\n`,
|
|
1159
1194
|
);
|
|
1160
1195
|
return 1;
|
|
@@ -1171,10 +1206,10 @@ export async function runExport(argv, deps = {}) {
|
|
|
1171
1206
|
? ' [--config override active]'
|
|
1172
1207
|
: '';
|
|
1173
1208
|
process.stdout.write(
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
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`,
|
|
1178
1213
|
);
|
|
1179
1214
|
|
|
1180
1215
|
const bootServer = deps.bootServer || bootViteServer;
|
|
@@ -1200,7 +1235,7 @@ export async function runExport(argv, deps = {}) {
|
|
|
1200
1235
|
url = booted.url;
|
|
1201
1236
|
} catch (err) {
|
|
1202
1237
|
process.stderr.write(
|
|
1203
|
-
|
|
1238
|
+
`@lerret/cli export: Vite dev server failed to start: ` +
|
|
1204
1239
|
`${err && err.message ? err.message : String(err)}\n`,
|
|
1205
1240
|
);
|
|
1206
1241
|
return 1;
|
|
@@ -1209,10 +1244,10 @@ export async function runExport(argv, deps = {}) {
|
|
|
1209
1244
|
try {
|
|
1210
1245
|
const launched = await launchBrowser();
|
|
1211
1246
|
browser = launched.browser;
|
|
1212
|
-
process.stdout.write(
|
|
1247
|
+
process.stdout.write(`@lerret/cli export: ${launched.launchedVia}\n`);
|
|
1213
1248
|
} catch (err) {
|
|
1214
1249
|
process.stderr.write(
|
|
1215
|
-
|
|
1250
|
+
`@lerret/cli export: ${err && err.message ? err.message : String(err)}\n`,
|
|
1216
1251
|
);
|
|
1217
1252
|
return 1;
|
|
1218
1253
|
}
|
|
@@ -1235,7 +1270,7 @@ export async function runExport(argv, deps = {}) {
|
|
|
1235
1270
|
await page.waitForSelector(firstSelector, { state: 'attached', timeout: 30000 });
|
|
1236
1271
|
} catch (err) {
|
|
1237
1272
|
process.stderr.write(
|
|
1238
|
-
|
|
1273
|
+
`@lerret/cli export: studio did not render any artboards within 30s ` +
|
|
1239
1274
|
`(${err && err.message ? err.message : String(err)}). The project may be empty or failed to load.\n`,
|
|
1240
1275
|
);
|
|
1241
1276
|
return 1;
|
|
@@ -1324,16 +1359,16 @@ export async function runExport(argv, deps = {}) {
|
|
|
1324
1359
|
// 7. Summary.
|
|
1325
1360
|
const summaryLines = [
|
|
1326
1361
|
'',
|
|
1327
|
-
|
|
1362
|
+
`@lerret/cli export: wrote ${writtenCount} of ${expanded.length} image${expanded.length === 1 ? '' : 's'} to ${outDirAbs}`,
|
|
1328
1363
|
];
|
|
1329
1364
|
if (failures.length > 0) {
|
|
1330
1365
|
summaryLines.push(
|
|
1331
|
-
|
|
1366
|
+
`@lerret/cli export: ${failures.length} artboard${failures.length === 1 ? '' : 's'} failed (see messages above)`,
|
|
1332
1367
|
);
|
|
1333
1368
|
}
|
|
1334
1369
|
if (allUnembeddedFonts.size > 0) {
|
|
1335
1370
|
summaryLines.push(
|
|
1336
|
-
|
|
1371
|
+
`@lerret/cli export: fonts not embedded: ${[...allUnembeddedFonts].sort().join(', ')}`,
|
|
1337
1372
|
);
|
|
1338
1373
|
}
|
|
1339
1374
|
process.stdout.write(summaryLines.join('\n') + '\n');
|
package/src/fs/node-backend.js
CHANGED
|
@@ -325,7 +325,7 @@ export { NODE_CAPABILITIES };
|
|
|
325
325
|
// realpath helper — CLI-internal, NOT part of the FilesystemAccess contract
|
|
326
326
|
// ---------------------------------------------------------------------------
|
|
327
327
|
//
|
|
328
|
-
//
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
2
|
+
// `.lerret/` project to the studio in `@lerret/cli dev` mode.
|
|
3
3
|
//
|
|
4
4
|
// ── Why a Vite plugin ──────────────────────────────────────────────────────
|
|
5
|
-
//
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
*
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{i as e,n as t,s as n}from"./index-DDZr-wEU.js";import{n as r,r as i,t as a}from"./project-studio-Cu9lqG-F.js";import{t as o}from"./open-folder-BwK8FWeb.js";import{assetBaseUrl as s,cascadeEntries as c,project as l}from"virtual:lerret-project";var u=n(e(),1),d=t();function f(){let e=l,t=s,[n,f]=u.useState(e),[p,m]=u.useState(c||[]),h=u.useMemo(()=>e?i(e,{assetBaseUrl:t}):null,[e,t]);return u.useEffect(()=>{if(h)return()=>h.dispose()},[h]),u.useEffect(()=>{},[h]),n?(0,d.jsx)(r,{cascadeEntries:p,children:(0,d.jsx)(a,{project:n,runtime:h,assetBaseUrl:t})}):(0,d.jsx)(o,{cliMode:!0})}export{f as CliProjectSource,f as default};
|