@featherk/icons 0.15.8 → 0.16.1

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 (34) hide show
  1. package/README.md +25 -13
  2. package/dist/docs-manifest.d.ts +1 -0
  3. package/dist/docs-manifest.js +7 -5
  4. package/dist/fontawesome/build.cjs +1 -2
  5. package/dist/fontawesome/build.d.ts +1 -1
  6. package/dist/fontawesome/build.mjs +2 -3
  7. package/dist/fontawesome/catalog.cjs +0 -13
  8. package/dist/fontawesome/catalog.d.ts +0 -8
  9. package/dist/fontawesome/catalog.mjs +0 -13
  10. package/dist/fontawesome/chunks/{generate-BBurrhLv.cjs → generate-B_FxftR7.cjs} +12 -1
  11. package/dist/fontawesome/chunks/{generate-Zq9q2YZD.mjs → generate-DF9R65sV.mjs} +13 -2
  12. package/dist/fontawesome/chunks/manifest-CF473fsM.mjs +61 -0
  13. package/dist/fontawesome/chunks/manifest-DEhGKvmi.cjs +60 -0
  14. package/dist/fontawesome/cli.cjs +23 -26
  15. package/dist/fontawesome/cli.mjs +23 -26
  16. package/dist/fontawesome/generate.d.ts +7 -0
  17. package/dist/fontawesome/manifest.d.ts +35 -0
  18. package/dist/fontawesome/setup.cjs +147 -179
  19. package/dist/fontawesome/setup.d.ts +2 -2
  20. package/dist/fontawesome/setup.mjs +149 -181
  21. package/dist/fontawesome/vite.cjs +64 -28
  22. package/dist/fontawesome/vite.d.ts +25 -5
  23. package/dist/fontawesome/vite.mjs +65 -29
  24. package/docs/ADDING-ICONS.md +4 -3
  25. package/docs/COMING-SOON.md +24 -14
  26. package/docs/ICONS.md +1 -1
  27. package/docs/fontawesome/CreateFontAwesomeManifest.md +12 -12
  28. package/docs/fontawesome/FontAwesome.md +47 -48
  29. package/docs/fontawesome/FontAwesomeCLI.md +14 -19
  30. package/docs/fontawesome/FontAwesomeDeveloperSetup.md +134 -0
  31. package/docs/fontawesome/LICENSING.md +61 -82
  32. package/package.json +1 -1
  33. package/dist/fontawesome/chunks/manifest-BB3q10t1.mjs +0 -20
  34. package/dist/fontawesome/chunks/manifest-C15Xa22L.cjs +0 -19
@@ -6,7 +6,7 @@ const node_path = require("node:path");
6
6
  const node_readline = require("node:readline");
7
7
  const node_util = require("node:util");
8
8
  const fontawesome_catalog = require("./catalog.cjs");
9
- const manifest = require("./chunks/manifest-C15Xa22L.cjs");
9
+ const manifest = require("./chunks/manifest-DEhGKvmi.cjs");
10
10
  const tokenVariable = "FONTAWESOME_PACKAGE_TOKEN";
11
11
  const tokenPlaceholder = `\${${tokenVariable}}`;
12
12
  const registry = "https://npm.fontawesome.com/";
@@ -25,30 +25,29 @@ const workspaceVariables = [
25
25
  "NPM_CONFIG_WORKSPACES"
26
26
  ];
27
27
  const usage = `Usage:
28
- featherk-fontawesome-setup (--manifest <icons.json> | --keys <a,b>) [--free-only]
29
- featherk-fontawesome-setup --source-root <dir> [--refresh-lock]
30
- featherk-fontawesome-setup --source-root <dir> --init (--manifest <icons.json> | --keys <a,b>) [--force]
28
+ featherk-fontawesome-setup --manifest <icons.json> [--free-only]
29
+ featherk-fontawesome-setup
31
30
 
32
- Default (Free + Pro): run once from the application root on a developer
33
- machine. Adds the @fortawesome registry lines to .npmrc (token placeholder
34
- only) and installs exact pins for all selected keys as devDependencies.
35
- Commit .npmrc, package.json, and package-lock.json. Later installs, including
36
- CI, give ${tokenVariable} only to "npm ci --ignore-scripts", then run any
37
- needed install scripts (npm rebuild for dependencies, plus the app's own) and
38
- builds without it. Do not export the token persistently.
31
+ Run from the application root. The manifest contains
32
+ { "free": [keys], "pro": [keys] }, the same file the Vite plugin reads.
39
33
 
40
- --free-only: Free keys only from public npm. No .npmrc changes, no token.
34
+ --manifest (default): installs exact Free pins into the app's devDependencies
35
+ from public npm, and writes exact Pro pins into an isolated private source
36
+ project, ${manifest.fontAwesomeProSourcesDir}/, then installs it with the token. The
37
+ app's own install never needs the token. Rerun after changing the manifest.
38
+ Commit package.json, package-lock.json, and ${manifest.fontAwesomeProSourcesDir}/
39
+ (its node_modules is ignored).
41
40
 
42
- --source-root <dir>: install licensed packages into an isolated private
43
- source project instead (npm ci when its lockfile exists). --init scaffolds
44
- that project; with --force, a lockfile for different dependencies is removed
45
- so the next install regenerates it. --refresh-lock runs npm install to update
46
- the lockfile after editing package.json by hand. In CI, --init and
47
- --refresh-lock are refused and a lockfile is required.
41
+ No arguments: installs ${manifest.fontAwesomeProSourcesDir}/ from its committed
42
+ lockfile with the token, for CI and fresh clones. Run it after the app's own
43
+ "npm ci".
44
+
45
+ --free-only: Free keys only from public npm. No token, no source project.
48
46
 
49
47
  The token comes from ${tokenVariable} or a hidden prompt in an interactive
50
- terminal. App-root setup changes package.json and is refused in CI
51
- (CI, TEAMCITY_VERSION, or GITHUB_ACTIONS is set).`;
48
+ terminal. --manifest setup changes package.json and is refused in CI
49
+ (CI, TEAMCITY_VERSION, or GITHUB_ACTIONS is set). Do not export the token
50
+ persistently.`;
52
51
  function promptForTerminalToken() {
53
52
  const input = process.stdin;
54
53
  if (!input.isTTY || typeof input.setRawMode !== "function") {
@@ -127,19 +126,13 @@ function requireNpm(context) {
127
126
  return npmCli;
128
127
  }
129
128
  async function readKeys(values, context) {
130
- if (values.keys && values.manifest) {
131
- throw new Error("Provide either --keys or --manifest, not both.");
132
- }
133
- if (values.keys) {
134
- return values.keys.split(",").map((key) => key.trim()).filter(Boolean);
135
- }
136
129
  if (!values.manifest) {
137
- throw new Error("Provide --manifest or --keys. Use --help for usage.");
130
+ throw new Error("Provide --manifest. Use --help for usage.");
138
131
  }
139
- const { free, pro } = await manifest.readFontAwesomeManifest(
132
+ const manifest$1 = await manifest.readFontAwesomeManifest(
140
133
  node_path.resolve(context.cwd, values.manifest)
141
134
  );
142
- return [...free, ...pro];
135
+ return manifest.fontAwesomeManifestKeys(manifest$1);
143
136
  }
144
137
  function resolvePins(keys) {
145
138
  const tiers = new Map(
@@ -194,54 +187,10 @@ function checkNpmrc(config, file) {
194
187
  }
195
188
  return { fontAwesomeRegistry, hasAuth };
196
189
  }
197
- async function setupAppRoot(values, context) {
198
- const { log } = context;
199
- if (context.isCi) {
200
- throw new Error(
201
- `App-root setup changes package.json and is a local, one-time step. In CI, give ${tokenVariable} only to "npm ci --ignore-scripts", then run needed install scripts and the build without it.`
202
- );
203
- }
204
- const appRoot = context.cwd;
205
- if (!node_fs.existsSync(node_path.resolve(appRoot, "package.json"))) {
206
- throw new Error(
207
- "Run this command from the application root (package.json not found)."
208
- );
209
- }
210
- const freeOnly = Boolean(values["free-only"]);
211
- const pins = resolvePins(await readKeys(values, context));
212
- const proPins = [...pins.values()].filter((pin) => pin.tier === "pro");
213
- if (freeOnly && proPins.length) {
214
- throw new Error(
215
- `--free-only cannot install Pro keys: ${proPins.map((pin) => pin.key).join(", ")}.`
216
- );
217
- }
218
- if (!pins.size) {
219
- throw new Error("No Font Awesome keys selected.");
220
- }
221
- const npmrcPath = node_path.resolve(appRoot, ".npmrc");
222
- const config = node_fs.existsSync(npmrcPath) ? node_fs.readFileSync(npmrcPath, "utf8") : "";
223
- const { fontAwesomeRegistry, hasAuth } = checkNpmrc(config, ".npmrc");
224
- if (freeOnly && fontAwesomeRegistry) {
225
- throw new Error(
226
- `.npmrc routes @fortawesome to ${fontAwesomeRegistry}, so this app is set up for Pro. Run without --free-only.`
227
- );
228
- }
190
+ function installFreeIntoApp(pins, context) {
229
191
  const npmCli = requireNpm(context);
230
192
  const environment = { ...context.env };
231
- if (!freeOnly) {
232
- environment[tokenVariable] = await readToken(context);
233
- const missing = [];
234
- if (!fontAwesomeRegistry) missing.push(npmrcLines[0], npmrcLines[1]);
235
- if (!hasAuth) missing.push(npmrcLines[2], npmrcLines[3]);
236
- if (missing.length) {
237
- const separator = config && !config.endsWith("\n") ? "\n" : "";
238
- node_fs.writeFileSync(npmrcPath, `${config}${separator}${missing.join("\n")}
239
- `);
240
- log(
241
- `${config ? "Updated" : "Created"} .npmrc with the Font Awesome registry and token placeholder.`
242
- );
243
- }
244
- }
193
+ delete environment[tokenVariable];
245
194
  const specs = [...pins].map(([name, pin]) => `${name}@${pin.spec}`);
246
195
  const status = context.runNpm({
247
196
  npmCli,
@@ -252,27 +201,17 @@ async function setupAppRoot(values, context) {
252
201
  "--ignore-scripts",
253
202
  "--no-audit",
254
203
  "--no-fund",
255
- ...freeOnly ? [] : [pinRegistry],
256
204
  ...specs
257
205
  ],
258
- cwd: appRoot,
206
+ cwd: context.cwd,
259
207
  env: environment
260
208
  });
261
- if (status !== 0) return status;
262
- log(`Installed ${specs.length} Font Awesome package(s): ${specs.join(" ")}`);
263
- log(
264
- "Lifecycle scripts were skipped. If needed, run npm rebuild for dependency scripts and the app's own scripts (e.g. npm run prepare --if-present)."
265
- );
266
- if (freeOnly) {
267
- log(
268
- "Next: commit package.json and package-lock.json. Keep the Vite plugin's allowPro unset (Free only); no CI token is needed."
269
- );
270
- } else {
271
- log(
272
- `Next: commit .npmrc, package.json, and package-lock.json. Set allowPro: true in the Vite plugin (no sourceRoot). Later installs, including CI, give ${tokenVariable} only to "npm ci --ignore-scripts"; run needed install scripts and builds without it. See LICENSING.md for the TeamCity setup.`
209
+ if (status === 0) {
210
+ context.log(
211
+ `Installed ${specs.length} Font Awesome package(s) into the app: ${specs.join(" ")}`
273
212
  );
274
213
  }
275
- return 0;
214
+ return status;
276
215
  }
277
216
  function readDependencies(packageJsonPath) {
278
217
  try {
@@ -286,109 +225,61 @@ function readDependencies(packageJsonPath) {
286
225
  return void 0;
287
226
  }
288
227
  }
289
- async function initSourceProject(sourceRoot, values, context) {
290
- const { log, display } = context;
291
- if (context.isCi) {
292
- throw new Error(
293
- "--init is a local, one-time step. Commit the scaffolded source project instead of generating it in CI."
294
- );
295
- }
296
- const pins = resolvePins(await readKeys(values, context));
297
- const dependencies = {};
298
- const skipped = [];
299
- for (const [name, pin] of pins) {
300
- if (pin.tier === "pro") dependencies[name] = pin.spec;
301
- else skipped.push(pin.key);
302
- }
303
- if (!Object.keys(dependencies).length) {
304
- throw new Error(
305
- "No Pro keys selected. Free packages belong in the application's own devDependencies."
306
- );
307
- }
308
- const sortedDependencies = Object.fromEntries(
309
- Object.entries(dependencies).sort()
228
+ function writeSourceProject(sourceRoot, proPins, context) {
229
+ const dependencies = Object.fromEntries(
230
+ [...proPins].map(([name, pin]) => [name, pin.spec]).sort()
310
231
  );
232
+ const created = !node_fs.existsSync(node_path.resolve(sourceRoot, "package.json"));
233
+ const lockfilePath = node_path.resolve(sourceRoot, "package-lock.json");
234
+ const removeStaleLockfile = node_fs.existsSync(lockfilePath) && readDependencies(node_path.resolve(sourceRoot, "package.json")) !== JSON.stringify(dependencies);
311
235
  const files = {
312
236
  ".npmrc": `${npmrcLines.join("\n")}
313
237
  `,
314
238
  ".gitignore": "node_modules/\n",
315
239
  "package.json": `${JSON.stringify(
316
240
  {
317
- name: "fontawesome-pro-sources",
241
+ name: manifest.fontAwesomeProSourcesDir,
318
242
  version: "0.0.0",
319
243
  private: true,
320
- dependencies: sortedDependencies
244
+ dependencies
321
245
  },
322
246
  null,
323
247
  2
324
248
  )}
325
249
  `
326
250
  };
327
- const existing = Object.keys(files).filter(
328
- (name) => node_fs.existsSync(node_path.resolve(sourceRoot, name))
329
- );
330
- if (existing.length && !values.force) {
331
- throw new Error(
332
- `${display(sourceRoot)} already contains ${existing.join(", ")}. Use --force to overwrite.`
333
- );
334
- }
335
- const lockfilePath = node_path.resolve(sourceRoot, "package-lock.json");
336
- const removeStaleLockfile = node_fs.existsSync(lockfilePath) && readDependencies(node_path.resolve(sourceRoot, "package.json")) !== JSON.stringify(sortedDependencies);
337
251
  node_fs.mkdirSync(sourceRoot, { recursive: true });
338
252
  for (const [name, content] of Object.entries(files)) {
339
253
  node_fs.writeFileSync(node_path.resolve(sourceRoot, name), content);
340
254
  }
341
255
  if (removeStaleLockfile) node_fs.rmSync(lockfilePath);
342
- if (skipped.length) {
343
- log(
344
- `Skipped Free keys (install them in the application instead): ${skipped.join(", ")}`
345
- );
346
- }
347
- log(
348
- `Scaffolded ${display(sourceRoot)} with ${Object.keys(dependencies).length} Pro package(s).`
256
+ context.log(
257
+ `${created ? "Created" : "Updated"} ${manifest.fontAwesomeProSourcesDir}/ with ${proPins.size} Pro package(s).`
349
258
  );
350
259
  if (removeStaleLockfile) {
351
- log(
352
- `Removed ${display(sourceRoot)}/package-lock.json because the dependencies changed; the next install regenerates it.`
260
+ context.log(
261
+ `Removed ${manifest.fontAwesomeProSourcesDir}/package-lock.json because the Pro pins changed; this install regenerates it.`
353
262
  );
354
263
  }
355
- log(
356
- "Next: run this command with --source-root and without --init, then commit the source project and its package-lock.json."
357
- );
358
- return 0;
359
264
  }
360
- async function installSourceProject(sourceRoot, values, context) {
361
- const { log, display } = context;
265
+ async function installSourceProject(sourceRoot, token, context) {
362
266
  const npmCli = requireNpm(context);
363
- for (const name of ["package.json", ".npmrc"]) {
364
- if (!node_fs.existsSync(node_path.resolve(sourceRoot, name))) {
365
- throw new Error(
366
- `${display(sourceRoot)}/${name} was not found. Check --source-root, or scaffold the project with --init.`
367
- );
368
- }
369
- }
370
- const npmrc = `${display(sourceRoot)}/.npmrc`;
267
+ const npmrc = `${manifest.fontAwesomeProSourcesDir}/.npmrc`;
371
268
  const { fontAwesomeRegistry, hasAuth } = checkNpmrc(
372
269
  node_fs.readFileSync(node_path.resolve(sourceRoot, ".npmrc"), "utf8"),
373
270
  npmrc
374
271
  );
375
272
  if (!fontAwesomeRegistry || !hasAuth) {
376
273
  throw new Error(
377
- `${npmrc} must contain @fortawesome:registry=${registry} and ${authKey}=${tokenPlaceholder}. Scaffold it with --init.`
378
- );
379
- }
380
- const hasLockfile = node_fs.existsSync(node_path.resolve(sourceRoot, "package-lock.json"));
381
- if (context.isCi && !hasLockfile) {
382
- throw new Error(
383
- `${display(sourceRoot)}/package-lock.json is required in CI. Install locally first and commit the lockfile.`
274
+ `${npmrc} must contain @fortawesome:registry=${registry} and ${authKey}=${tokenPlaceholder}. Rerun with --manifest to rewrite it.`
384
275
  );
385
276
  }
386
- if (context.isCi && values["refresh-lock"]) {
277
+ const locked = node_fs.existsSync(node_path.resolve(sourceRoot, "package-lock.json"));
278
+ if (context.isCi && !locked) {
387
279
  throw new Error(
388
- "--refresh-lock updates the lockfile and is a local step. In CI, install from the committed lockfile."
280
+ `${manifest.fontAwesomeProSourcesDir}/package-lock.json is required in CI. Run setup with --manifest locally first and commit the lockfile.`
389
281
  );
390
282
  }
391
- const locked = hasLockfile && !values["refresh-lock"];
392
283
  const environment = {
393
284
  ...context.env,
394
285
  [tokenVariable]: await readToken(context)
@@ -408,12 +299,87 @@ async function installSourceProject(sourceRoot, values, context) {
408
299
  env: environment
409
300
  });
410
301
  if (status !== 0) return status;
411
- const lockfile = `${display(sourceRoot)}/package-lock.json`;
412
- log(
302
+ const lockfile = `${manifest.fontAwesomeProSourcesDir}/package-lock.json`;
303
+ context.log(
413
304
  locked ? `Pro sources installed from ${lockfile}.` : `Pro sources installed. Review and commit ${lockfile}.`
414
305
  );
306
+ context.log(
307
+ "Restart any running Vite dev server so it includes the installed Pro icons."
308
+ );
309
+ return 0;
310
+ }
311
+ async function setupFromManifest(values, context) {
312
+ const { log } = context;
313
+ const freeOnly = Boolean(values["free-only"]);
314
+ if (context.isCi) {
315
+ throw new Error(
316
+ `--manifest setup changes package.json and is a local step. In CI, run the app's own "npm ci", then featherk-fontawesome-setup without arguments to install ${manifest.fontAwesomeProSourcesDir}/.`
317
+ );
318
+ }
319
+ const appRoot = context.cwd;
320
+ if (!node_fs.existsSync(node_path.resolve(appRoot, "package.json"))) {
321
+ throw new Error(
322
+ "Run this command from the application root (package.json not found)."
323
+ );
324
+ }
325
+ const pins = resolvePins(await readKeys(values, context));
326
+ if (!pins.size) {
327
+ throw new Error("No Font Awesome keys selected.");
328
+ }
329
+ const freePins = new Map([...pins].filter(([, pin]) => pin.tier !== "pro"));
330
+ const proPins = new Map([...pins].filter(([, pin]) => pin.tier === "pro"));
331
+ if (freeOnly && proPins.size) {
332
+ throw new Error(
333
+ `--free-only cannot install Pro keys: ${[...proPins.values()].map((pin) => pin.key).join(", ")}.`
334
+ );
335
+ }
336
+ const npmrcPath = node_path.resolve(appRoot, ".npmrc");
337
+ const config = node_fs.existsSync(npmrcPath) ? node_fs.readFileSync(npmrcPath, "utf8") : "";
338
+ const { fontAwesomeRegistry } = checkNpmrc(config, ".npmrc");
339
+ const sourceRoot = node_path.resolve(appRoot, manifest.fontAwesomeProSourcesDir);
340
+ const isolated = manifest.isFontAwesomeIsolated(appRoot);
341
+ if (fontAwesomeRegistry) {
342
+ throw new Error(
343
+ `.npmrc routes @fortawesome to ${fontAwesomeRegistry}, which installs Pro packages in the app itself; that layout is not supported. Remove the Font Awesome lines from .npmrc and any @fortawesome/pro-* packages from the app's devDependencies, then rerun.`
344
+ );
345
+ }
346
+ if (freeOnly && isolated) {
347
+ throw new Error(
348
+ `${manifest.fontAwesomeProSourcesDir}/ exists, so this app uses Pro. Run without --free-only, or remove ${manifest.fontAwesomeProSourcesDir}/ first.`
349
+ );
350
+ }
351
+ if (freePins.size) {
352
+ const status2 = installFreeIntoApp(freePins, context);
353
+ if (status2 !== 0) return status2;
354
+ log(lifecycleNote);
355
+ }
356
+ if (!proPins.size) {
357
+ if (isolated) {
358
+ log(
359
+ `The manifest has no Pro keys; ${manifest.fontAwesomeProSourcesDir}/ is no longer needed and can be removed.`
360
+ );
361
+ }
362
+ log(
363
+ "Next: commit package.json and package-lock.json. Configure the Vite plugin with { manifest }; no token is needed."
364
+ );
365
+ return 0;
366
+ }
367
+ writeSourceProject(sourceRoot, proPins, context);
368
+ const status = await installSourceProject(sourceRoot, void 0, context);
369
+ if (status !== 0) return status;
370
+ log(
371
+ `Next: commit package.json, package-lock.json, and ${manifest.fontAwesomeProSourcesDir}/. Configure the Vite plugin with { manifest }; builds include Pro icons wherever ${manifest.fontAwesomeProSourcesDir}/ is installed. In CI, run the app's "npm ci" without the token, then featherk-fontawesome-setup with ${tokenVariable}, then the normal build.`
372
+ );
415
373
  return 0;
416
374
  }
375
+ const lifecycleNote = "Lifecycle scripts were skipped. If needed, run npm rebuild for dependency scripts and the app's own scripts (e.g. npm run prepare --if-present).";
376
+ const removedFlags = [
377
+ "--keys",
378
+ "--source-root",
379
+ "--init",
380
+ "--force",
381
+ "--refresh-lock"
382
+ ];
417
383
  async function runFontAwesomeSetup(args, io = {}) {
418
384
  const cwd = io.cwd ?? process.cwd();
419
385
  const env = io.env ?? process.env;
@@ -425,20 +391,26 @@ async function runFontAwesomeSetup(args, io = {}) {
425
391
  isCi: Boolean(env.CI) && env.CI !== "false" || Boolean(env.TEAMCITY_VERSION || env.GITHUB_ACTIONS),
426
392
  log: io.stdout ?? console.log,
427
393
  promptForToken: io.promptForToken ?? promptForTerminalToken,
428
- runNpm: io.runNpm ?? spawnNpm,
429
- display: (path) => node_path.relative(cwd, path) || "."
394
+ runNpm: io.runNpm ?? spawnNpm
430
395
  };
396
+ const hasFlag = (flag) => args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
431
397
  try {
398
+ const removed = removedFlags.find(hasFlag);
399
+ if (removed) {
400
+ throw new Error(
401
+ `${removed} was removed in 0.16.0. Run setup with --manifest; Pro sources always live in ${manifest.fontAwesomeProSourcesDir}/, and rerunning with --manifest updates them. Use --help for usage.`
402
+ );
403
+ }
404
+ if (hasFlag("--pro-in-app")) {
405
+ throw new Error(
406
+ `--pro-in-app was removed. Pro packages always install into ${manifest.fontAwesomeProSourcesDir}/, so the app's own install never needs the token. Run setup with --manifest.`
407
+ );
408
+ }
432
409
  const { values } = node_util.parseArgs({
433
410
  args: [...args],
434
411
  options: {
435
- "source-root": { type: "string" },
436
412
  "free-only": { type: "boolean" },
437
- init: { type: "boolean" },
438
- keys: { type: "string" },
439
413
  manifest: { type: "string" },
440
- force: { type: "boolean" },
441
- "refresh-lock": { type: "boolean" },
442
414
  help: { type: "boolean", short: "h" }
443
415
  },
444
416
  strict: true,
@@ -448,26 +420,22 @@ async function runFontAwesomeSetup(args, io = {}) {
448
420
  context.log(usage);
449
421
  return 0;
450
422
  }
451
- if (values["source-root"] === void 0) {
452
- if (values.init || values.force || values["refresh-lock"]) {
453
- throw new Error(
454
- "--init, --force, and --refresh-lock apply only with --source-root."
455
- );
456
- }
457
- return await setupAppRoot(values, context);
423
+ if (values.manifest !== void 0) {
424
+ return await setupFromManifest(values, context);
458
425
  }
459
426
  if (values["free-only"]) {
460
- throw new Error(
461
- "--free-only applies only to app-root setup; an isolated source project holds Pro packages."
462
- );
427
+ throw new Error("--free-only requires --manifest.");
463
428
  }
464
- if (values.init && values["refresh-lock"]) {
429
+ if (!manifest.isFontAwesomeIsolated(cwd)) {
465
430
  throw new Error(
466
- "--refresh-lock applies to the install step, not --init."
431
+ `${manifest.fontAwesomeProSourcesDir}/package.json was not found. Run from the application root; for first-time setup, run with --manifest <icons.json>.`
467
432
  );
468
433
  }
469
- const sourceRoot = node_path.resolve(cwd, values["source-root"]);
470
- return values.init ? await initSourceProject(sourceRoot, values, context) : await installSourceProject(sourceRoot, values, context);
434
+ return await installSourceProject(
435
+ node_path.resolve(cwd, manifest.fontAwesomeProSourcesDir),
436
+ void 0,
437
+ context
438
+ );
471
439
  } catch (error) {
472
440
  stderr(error instanceof Error ? error.message : "Unknown error");
473
441
  return 1;
@@ -30,8 +30,8 @@ export declare function checkNpmrc(config: string, file: string): {
30
30
  hasAuth: boolean;
31
31
  };
32
32
  /**
33
- * Parses setup arguments and runs app-root setup, source-project scaffolding,
34
- * or source-project installation.
33
+ * Parses setup arguments and runs manifest setup, or installs the isolated
34
+ * source project when no arguments are given.
35
35
  *
36
36
  * @returns `0` on success, npm's exit status when an install fails, and `1`
37
37
  * when argument, manifest, config, or environment validation fails.