@akii09/pdfx-cli 0.1.2 → 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.
Files changed (2) hide show
  1. package/dist/index.js +606 -203
  2. package/package.json +4 -1
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ var __export = (target, all) => {
9
9
  import { Command } from "commander";
10
10
 
11
11
  // src/commands/add.ts
12
- import path2 from "path";
12
+ import path3 from "path";
13
13
 
14
14
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
15
15
  var external_exports = {};
@@ -489,8 +489,8 @@ function getErrorMap() {
489
489
 
490
490
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
491
491
  var makeIssue = (params) => {
492
- const { data, path: path8, errorMaps, issueData } = params;
493
- const fullPath = [...path8, ...issueData.path || []];
492
+ const { data, path: path11, errorMaps, issueData } = params;
493
+ const fullPath = [...path11, ...issueData.path || []];
494
494
  const fullIssue = {
495
495
  ...issueData,
496
496
  path: fullPath
@@ -606,11 +606,11 @@ var errorUtil;
606
606
 
607
607
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
608
608
  var ParseInputLazyPath = class {
609
- constructor(parent, value, path8, key) {
609
+ constructor(parent, value, path11, key) {
610
610
  this._cachedPath = [];
611
611
  this.parent = parent;
612
612
  this.data = value;
613
- this._path = path8;
613
+ this._path = path11;
614
614
  this._key = key;
615
615
  }
616
616
  get path() {
@@ -4461,30 +4461,156 @@ import chalk from "chalk";
4461
4461
  import ora from "ora";
4462
4462
  import prompts from "prompts";
4463
4463
 
4464
- // src/utils/file-system.ts
4465
- import fs from "fs";
4464
+ // src/utils/dependency-validator.ts
4465
+ import fs2 from "fs";
4466
4466
  import path from "path";
4467
+ import semver from "semver";
4468
+
4469
+ // src/utils/read-json.ts
4470
+ import fs from "fs";
4471
+ function readJsonFile(filePath) {
4472
+ const raw = fs.readFileSync(filePath, "utf-8");
4473
+ try {
4474
+ return JSON.parse(raw);
4475
+ } catch (error) {
4476
+ const details = error instanceof Error ? error.message : String(error);
4477
+ throw new ConfigError(`Invalid JSON in ${filePath}: ${details}`);
4478
+ }
4479
+ }
4480
+
4481
+ // src/utils/dependency-validator.ts
4482
+ var REQUIRED_VERSIONS = {
4483
+ "@react-pdf/renderer": ">=3.0.0",
4484
+ react: ">=16.8.0",
4485
+ node: ">=24.0.0"
4486
+ };
4487
+ function getPackageJson(cwd = process.cwd()) {
4488
+ const pkgPath = path.join(cwd, "package.json");
4489
+ if (!fs2.existsSync(pkgPath)) {
4490
+ return null;
4491
+ }
4492
+ return readJsonFile(pkgPath);
4493
+ }
4494
+ function getInstalledVersion(packageName, cwd = process.cwd()) {
4495
+ const pkg = getPackageJson(cwd);
4496
+ if (!pkg) return null;
4497
+ const deps = {
4498
+ ...pkg.dependencies,
4499
+ ...pkg.devDependencies
4500
+ };
4501
+ const version = deps[packageName];
4502
+ if (!version) return null;
4503
+ return semver.clean(version) || semver.coerce(version)?.version || null;
4504
+ }
4505
+ function validateReactPdfRenderer(cwd = process.cwd()) {
4506
+ const version = getInstalledVersion("@react-pdf/renderer", cwd);
4507
+ const required = REQUIRED_VERSIONS["@react-pdf/renderer"];
4508
+ if (!version) {
4509
+ return {
4510
+ valid: false,
4511
+ installed: false,
4512
+ requiredVersion: required,
4513
+ message: "@react-pdf/renderer is not installed"
4514
+ };
4515
+ }
4516
+ const isCompatible = semver.satisfies(version, required);
4517
+ return {
4518
+ valid: isCompatible,
4519
+ installed: true,
4520
+ currentVersion: version,
4521
+ requiredVersion: required,
4522
+ message: isCompatible ? "@react-pdf/renderer version is compatible" : `@react-pdf/renderer version ${version} does not meet requirement ${required}`
4523
+ };
4524
+ }
4525
+ function validateReact(cwd = process.cwd()) {
4526
+ const version = getInstalledVersion("react", cwd);
4527
+ const required = REQUIRED_VERSIONS.react;
4528
+ if (!version) {
4529
+ return {
4530
+ valid: false,
4531
+ installed: false,
4532
+ requiredVersion: required,
4533
+ message: "React is not installed"
4534
+ };
4535
+ }
4536
+ const isCompatible = semver.satisfies(version, required);
4537
+ return {
4538
+ valid: isCompatible,
4539
+ installed: true,
4540
+ currentVersion: version,
4541
+ requiredVersion: required,
4542
+ message: isCompatible ? "React version is compatible" : `React version ${version} does not meet requirement ${required}`
4543
+ };
4544
+ }
4545
+ function validateNodeVersion() {
4546
+ const version = process.version;
4547
+ const required = REQUIRED_VERSIONS.node;
4548
+ const cleanVersion = semver.clean(version);
4549
+ if (!cleanVersion) {
4550
+ return {
4551
+ valid: false,
4552
+ installed: true,
4553
+ currentVersion: version,
4554
+ requiredVersion: required,
4555
+ message: `Unable to parse Node.js version: ${version}`
4556
+ };
4557
+ }
4558
+ const isCompatible = semver.satisfies(cleanVersion, required);
4559
+ return {
4560
+ valid: isCompatible,
4561
+ installed: true,
4562
+ currentVersion: cleanVersion,
4563
+ requiredVersion: required,
4564
+ message: isCompatible ? "Node.js version is compatible" : `Node.js version ${cleanVersion} does not meet requirement ${required}`
4565
+ };
4566
+ }
4567
+ function validateTypeScript(cwd = process.cwd()) {
4568
+ const tsVersion = getInstalledVersion("typescript", cwd);
4569
+ if (!tsVersion) {
4570
+ return null;
4571
+ }
4572
+ const typesInstalled = getInstalledVersion("@types/react-pdf", cwd);
4573
+ return {
4574
+ valid: !!typesInstalled,
4575
+ installed: !!typesInstalled,
4576
+ currentVersion: typesInstalled || void 0,
4577
+ requiredVersion: "latest",
4578
+ message: typesInstalled ? "TypeScript types for @react-pdf/renderer are installed" : "@types/react-pdf is recommended for TypeScript projects"
4579
+ };
4580
+ }
4581
+ function validateDependencies(cwd = process.cwd()) {
4582
+ return {
4583
+ reactPdfRenderer: validateReactPdfRenderer(cwd),
4584
+ react: validateReact(cwd),
4585
+ nodeJs: validateNodeVersion(),
4586
+ typescript: validateTypeScript(cwd) || void 0
4587
+ };
4588
+ }
4589
+
4590
+ // src/utils/file-system.ts
4591
+ import fs3 from "fs";
4592
+ import path2 from "path";
4467
4593
  function ensureDir(dir) {
4468
- if (!fs.existsSync(dir)) {
4469
- fs.mkdirSync(dir, { recursive: true });
4594
+ if (!fs3.existsSync(dir)) {
4595
+ fs3.mkdirSync(dir, { recursive: true });
4470
4596
  }
4471
4597
  }
4472
4598
  function writeFile(filePath, content) {
4473
- const dir = path.dirname(filePath);
4599
+ const dir = path2.dirname(filePath);
4474
4600
  ensureDir(dir);
4475
- fs.writeFileSync(filePath, content, "utf-8");
4601
+ fs3.writeFileSync(filePath, content, "utf-8");
4476
4602
  }
4477
4603
  function checkFileExists(filePath) {
4478
- return fs.existsSync(filePath);
4604
+ return fs3.existsSync(filePath);
4479
4605
  }
4480
4606
  function normalizePath(...segments) {
4481
- return path.resolve(...segments);
4607
+ return path2.resolve(...segments);
4482
4608
  }
4483
4609
  function isPathWithinDirectory(resolvedPath, targetDir) {
4484
4610
  const normalizedTarget = normalizePath(targetDir);
4485
4611
  const normalizedResolved = normalizePath(resolvedPath);
4486
4612
  if (normalizedResolved === normalizedTarget) return true;
4487
- const prefix = normalizedTarget.endsWith(path.sep) ? normalizedTarget : normalizedTarget + path.sep;
4613
+ const prefix = normalizedTarget.endsWith(path2.sep) ? normalizedTarget : normalizedTarget + path2.sep;
4488
4614
  return normalizedResolved.startsWith(prefix);
4489
4615
  }
4490
4616
  function safePath(targetDir, fileName) {
@@ -4754,18 +4880,6 @@ export function useSafeMemo<T>(factory: () => T, deps: DependencyList): T {
4754
4880
  `;
4755
4881
  }
4756
4882
 
4757
- // src/utils/read-json.ts
4758
- import fs2 from "fs";
4759
- function readJsonFile(filePath) {
4760
- const raw = fs2.readFileSync(filePath, "utf-8");
4761
- try {
4762
- return JSON.parse(raw);
4763
- } catch (error) {
4764
- const details = error instanceof Error ? error.message : String(error);
4765
- throw new ConfigError(`Invalid JSON in ${filePath}: ${details}`);
4766
- }
4767
- }
4768
-
4769
4883
  // src/commands/add.ts
4770
4884
  function readConfig(configPath) {
4771
4885
  const raw = readJsonFile(configPath);
@@ -4810,15 +4924,15 @@ async function fetchComponent(name, registryUrl) {
4810
4924
  return result.data;
4811
4925
  }
4812
4926
  function resolveThemeImport(componentDir, themePath, fileContent) {
4813
- const absComponentDir = path2.resolve(process.cwd(), componentDir);
4814
- const absThemePath = path2.resolve(process.cwd(), themePath);
4927
+ const absComponentDir = path3.resolve(process.cwd(), componentDir);
4928
+ const absThemePath = path3.resolve(process.cwd(), themePath);
4815
4929
  const themeImportTarget = absThemePath.replace(/\.tsx?$/, "");
4816
- let relativePath = path2.relative(absComponentDir, themeImportTarget);
4930
+ let relativePath = path3.relative(absComponentDir, themeImportTarget);
4817
4931
  if (!relativePath.startsWith(".")) {
4818
4932
  relativePath = `./${relativePath}`;
4819
4933
  }
4820
- const absContextPath = path2.join(path2.dirname(absThemePath), "pdfx-theme-context");
4821
- let relativeContextPath = path2.relative(absComponentDir, absContextPath);
4934
+ const absContextPath = path3.join(path3.dirname(absThemePath), "pdfx-theme-context");
4935
+ let relativeContextPath = path3.relative(absComponentDir, absContextPath);
4822
4936
  if (!relativeContextPath.startsWith(".")) {
4823
4937
  relativeContextPath = `./${relativeContextPath}`;
4824
4938
  }
@@ -4834,13 +4948,13 @@ function resolveThemeImport(componentDir, themePath, fileContent) {
4834
4948
  }
4835
4949
  async function installComponent(name, config, force) {
4836
4950
  const component = await fetchComponent(name, config.registry);
4837
- const targetDir = path2.resolve(process.cwd(), config.componentDir);
4838
- const componentDir = path2.join(targetDir, component.name);
4951
+ const targetDir = path3.resolve(process.cwd(), config.componentDir);
4952
+ const componentDir = path3.join(targetDir, component.name);
4839
4953
  ensureDir(componentDir);
4840
- const componentRelDir = path2.join(config.componentDir, component.name);
4954
+ const componentRelDir = path3.join(config.componentDir, component.name);
4841
4955
  const filesToWrite = [];
4842
4956
  for (const file of component.files) {
4843
- const fileName = path2.basename(file.path);
4957
+ const fileName = path3.basename(file.path);
4844
4958
  const filePath = safePath(componentDir, fileName);
4845
4959
  let content = file.content;
4846
4960
  if (config.theme && (content.includes("pdfx-theme") || content.includes("pdfx-theme-context"))) {
@@ -4851,7 +4965,7 @@ async function installComponent(name, config, force) {
4851
4965
  if (!force) {
4852
4966
  const existing = filesToWrite.filter((f) => checkFileExists(f.filePath));
4853
4967
  if (existing.length > 0) {
4854
- const fileNames = existing.map((f) => path2.basename(f.filePath)).join(", ");
4968
+ const fileNames = existing.map((f) => path3.basename(f.filePath)).join(", ");
4855
4969
  const { overwrite } = await prompts({
4856
4970
  type: "confirm",
4857
4971
  name: "overwrite",
@@ -4867,17 +4981,35 @@ async function installComponent(name, config, force) {
4867
4981
  writeFile(file.filePath, file.content);
4868
4982
  }
4869
4983
  if (config.theme) {
4870
- const absThemePath = path2.resolve(process.cwd(), config.theme);
4871
- const contextPath = path2.join(path2.dirname(absThemePath), "pdfx-theme-context.tsx");
4984
+ const absThemePath = path3.resolve(process.cwd(), config.theme);
4985
+ const contextPath = path3.join(path3.dirname(absThemePath), "pdfx-theme-context.tsx");
4872
4986
  if (!checkFileExists(contextPath)) {
4873
- ensureDir(path2.dirname(contextPath));
4987
+ ensureDir(path3.dirname(contextPath));
4874
4988
  writeFile(contextPath, generateThemeContextFile());
4875
4989
  }
4876
4990
  }
4877
4991
  return;
4878
4992
  }
4879
4993
  async function add(components, options = {}) {
4880
- const configPath = path2.join(process.cwd(), "pdfx.json");
4994
+ const reactPdfCheck = validateReactPdfRenderer();
4995
+ if (!reactPdfCheck.installed) {
4996
+ console.error(chalk.red("\nError: @react-pdf/renderer is not installed\n"));
4997
+ console.log(chalk.yellow(" PDFx components require @react-pdf/renderer to work.\n"));
4998
+ console.log(chalk.cyan(" Run: pdfx init"));
4999
+ console.log(chalk.dim(" or install manually: npm install @react-pdf/renderer\n"));
5000
+ process.exit(1);
5001
+ }
5002
+ if (!reactPdfCheck.valid) {
5003
+ console.log(
5004
+ chalk.yellow(
5005
+ `
5006
+ \u26A0 Warning: ${reactPdfCheck.message}
5007
+ ${chalk.dim("\u2192")} You may encounter compatibility issues
5008
+ `
5009
+ )
5010
+ );
5011
+ }
5012
+ const configPath = path3.join(process.cwd(), "pdfx.json");
4881
5013
  if (!checkFileExists(configPath)) {
4882
5014
  console.error(chalk.red("Error: pdfx.json not found"));
4883
5015
  console.log(chalk.yellow("Run: pdfx init"));
@@ -4933,7 +5065,7 @@ async function add(components, options = {}) {
4933
5065
  console.log(chalk.yellow(`Failed to add: ${failed.join(", ")}`));
4934
5066
  }
4935
5067
  if (failed.length < components.length) {
4936
- const resolvedDir = path2.resolve(process.cwd(), config.componentDir);
5068
+ const resolvedDir = path3.resolve(process.cwd(), config.componentDir);
4937
5069
  console.log(chalk.green("Done!"));
4938
5070
  console.log(chalk.dim(`Components installed to: ${resolvedDir}
4939
5071
  `));
@@ -4944,13 +5076,13 @@ async function add(components, options = {}) {
4944
5076
  }
4945
5077
 
4946
5078
  // src/commands/diff.ts
4947
- import fs3 from "fs";
4948
- import path3 from "path";
5079
+ import fs4 from "fs";
5080
+ import path4 from "path";
4949
5081
  import chalk2 from "chalk";
4950
5082
  import ora2 from "ora";
4951
5083
  var FETCH_TIMEOUT_MS = 1e4;
4952
5084
  async function diff(components) {
4953
- const configPath = path3.join(process.cwd(), "pdfx.json");
5085
+ const configPath = path4.join(process.cwd(), "pdfx.json");
4954
5086
  if (!checkFileExists(configPath)) {
4955
5087
  console.error(chalk2.red("Error: pdfx.json not found"));
4956
5088
  console.log(chalk2.yellow("Run: pdfx init"));
@@ -4963,7 +5095,7 @@ async function diff(components) {
4963
5095
  process.exit(1);
4964
5096
  }
4965
5097
  const config = configResult.data;
4966
- const targetDir = path3.resolve(process.cwd(), config.componentDir);
5098
+ const targetDir = path4.resolve(process.cwd(), config.componentDir);
4967
5099
  for (const componentName of components) {
4968
5100
  const nameResult = componentNameSchema.safeParse(componentName);
4969
5101
  if (!nameResult.success) {
@@ -4995,17 +5127,17 @@ async function diff(components) {
4995
5127
  }
4996
5128
  const component = result.data;
4997
5129
  spinner.stop();
4998
- const componentSubDir = path3.join(targetDir, component.name);
5130
+ const componentSubDir = path4.join(targetDir, component.name);
4999
5131
  for (const file of component.files) {
5000
- const fileName = path3.basename(file.path);
5132
+ const fileName = path4.basename(file.path);
5001
5133
  const localPath = safePath(componentSubDir, fileName);
5002
5134
  if (!checkFileExists(localPath)) {
5003
5135
  console.log(chalk2.yellow(` ${fileName}: not installed locally`));
5004
5136
  continue;
5005
5137
  }
5006
- const localContent = fs3.readFileSync(localPath, "utf-8");
5138
+ const localContent = fs4.readFileSync(localPath, "utf-8");
5007
5139
  const registryContent = config.theme && (file.content.includes("pdfx-theme") || file.content.includes("pdfx-theme-context")) ? resolveThemeImport(
5008
- path3.join(config.componentDir, component.name),
5140
+ path4.join(config.componentDir, component.name),
5009
5141
  config.theme,
5010
5142
  file.content
5011
5143
  ) : file.content;
@@ -5028,11 +5160,11 @@ async function diff(components) {
5028
5160
  }
5029
5161
 
5030
5162
  // src/commands/init.ts
5031
- import fs4 from "fs";
5032
- import path4 from "path";
5033
- import chalk3 from "chalk";
5034
- import ora3 from "ora";
5035
- import prompts2 from "prompts";
5163
+ import fs7 from "fs";
5164
+ import path7 from "path";
5165
+ import chalk5 from "chalk";
5166
+ import ora4 from "ora";
5167
+ import prompts3 from "prompts";
5036
5168
 
5037
5169
  // src/constants.ts
5038
5170
  var DEFAULTS = {
@@ -5046,23 +5178,294 @@ var REGISTRY_SUBPATHS = {
5046
5178
  TEMPLATES: "templates"
5047
5179
  };
5048
5180
 
5181
+ // src/utils/install-dependencies.ts
5182
+ import chalk3 from "chalk";
5183
+ import { execa } from "execa";
5184
+ import ora3 from "ora";
5185
+ import prompts2 from "prompts";
5186
+
5187
+ // src/utils/package-manager.ts
5188
+ import fs5 from "fs";
5189
+ import path5 from "path";
5190
+ var PACKAGE_MANAGERS = {
5191
+ pnpm: {
5192
+ name: "pnpm",
5193
+ lockfile: "pnpm-lock.yaml",
5194
+ installCommand: "pnpm add"
5195
+ },
5196
+ yarn: {
5197
+ name: "yarn",
5198
+ lockfile: "yarn.lock",
5199
+ installCommand: "yarn add"
5200
+ },
5201
+ bun: {
5202
+ name: "bun",
5203
+ lockfile: "bun.lockb",
5204
+ installCommand: "bun add"
5205
+ },
5206
+ npm: {
5207
+ name: "npm",
5208
+ lockfile: "package-lock.json",
5209
+ installCommand: "npm install"
5210
+ }
5211
+ };
5212
+ function detectPackageManager(cwd = process.cwd()) {
5213
+ const managers = ["pnpm", "yarn", "bun", "npm"];
5214
+ for (const manager of managers) {
5215
+ const info = PACKAGE_MANAGERS[manager];
5216
+ const lockfilePath = path5.join(cwd, info.lockfile);
5217
+ if (fs5.existsSync(lockfilePath)) {
5218
+ return info;
5219
+ }
5220
+ }
5221
+ return PACKAGE_MANAGERS.npm;
5222
+ }
5223
+ function getInstallCommand(packageManager, packages, devDependency = false) {
5224
+ const pm = PACKAGE_MANAGERS[packageManager];
5225
+ const devFlag = devDependency ? packageManager === "npm" ? "--save-dev" : "-D" : "";
5226
+ return `${pm.installCommand} ${packages.join(" ")} ${devFlag}`.trim();
5227
+ }
5228
+
5229
+ // src/utils/install-dependencies.ts
5230
+ async function promptAndInstallReactPdf(validation, cwd = process.cwd()) {
5231
+ if (validation.installed && validation.valid) {
5232
+ return {
5233
+ success: true,
5234
+ message: "@react-pdf/renderer is already installed and compatible"
5235
+ };
5236
+ }
5237
+ const pm = detectPackageManager(cwd);
5238
+ const packageName = "@react-pdf/renderer";
5239
+ const installCmd = getInstallCommand(pm.name, [packageName]);
5240
+ console.log(chalk3.yellow("\n \u26A0 @react-pdf/renderer is required but not installed\n"));
5241
+ console.log(chalk3.dim(` This command will run: ${installCmd}
5242
+ `));
5243
+ const { shouldInstall } = await prompts2({
5244
+ type: "confirm",
5245
+ name: "shouldInstall",
5246
+ message: "Install @react-pdf/renderer now?",
5247
+ initial: true
5248
+ });
5249
+ if (!shouldInstall) {
5250
+ return {
5251
+ success: false,
5252
+ message: `Installation cancelled. Please install manually:
5253
+ ${chalk3.cyan(installCmd)}`
5254
+ };
5255
+ }
5256
+ const spinner = ora3("Installing @react-pdf/renderer...").start();
5257
+ try {
5258
+ await execa(pm.name, ["add", packageName], {
5259
+ cwd,
5260
+ stdio: "pipe"
5261
+ });
5262
+ spinner.succeed("Installed @react-pdf/renderer");
5263
+ return {
5264
+ success: true,
5265
+ message: "@react-pdf/renderer installed successfully"
5266
+ };
5267
+ } catch (error) {
5268
+ spinner.fail("Failed to install @react-pdf/renderer");
5269
+ const message = error instanceof Error ? error.message : String(error);
5270
+ return {
5271
+ success: false,
5272
+ message: `Installation failed: ${message}
5273
+ Try manually: ${chalk3.cyan(installCmd)}`
5274
+ };
5275
+ }
5276
+ }
5277
+ async function ensureReactPdfRenderer(validation, cwd = process.cwd()) {
5278
+ if (!validation.installed) {
5279
+ const result = await promptAndInstallReactPdf(validation, cwd);
5280
+ if (!result.success) {
5281
+ console.error(chalk3.red(`
5282
+ ${result.message}
5283
+ `));
5284
+ return false;
5285
+ }
5286
+ return true;
5287
+ }
5288
+ if (!validation.valid) {
5289
+ console.log(
5290
+ chalk3.yellow(
5291
+ `
5292
+ \u26A0 ${validation.message}
5293
+ ${chalk3.dim("\u2192")} You may encounter compatibility issues
5294
+ `
5295
+ )
5296
+ );
5297
+ }
5298
+ return true;
5299
+ }
5300
+
5301
+ // src/utils/pre-flight.ts
5302
+ import chalk4 from "chalk";
5303
+
5304
+ // src/utils/environment-validator.ts
5305
+ import fs6 from "fs";
5306
+ import path6 from "path";
5307
+ function validatePackageJson(cwd = process.cwd()) {
5308
+ const pkgPath = path6.join(cwd, "package.json");
5309
+ const exists = fs6.existsSync(pkgPath);
5310
+ return {
5311
+ valid: exists,
5312
+ message: exists ? "package.json found" : "No package.json found in current directory",
5313
+ fixCommand: exists ? void 0 : 'Run "npm init" or "pnpm init" to create a package.json'
5314
+ };
5315
+ }
5316
+ function validateReactProject(cwd = process.cwd()) {
5317
+ const pkgPath = path6.join(cwd, "package.json");
5318
+ if (!fs6.existsSync(pkgPath)) {
5319
+ return {
5320
+ valid: false,
5321
+ message: "Cannot validate React project without package.json"
5322
+ };
5323
+ }
5324
+ try {
5325
+ const pkg = readJsonFile(pkgPath);
5326
+ const deps = {
5327
+ ...pkg.dependencies,
5328
+ ...pkg.devDependencies
5329
+ };
5330
+ const hasReact = "react" in deps;
5331
+ return {
5332
+ valid: hasReact,
5333
+ message: hasReact ? "React is installed" : "This does not appear to be a React project",
5334
+ fixCommand: hasReact ? void 0 : "Install React: npx create-vite@latest or npx create-react-app"
5335
+ };
5336
+ } catch {
5337
+ return {
5338
+ valid: false,
5339
+ message: "Failed to read package.json"
5340
+ };
5341
+ }
5342
+ }
5343
+ function validatePdfxConfig(cwd = process.cwd()) {
5344
+ const configPath = path6.join(cwd, "pdfx.json");
5345
+ const exists = fs6.existsSync(configPath);
5346
+ return {
5347
+ valid: true,
5348
+ // Not blocking
5349
+ message: exists ? "pdfx.json already exists (will prompt to overwrite)" : "No existing pdfx.json"
5350
+ };
5351
+ }
5352
+ function validateEnvironment(cwd = process.cwd()) {
5353
+ return {
5354
+ hasPackageJson: validatePackageJson(cwd),
5355
+ isReactProject: validateReactProject(cwd),
5356
+ hasPdfxConfig: validatePdfxConfig(cwd)
5357
+ };
5358
+ }
5359
+
5360
+ // src/utils/pre-flight.ts
5361
+ function runPreFlightChecks(cwd = process.cwd()) {
5362
+ const environment = validateEnvironment(cwd);
5363
+ const dependencies = validateDependencies(cwd);
5364
+ const blockingErrors = [];
5365
+ const warnings = [];
5366
+ if (!environment.hasPackageJson.valid) {
5367
+ blockingErrors.push(
5368
+ `${environment.hasPackageJson.message}
5369
+ ${chalk4.dim("\u2192")} ${environment.hasPackageJson.fixCommand}`
5370
+ );
5371
+ }
5372
+ if (!environment.isReactProject.valid) {
5373
+ blockingErrors.push(
5374
+ `${environment.isReactProject.message}
5375
+ ${chalk4.dim("\u2192")} ${environment.isReactProject.fixCommand}`
5376
+ );
5377
+ }
5378
+ if (!dependencies.nodeJs.valid) {
5379
+ blockingErrors.push(
5380
+ `${dependencies.nodeJs.message}
5381
+ ${chalk4.dim("\u2192")} Current: ${dependencies.nodeJs.currentVersion}, Required: ${dependencies.nodeJs.requiredVersion}
5382
+ ${chalk4.dim("\u2192")} Visit https://nodejs.org to upgrade`
5383
+ );
5384
+ }
5385
+ if (!dependencies.react.valid && dependencies.react.installed) {
5386
+ warnings.push(
5387
+ `${dependencies.react.message}
5388
+ ${chalk4.dim("\u2192")} Current: ${dependencies.react.currentVersion}, Required: ${dependencies.react.requiredVersion}`
5389
+ );
5390
+ } else if (!dependencies.react.installed) {
5391
+ blockingErrors.push(
5392
+ `${dependencies.react.message}
5393
+ ${chalk4.dim("\u2192")} This should have been caught by React project check`
5394
+ );
5395
+ }
5396
+ if (dependencies.reactPdfRenderer.installed && !dependencies.reactPdfRenderer.valid) {
5397
+ warnings.push(
5398
+ `${dependencies.reactPdfRenderer.message}
5399
+ ${chalk4.dim("\u2192")} Consider upgrading: npm install @react-pdf/renderer@latest`
5400
+ );
5401
+ }
5402
+ if (dependencies.typescript && !dependencies.typescript.valid) {
5403
+ warnings.push(
5404
+ `${dependencies.typescript.message}
5405
+ ${chalk4.dim("\u2192")} Install types: npm install -D @types/react-pdf`
5406
+ );
5407
+ }
5408
+ return {
5409
+ environment,
5410
+ dependencies,
5411
+ blockingErrors,
5412
+ warnings,
5413
+ canProceed: blockingErrors.length === 0
5414
+ };
5415
+ }
5416
+ function displayPreFlightResults(result) {
5417
+ console.log(chalk4.bold("\n Pre-flight Checks:\n"));
5418
+ if (result.blockingErrors.length > 0) {
5419
+ console.log(chalk4.red(" \u2717 Blocking Issues:\n"));
5420
+ for (const error of result.blockingErrors) {
5421
+ console.log(chalk4.red(` \u2022 ${error}
5422
+ `));
5423
+ }
5424
+ }
5425
+ if (result.warnings.length > 0) {
5426
+ console.log(chalk4.yellow(" \u26A0 Warnings:\n"));
5427
+ for (const warning of result.warnings) {
5428
+ console.log(chalk4.yellow(` \u2022 ${warning}
5429
+ `));
5430
+ }
5431
+ }
5432
+ if (result.blockingErrors.length === 0 && result.warnings.length === 0) {
5433
+ console.log(chalk4.green(" \u2713 All checks passed!\n"));
5434
+ }
5435
+ }
5436
+
5049
5437
  // src/commands/init.ts
5050
5438
  async function init() {
5051
- console.log(chalk3.bold.cyan("\n Welcome to the pdfx cli\n"));
5052
- const existingConfig = path4.join(process.cwd(), "pdfx.json");
5053
- if (fs4.existsSync(existingConfig)) {
5054
- const { overwrite } = await prompts2({
5439
+ console.log(chalk5.bold.cyan("\n Welcome to the pdfx cli\n"));
5440
+ const preFlightResult = runPreFlightChecks();
5441
+ displayPreFlightResults(preFlightResult);
5442
+ if (!preFlightResult.canProceed) {
5443
+ console.error(
5444
+ chalk5.red("\n Cannot proceed due to blocking issues. Please fix them and try again.\n")
5445
+ );
5446
+ process.exit(1);
5447
+ }
5448
+ const hasReactPdf = await ensureReactPdfRenderer(preFlightResult.dependencies.reactPdfRenderer);
5449
+ if (!hasReactPdf) {
5450
+ console.error(
5451
+ chalk5.red("\n @react-pdf/renderer is required. Please install it and try again.\n")
5452
+ );
5453
+ process.exit(1);
5454
+ }
5455
+ const existingConfig = path7.join(process.cwd(), "pdfx.json");
5456
+ if (fs7.existsSync(existingConfig)) {
5457
+ const { overwrite } = await prompts3({
5055
5458
  type: "confirm",
5056
5459
  name: "overwrite",
5057
5460
  message: "pdfx.json already exists. Overwrite?",
5058
5461
  initial: false
5059
5462
  });
5060
5463
  if (!overwrite) {
5061
- console.log(chalk3.yellow("Init cancelled \u2014 existing config preserved."));
5464
+ console.log(chalk5.yellow("Init cancelled \u2014 existing config preserved."));
5062
5465
  return;
5063
5466
  }
5064
5467
  }
5065
- const answers = await prompts2(
5468
+ const answers = await prompts3(
5066
5469
  [
5067
5470
  {
5068
5471
  type: "text",
@@ -5108,13 +5511,13 @@ async function init() {
5108
5511
  ],
5109
5512
  {
5110
5513
  onCancel: () => {
5111
- console.log(chalk3.yellow("\nSetup cancelled."));
5514
+ console.log(chalk5.yellow("\nSetup cancelled."));
5112
5515
  process.exit(0);
5113
5516
  }
5114
5517
  }
5115
5518
  );
5116
5519
  if (!answers.componentDir || !answers.registry) {
5117
- console.error(chalk3.red("Missing required fields. Run pdfx init again."));
5520
+ console.error(chalk5.red("Missing required fields. Run pdfx init again."));
5118
5521
  process.exit(1);
5119
5522
  }
5120
5523
  const config = {
@@ -5126,54 +5529,54 @@ async function init() {
5126
5529
  const validation = configSchema.safeParse(config);
5127
5530
  if (!validation.success) {
5128
5531
  const issues = validation.error.issues.map((i) => i.message).join(", ");
5129
- console.error(chalk3.red(`Invalid configuration: ${issues}`));
5532
+ console.error(chalk5.red(`Invalid configuration: ${issues}`));
5130
5533
  process.exit(1);
5131
5534
  }
5132
- const spinner = ora3("Creating config and theme files...").start();
5535
+ const spinner = ora4("Creating config and theme files...").start();
5133
5536
  try {
5134
- fs4.writeFileSync(path4.join(process.cwd(), "pdfx.json"), JSON.stringify(config, null, 2));
5537
+ fs7.writeFileSync(path7.join(process.cwd(), "pdfx.json"), JSON.stringify(config, null, 2));
5135
5538
  const presetName = answers.themePreset || "professional";
5136
5539
  const preset = themePresets[presetName];
5137
- const themePath = path4.resolve(process.cwd(), config.theme);
5138
- ensureDir(path4.dirname(themePath));
5139
- fs4.writeFileSync(themePath, generateThemeFile(preset), "utf-8");
5140
- const contextPath = path4.join(path4.dirname(themePath), "pdfx-theme-context.tsx");
5141
- fs4.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
5540
+ const themePath = path7.resolve(process.cwd(), config.theme);
5541
+ ensureDir(path7.dirname(themePath));
5542
+ fs7.writeFileSync(themePath, generateThemeFile(preset), "utf-8");
5543
+ const contextPath = path7.join(path7.dirname(themePath), "pdfx-theme-context.tsx");
5544
+ fs7.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
5142
5545
  spinner.succeed(`Created pdfx.json + ${config.theme} (${presetName} theme)`);
5143
- console.log(chalk3.green("\nSuccess! You can now run:"));
5144
- console.log(chalk3.cyan(" pdfx add heading"));
5145
- console.log(chalk3.dim(`
5146
- Components: ${path4.resolve(process.cwd(), answers.componentDir)}`));
5147
- console.log(chalk3.dim(` Theme: ${path4.resolve(process.cwd(), config.theme)}
5546
+ console.log(chalk5.green("\nSuccess! You can now run:"));
5547
+ console.log(chalk5.cyan(" pdfx add heading"));
5548
+ console.log(chalk5.dim(`
5549
+ Components: ${path7.resolve(process.cwd(), answers.componentDir)}`));
5550
+ console.log(chalk5.dim(` Theme: ${path7.resolve(process.cwd(), config.theme)}
5148
5551
  `));
5149
5552
  } catch (error) {
5150
5553
  spinner.fail("Failed to create config");
5151
5554
  const message = error instanceof Error ? error.message : String(error);
5152
- console.error(chalk3.dim(` ${message}`));
5555
+ console.error(chalk5.dim(` ${message}`));
5153
5556
  process.exit(1);
5154
5557
  }
5155
5558
  }
5156
5559
 
5157
5560
  // src/commands/list.ts
5158
- import path5 from "path";
5159
- import chalk4 from "chalk";
5160
- import ora4 from "ora";
5561
+ import path8 from "path";
5562
+ import chalk6 from "chalk";
5563
+ import ora5 from "ora";
5161
5564
  var FETCH_TIMEOUT_MS2 = 1e4;
5162
5565
  async function list() {
5163
- const configPath = path5.join(process.cwd(), "pdfx.json");
5566
+ const configPath = path8.join(process.cwd(), "pdfx.json");
5164
5567
  if (!checkFileExists(configPath)) {
5165
- console.error(chalk4.red("Error: pdfx.json not found"));
5166
- console.log(chalk4.yellow("Run: pdfx init"));
5568
+ console.error(chalk6.red("Error: pdfx.json not found"));
5569
+ console.log(chalk6.yellow("Run: pdfx init"));
5167
5570
  process.exit(1);
5168
5571
  }
5169
5572
  const raw = readJsonFile(configPath);
5170
5573
  const configResult = configSchema.safeParse(raw);
5171
5574
  if (!configResult.success) {
5172
- console.error(chalk4.red("Invalid pdfx.json"));
5575
+ console.error(chalk6.red("Invalid pdfx.json"));
5173
5576
  process.exit(1);
5174
5577
  }
5175
5578
  const config = configResult.data;
5176
- const spinner = ora4("Fetching component list...").start();
5579
+ const spinner = ora5("Fetching component list...").start();
5177
5580
  try {
5178
5581
  let response;
5179
5582
  try {
@@ -5195,17 +5598,17 @@ async function list() {
5195
5598
  throw new RegistryError("Invalid registry format");
5196
5599
  }
5197
5600
  spinner.stop();
5198
- const targetDir = path5.resolve(process.cwd(), config.componentDir);
5601
+ const targetDir = path8.resolve(process.cwd(), config.componentDir);
5199
5602
  const components = result.data.items.filter((item) => item.type === "registry:ui");
5200
- console.log(chalk4.bold(`
5603
+ console.log(chalk6.bold(`
5201
5604
  Available Components (${components.length})
5202
5605
  `));
5203
5606
  for (const item of components) {
5204
- const componentSubDir = path5.join(targetDir, item.name);
5607
+ const componentSubDir = path8.join(targetDir, item.name);
5205
5608
  const localPath = safePath(componentSubDir, `pdfx-${item.name}.tsx`);
5206
5609
  const installed = checkFileExists(localPath);
5207
- const status = installed ? chalk4.green("[installed]") : chalk4.dim("[not installed]");
5208
- console.log(` ${chalk4.cyan(item.name.padEnd(20))} ${item.description}`);
5610
+ const status = installed ? chalk6.green("[installed]") : chalk6.dim("[not installed]");
5611
+ console.log(` ${chalk6.cyan(item.name.padEnd(20))} ${item.description}`);
5209
5612
  console.log(` ${"".padEnd(20)} ${status}`);
5210
5613
  console.log();
5211
5614
  }
@@ -5217,10 +5620,10 @@ async function list() {
5217
5620
  }
5218
5621
 
5219
5622
  // src/commands/template.ts
5220
- import path6 from "path";
5221
- import chalk5 from "chalk";
5222
- import ora5 from "ora";
5223
- import prompts3 from "prompts";
5623
+ import path9 from "path";
5624
+ import chalk7 from "chalk";
5625
+ import ora6 from "ora";
5626
+ import prompts4 from "prompts";
5224
5627
  function readConfig2(configPath) {
5225
5628
  const raw = readJsonFile(configPath);
5226
5629
  const result = configSchema.safeParse(raw);
@@ -5228,7 +5631,7 @@ function readConfig2(configPath) {
5228
5631
  const issues = result.error.issues.map((i) => i.message).join(", ");
5229
5632
  throw new ConfigError(
5230
5633
  `Invalid pdfx.json: ${issues}`,
5231
- `Fix the config or re-run ${chalk5.cyan("pdfx init")}`
5634
+ `Fix the config or re-run ${chalk7.cyan("pdfx init")}`
5232
5635
  );
5233
5636
  }
5234
5637
  return result.data;
@@ -5295,7 +5698,7 @@ async function fetchComponent2(name, registryUrl) {
5295
5698
  }
5296
5699
  function resolveTemplateImports(content, templateName, config) {
5297
5700
  const cwd = process.cwd();
5298
- const templateSubdir = path6.resolve(
5701
+ const templateSubdir = path9.resolve(
5299
5702
  cwd,
5300
5703
  config.templateDir ?? DEFAULTS.TEMPLATE_DIR,
5301
5704
  templateName
@@ -5303,26 +5706,26 @@ function resolveTemplateImports(content, templateName, config) {
5303
5706
  let result = content.replace(
5304
5707
  /from '\.\.\/\.\.\/components\/pdfx\/([a-z][a-z0-9-]*)\/pdfx-([a-z][a-z0-9-]*)'/g,
5305
5708
  (_match, componentName) => {
5306
- const absCompFile = path6.resolve(
5709
+ const absCompFile = path9.resolve(
5307
5710
  cwd,
5308
5711
  config.componentDir,
5309
5712
  componentName,
5310
5713
  `pdfx-${componentName}`
5311
5714
  );
5312
- let rel = path6.relative(templateSubdir, absCompFile);
5715
+ let rel = path9.relative(templateSubdir, absCompFile);
5313
5716
  if (!rel.startsWith(".")) rel = `./${rel}`;
5314
5717
  return `from '${rel}'`;
5315
5718
  }
5316
5719
  );
5317
5720
  if (config.theme) {
5318
- const absThemePath = path6.resolve(cwd, config.theme).replace(/\.tsx?$/, "");
5319
- let relTheme = path6.relative(templateSubdir, absThemePath);
5721
+ const absThemePath = path9.resolve(cwd, config.theme).replace(/\.tsx?$/, "");
5722
+ let relTheme = path9.relative(templateSubdir, absThemePath);
5320
5723
  if (!relTheme.startsWith(".")) relTheme = `./${relTheme}`;
5321
- const absContextPath = path6.join(
5322
- path6.dirname(path6.resolve(cwd, config.theme)),
5724
+ const absContextPath = path9.join(
5725
+ path9.dirname(path9.resolve(cwd, config.theme)),
5323
5726
  "pdfx-theme-context"
5324
5727
  );
5325
- let relContext = path6.relative(templateSubdir, absContextPath);
5728
+ let relContext = path9.relative(templateSubdir, absContextPath);
5326
5729
  if (!relContext.startsWith(".")) relContext = `./${relContext}`;
5327
5730
  result = result.replace(/from '\.\.\/\.\.\/lib\/pdfx-theme'/g, `from '${relTheme}'`);
5328
5731
  result = result.replace(/from '\.\.\/\.\.\/lib\/pdfx-theme-context'/g, `from '${relContext}'`);
@@ -5331,10 +5734,10 @@ function resolveTemplateImports(content, templateName, config) {
5331
5734
  }
5332
5735
  async function resolveConflict(fileName, currentDecision) {
5333
5736
  if (currentDecision === "overwrite-all") return "overwrite-all";
5334
- const { action } = await prompts3({
5737
+ const { action } = await prompts4({
5335
5738
  type: "select",
5336
5739
  name: "action",
5337
- message: `${chalk5.yellow(fileName)} already exists. What would you like to do?`,
5740
+ message: `${chalk7.yellow(fileName)} already exists. What would you like to do?`,
5338
5741
  choices: [
5339
5742
  { title: "Skip", value: "skip", description: "Keep the existing file unchanged" },
5340
5743
  { title: "Overwrite", value: "overwrite", description: "Replace this file only" },
@@ -5355,14 +5758,14 @@ async function ensurePeerComponents(template, config, force) {
5355
5758
  if (!template.peerComponents || template.peerComponents.length === 0) {
5356
5759
  return { installedPeers, peerWarnings };
5357
5760
  }
5358
- const componentBaseDir = path6.resolve(process.cwd(), config.componentDir);
5761
+ const componentBaseDir = path9.resolve(process.cwd(), config.componentDir);
5359
5762
  for (const componentName of template.peerComponents) {
5360
- const componentDir = path6.join(componentBaseDir, componentName);
5361
- const expectedMain = path6.join(componentDir, `pdfx-${componentName}.tsx`);
5763
+ const componentDir = path9.join(componentBaseDir, componentName);
5764
+ const expectedMain = path9.join(componentDir, `pdfx-${componentName}.tsx`);
5362
5765
  if (checkFileExists(componentDir)) {
5363
5766
  if (!checkFileExists(expectedMain)) {
5364
5767
  peerWarnings.push(
5365
- `${componentName}: directory exists but expected file missing (${path6.basename(expectedMain)})`
5768
+ `${componentName}: directory exists but expected file missing (${path9.basename(expectedMain)})`
5366
5769
  );
5367
5770
  } else {
5368
5771
  peerWarnings.push(
@@ -5373,9 +5776,9 @@ async function ensurePeerComponents(template, config, force) {
5373
5776
  }
5374
5777
  const component = await fetchComponent2(componentName, config.registry);
5375
5778
  ensureDir(componentDir);
5376
- const componentRelDir = path6.join(config.componentDir, component.name);
5779
+ const componentRelDir = path9.join(config.componentDir, component.name);
5377
5780
  for (const file of component.files) {
5378
- const fileName = path6.basename(file.path);
5781
+ const fileName = path9.basename(file.path);
5379
5782
  const filePath = safePath(componentDir, fileName);
5380
5783
  let content = file.content;
5381
5784
  if (config.theme && (content.includes("pdfx-theme") || content.includes("pdfx-theme-context"))) {
@@ -5396,12 +5799,12 @@ async function ensurePeerComponents(template, config, force) {
5396
5799
  async function installTemplate(name, config, force) {
5397
5800
  const template = await fetchTemplate(name, config.registry);
5398
5801
  const peerResult = await ensurePeerComponents(template, config, force);
5399
- const templateBaseDir = path6.resolve(process.cwd(), config.templateDir ?? DEFAULTS.TEMPLATE_DIR);
5400
- const templateDir = path6.join(templateBaseDir, template.name);
5802
+ const templateBaseDir = path9.resolve(process.cwd(), config.templateDir ?? DEFAULTS.TEMPLATE_DIR);
5803
+ const templateDir = path9.join(templateBaseDir, template.name);
5401
5804
  ensureDir(templateDir);
5402
5805
  const filesToWrite = [];
5403
5806
  for (const file of template.files) {
5404
- const fileName = path6.basename(file.path);
5807
+ const fileName = path9.basename(file.path);
5405
5808
  const filePath = safePath(templateDir, fileName);
5406
5809
  let content = file.content;
5407
5810
  if (/\.(tsx?|jsx?)$/.test(fileName) && content.includes("../../")) {
@@ -5414,7 +5817,7 @@ async function installTemplate(name, config, force) {
5414
5817
  const resolved = [];
5415
5818
  for (const file of filesToWrite) {
5416
5819
  if (checkFileExists(file.filePath)) {
5417
- const decision = await resolveConflict(path6.basename(file.filePath), globalDecision);
5820
+ const decision = await resolveConflict(path9.basename(file.filePath), globalDecision);
5418
5821
  if (decision === "overwrite-all") {
5419
5822
  globalDecision = "overwrite-all";
5420
5823
  }
@@ -5427,7 +5830,7 @@ async function installTemplate(name, config, force) {
5427
5830
  if (!file.skip) {
5428
5831
  writeFile(file.filePath, file.content);
5429
5832
  } else {
5430
- console.log(chalk5.dim(` skipped ${path6.basename(file.filePath)}`));
5833
+ console.log(chalk7.dim(` skipped ${path9.basename(file.filePath)}`));
5431
5834
  }
5432
5835
  }
5433
5836
  } else {
@@ -5436,37 +5839,37 @@ async function installTemplate(name, config, force) {
5436
5839
  }
5437
5840
  }
5438
5841
  if (template.peerComponents && template.peerComponents.length > 0) {
5439
- const componentBaseDir = path6.resolve(process.cwd(), config.componentDir);
5842
+ const componentBaseDir = path9.resolve(process.cwd(), config.componentDir);
5440
5843
  const missing = [];
5441
5844
  for (const comp of template.peerComponents) {
5442
- const compDir = path6.join(componentBaseDir, comp);
5845
+ const compDir = path9.join(componentBaseDir, comp);
5443
5846
  if (!checkFileExists(compDir)) {
5444
5847
  missing.push(comp);
5445
5848
  }
5446
5849
  }
5447
5850
  if (missing.length > 0) {
5448
5851
  console.log();
5449
- console.log(chalk5.yellow(" Missing peer components:"));
5852
+ console.log(chalk7.yellow(" Missing peer components:"));
5450
5853
  for (const comp of missing) {
5451
- console.log(chalk5.dim(` ${comp} \u2192 run: ${chalk5.cyan(`pdfx add ${comp}`)}`));
5854
+ console.log(chalk7.dim(` ${comp} \u2192 run: ${chalk7.cyan(`pdfx add ${comp}`)}`));
5452
5855
  }
5453
5856
  }
5454
5857
  }
5455
5858
  if (config.theme) {
5456
- const absThemePath = path6.resolve(process.cwd(), config.theme);
5457
- const contextPath = path6.join(path6.dirname(absThemePath), "pdfx-theme-context.tsx");
5859
+ const absThemePath = path9.resolve(process.cwd(), config.theme);
5860
+ const contextPath = path9.join(path9.dirname(absThemePath), "pdfx-theme-context.tsx");
5458
5861
  if (!checkFileExists(contextPath)) {
5459
- ensureDir(path6.dirname(contextPath));
5862
+ ensureDir(path9.dirname(contextPath));
5460
5863
  writeFile(contextPath, generateThemeContextFile());
5461
5864
  }
5462
5865
  }
5463
5866
  return peerResult;
5464
5867
  }
5465
5868
  async function templateAdd(names, options = {}) {
5466
- const configPath = path6.join(process.cwd(), "pdfx.json");
5869
+ const configPath = path9.join(process.cwd(), "pdfx.json");
5467
5870
  if (!checkFileExists(configPath)) {
5468
- console.error(chalk5.red("Error: pdfx.json not found"));
5469
- console.log(chalk5.yellow("Run: pdfx init"));
5871
+ console.error(chalk7.red("Error: pdfx.json not found"));
5872
+ console.log(chalk7.yellow("Run: pdfx init"));
5470
5873
  process.exit(1);
5471
5874
  }
5472
5875
  let config;
@@ -5474,11 +5877,11 @@ async function templateAdd(names, options = {}) {
5474
5877
  config = readConfig2(configPath);
5475
5878
  } catch (error) {
5476
5879
  if (error instanceof ConfigError) {
5477
- console.error(chalk5.red(error.message));
5478
- if (error.suggestion) console.log(chalk5.yellow(` Hint: ${error.suggestion}`));
5880
+ console.error(chalk7.red(error.message));
5881
+ if (error.suggestion) console.log(chalk7.yellow(` Hint: ${error.suggestion}`));
5479
5882
  } else {
5480
5883
  const message = error instanceof Error ? error.message : String(error);
5481
- console.error(chalk5.red(message));
5884
+ console.error(chalk7.red(message));
5482
5885
  }
5483
5886
  process.exit(1);
5484
5887
  }
@@ -5487,24 +5890,24 @@ async function templateAdd(names, options = {}) {
5487
5890
  for (const templateName of names) {
5488
5891
  const nameResult = componentNameSchema.safeParse(templateName);
5489
5892
  if (!nameResult.success) {
5490
- console.error(chalk5.red(`Invalid template name: "${templateName}"`));
5893
+ console.error(chalk7.red(`Invalid template name: "${templateName}"`));
5491
5894
  console.log(
5492
- chalk5.dim(' Names must be lowercase alphanumeric with hyphens (e.g., "invoice-classic")')
5895
+ chalk7.dim(' Names must be lowercase alphanumeric with hyphens (e.g., "invoice-classic")')
5493
5896
  );
5494
5897
  failed.push(templateName);
5495
5898
  continue;
5496
5899
  }
5497
- const spinner = ora5(`Adding template ${templateName}...`).start();
5900
+ const spinner = ora6(`Adding template ${templateName}...`).start();
5498
5901
  try {
5499
5902
  const result = await installTemplate(templateName, config, force);
5500
- spinner.succeed(`Added template ${chalk5.cyan(templateName)}`);
5903
+ spinner.succeed(`Added template ${chalk7.cyan(templateName)}`);
5501
5904
  if (result.installedPeers.length > 0) {
5502
5905
  console.log(
5503
- chalk5.green(` Installed required components: ${result.installedPeers.join(", ")}`)
5906
+ chalk7.green(` Installed required components: ${result.installedPeers.join(", ")}`)
5504
5907
  );
5505
5908
  }
5506
5909
  for (const warning of result.peerWarnings) {
5507
- console.log(chalk5.yellow(` Warning: ${warning}`));
5910
+ console.log(chalk7.yellow(` Warning: ${warning}`));
5508
5911
  }
5509
5912
  } catch (error) {
5510
5913
  if (error instanceof ValidationError && error.message.includes("Cancelled")) {
@@ -5513,24 +5916,24 @@ async function templateAdd(names, options = {}) {
5513
5916
  } else if (error instanceof NetworkError || error instanceof RegistryError || error instanceof ValidationError) {
5514
5917
  spinner.fail(error.message);
5515
5918
  if (error.suggestion) {
5516
- console.log(chalk5.dim(` Hint: ${error.suggestion}`));
5919
+ console.log(chalk7.dim(` Hint: ${error.suggestion}`));
5517
5920
  }
5518
5921
  } else {
5519
5922
  spinner.fail(`Failed to add template ${templateName}`);
5520
5923
  const message = error instanceof Error ? error.message : String(error);
5521
- console.error(chalk5.dim(` ${message}`));
5924
+ console.error(chalk7.dim(` ${message}`));
5522
5925
  }
5523
5926
  failed.push(templateName);
5524
5927
  }
5525
5928
  }
5526
5929
  console.log();
5527
5930
  if (failed.length > 0) {
5528
- console.log(chalk5.yellow(`Failed: ${failed.join(", ")}`));
5931
+ console.log(chalk7.yellow(`Failed: ${failed.join(", ")}`));
5529
5932
  }
5530
5933
  if (failed.length < names.length) {
5531
- const resolvedDir = path6.resolve(process.cwd(), config.templateDir ?? DEFAULTS.TEMPLATE_DIR);
5532
- console.log(chalk5.green("Done!"));
5533
- console.log(chalk5.dim(`Templates installed to: ${resolvedDir}
5934
+ const resolvedDir = path9.resolve(process.cwd(), config.templateDir ?? DEFAULTS.TEMPLATE_DIR);
5935
+ console.log(chalk7.green("Done!"));
5936
+ console.log(chalk7.dim(`Templates installed to: ${resolvedDir}
5534
5937
  `));
5535
5938
  }
5536
5939
  if (failed.length > 0) {
@@ -5538,20 +5941,20 @@ async function templateAdd(names, options = {}) {
5538
5941
  }
5539
5942
  }
5540
5943
  async function templateList() {
5541
- const configPath = path6.join(process.cwd(), "pdfx.json");
5944
+ const configPath = path9.join(process.cwd(), "pdfx.json");
5542
5945
  if (!checkFileExists(configPath)) {
5543
- console.error(chalk5.red("Error: pdfx.json not found"));
5544
- console.log(chalk5.yellow("Run: pdfx init"));
5946
+ console.error(chalk7.red("Error: pdfx.json not found"));
5947
+ console.log(chalk7.yellow("Run: pdfx init"));
5545
5948
  process.exit(1);
5546
5949
  }
5547
5950
  const raw = readJsonFile(configPath);
5548
5951
  const configResult = configSchema.safeParse(raw);
5549
5952
  if (!configResult.success) {
5550
- console.error(chalk5.red("Invalid pdfx.json"));
5953
+ console.error(chalk7.red("Invalid pdfx.json"));
5551
5954
  process.exit(1);
5552
5955
  }
5553
5956
  const config = configResult.data;
5554
- const spinner = ora5("Fetching template list...").start();
5957
+ const spinner = ora6("Fetching template list...").start();
5555
5958
  try {
5556
5959
  let response;
5557
5960
  try {
@@ -5575,28 +5978,28 @@ async function templateList() {
5575
5978
  spinner.stop();
5576
5979
  const templates = result.data.items.filter((item) => item.type === "registry:template");
5577
5980
  if (templates.length === 0) {
5578
- console.log(chalk5.dim("\n No templates available in the registry.\n"));
5981
+ console.log(chalk7.dim("\n No templates available in the registry.\n"));
5579
5982
  return;
5580
5983
  }
5581
- const templateBaseDir = path6.resolve(
5984
+ const templateBaseDir = path9.resolve(
5582
5985
  process.cwd(),
5583
5986
  config.templateDir ?? DEFAULTS.TEMPLATE_DIR
5584
5987
  );
5585
- console.log(chalk5.bold(`
5988
+ console.log(chalk7.bold(`
5586
5989
  Available Templates (${templates.length})
5587
5990
  `));
5588
5991
  for (const item of templates) {
5589
- const templateDir = path6.join(templateBaseDir, item.name);
5992
+ const templateDir = path9.join(templateBaseDir, item.name);
5590
5993
  const installed = checkFileExists(templateDir);
5591
- const status = installed ? chalk5.green("[installed]") : chalk5.dim("[not installed]");
5592
- console.log(` ${chalk5.cyan(item.name.padEnd(22))} ${item.description ?? ""}`);
5994
+ const status = installed ? chalk7.green("[installed]") : chalk7.dim("[not installed]");
5995
+ console.log(` ${chalk7.cyan(item.name.padEnd(22))} ${item.description ?? ""}`);
5593
5996
  console.log(` ${"".padEnd(22)} ${status}`);
5594
5997
  if (item.peerComponents && item.peerComponents.length > 0) {
5595
- console.log(chalk5.dim(` ${"".padEnd(22)} requires: ${item.peerComponents.join(", ")}`));
5998
+ console.log(chalk7.dim(` ${"".padEnd(22)} requires: ${item.peerComponents.join(", ")}`));
5596
5999
  }
5597
6000
  console.log();
5598
6001
  }
5599
- console.log(chalk5.dim(` Install with: ${chalk5.cyan("pdfx template add <template-name>")}
6002
+ console.log(chalk7.dim(` Install with: ${chalk7.cyan("pdfx template add <template-name>")}
5600
6003
  `));
5601
6004
  } catch (error) {
5602
6005
  const message = error instanceof Error ? error.message : String(error);
@@ -5606,15 +6009,15 @@ async function templateList() {
5606
6009
  }
5607
6010
 
5608
6011
  // src/commands/theme.ts
5609
- import fs5 from "fs";
5610
- import path7 from "path";
5611
- import chalk6 from "chalk";
5612
- import ora6 from "ora";
5613
- import prompts4 from "prompts";
6012
+ import fs8 from "fs";
6013
+ import path10 from "path";
6014
+ import chalk8 from "chalk";
6015
+ import ora7 from "ora";
6016
+ import prompts5 from "prompts";
5614
6017
  import ts from "typescript";
5615
6018
  async function themeInit() {
5616
- console.log(chalk6.bold.cyan("\n PDFx Theme Setup\n"));
5617
- const answers = await prompts4(
6019
+ console.log(chalk8.bold.cyan("\n PDFx Theme Setup\n"));
6020
+ const answers = await prompts5(
5618
6021
  [
5619
6022
  {
5620
6023
  type: "select",
@@ -5648,47 +6051,47 @@ async function themeInit() {
5648
6051
  ],
5649
6052
  {
5650
6053
  onCancel: () => {
5651
- console.log(chalk6.yellow("\nTheme setup cancelled."));
6054
+ console.log(chalk8.yellow("\nTheme setup cancelled."));
5652
6055
  process.exit(0);
5653
6056
  }
5654
6057
  }
5655
6058
  );
5656
6059
  if (!answers.preset || !answers.themePath) {
5657
- console.error(chalk6.red("Missing required fields."));
6060
+ console.error(chalk8.red("Missing required fields."));
5658
6061
  process.exit(1);
5659
6062
  }
5660
6063
  const presetName = answers.preset;
5661
6064
  const themePath = answers.themePath;
5662
6065
  const preset = themePresets[presetName];
5663
- const spinner = ora6(`Scaffolding ${presetName} theme...`).start();
6066
+ const spinner = ora7(`Scaffolding ${presetName} theme...`).start();
5664
6067
  try {
5665
- const absThemePath = path7.resolve(process.cwd(), themePath);
5666
- ensureDir(path7.dirname(absThemePath));
5667
- fs5.writeFileSync(absThemePath, generateThemeFile(preset), "utf-8");
5668
- const contextPath = path7.join(path7.dirname(absThemePath), "pdfx-theme-context.tsx");
5669
- fs5.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
6068
+ const absThemePath = path10.resolve(process.cwd(), themePath);
6069
+ ensureDir(path10.dirname(absThemePath));
6070
+ fs8.writeFileSync(absThemePath, generateThemeFile(preset), "utf-8");
6071
+ const contextPath = path10.join(path10.dirname(absThemePath), "pdfx-theme-context.tsx");
6072
+ fs8.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
5670
6073
  spinner.succeed(`Created ${themePath} with ${presetName} theme`);
5671
- const configPath = path7.join(process.cwd(), "pdfx.json");
5672
- if (fs5.existsSync(configPath)) {
6074
+ const configPath = path10.join(process.cwd(), "pdfx.json");
6075
+ if (fs8.existsSync(configPath)) {
5673
6076
  try {
5674
6077
  const rawConfig = readJsonFile(configPath);
5675
6078
  const result = configSchema.safeParse(rawConfig);
5676
6079
  if (result.success) {
5677
6080
  const updatedConfig = { ...result.data, theme: themePath };
5678
- fs5.writeFileSync(configPath, JSON.stringify(updatedConfig, null, 2), "utf-8");
5679
- console.log(chalk6.green(" Updated pdfx.json with theme path"));
6081
+ fs8.writeFileSync(configPath, JSON.stringify(updatedConfig, null, 2), "utf-8");
6082
+ console.log(chalk8.green(" Updated pdfx.json with theme path"));
5680
6083
  }
5681
6084
  } catch {
5682
- console.log(chalk6.yellow(' Could not update pdfx.json \u2014 add "theme" field manually'));
6085
+ console.log(chalk8.yellow(' Could not update pdfx.json \u2014 add "theme" field manually'));
5683
6086
  }
5684
6087
  }
5685
- console.log(chalk6.dim(`
6088
+ console.log(chalk8.dim(`
5686
6089
  Edit ${themePath} to customize your theme.
5687
6090
  `));
5688
6091
  } catch (error) {
5689
6092
  spinner.fail("Failed to create theme file");
5690
6093
  const message = error instanceof Error ? error.message : String(error);
5691
- console.error(chalk6.dim(` ${message}`));
6094
+ console.error(chalk8.dim(` ${message}`));
5692
6095
  process.exit(1);
5693
6096
  }
5694
6097
  }
@@ -5696,54 +6099,54 @@ async function themeSwitch(presetName) {
5696
6099
  const validPresets = Object.keys(themePresets);
5697
6100
  if (!validPresets.includes(presetName)) {
5698
6101
  console.error(
5699
- chalk6.red(`Invalid preset: "${presetName}". Valid presets: ${validPresets.join(", ")}`)
6102
+ chalk8.red(`Invalid preset: "${presetName}". Valid presets: ${validPresets.join(", ")}`)
5700
6103
  );
5701
6104
  process.exit(1);
5702
6105
  }
5703
6106
  const validatedPreset = presetName;
5704
- const configPath = path7.join(process.cwd(), "pdfx.json");
5705
- if (!fs5.existsSync(configPath)) {
5706
- console.error(chalk6.red('No pdfx.json found. Run "pdfx init" first.'));
6107
+ const configPath = path10.join(process.cwd(), "pdfx.json");
6108
+ if (!fs8.existsSync(configPath)) {
6109
+ console.error(chalk8.red('No pdfx.json found. Run "pdfx init" first.'));
5707
6110
  process.exit(1);
5708
6111
  }
5709
6112
  const rawConfig = readJsonFile(configPath);
5710
6113
  const result = configSchema.safeParse(rawConfig);
5711
6114
  if (!result.success) {
5712
- console.error(chalk6.red("Invalid pdfx.json configuration."));
6115
+ console.error(chalk8.red("Invalid pdfx.json configuration."));
5713
6116
  process.exit(1);
5714
6117
  }
5715
6118
  const config = result.data;
5716
6119
  if (!config.theme) {
5717
6120
  console.error(
5718
- chalk6.red('No theme path in pdfx.json. Run "pdfx theme init" to set up theming.')
6121
+ chalk8.red('No theme path in pdfx.json. Run "pdfx theme init" to set up theming.')
5719
6122
  );
5720
6123
  process.exit(1);
5721
6124
  }
5722
- const answer = await prompts4({
6125
+ const answer = await prompts5({
5723
6126
  type: "confirm",
5724
6127
  name: "confirm",
5725
6128
  message: `This will overwrite ${config.theme} with the ${validatedPreset} preset. Continue?`,
5726
6129
  initial: false
5727
6130
  });
5728
6131
  if (!answer.confirm) {
5729
- console.log(chalk6.yellow("Cancelled."));
6132
+ console.log(chalk8.yellow("Cancelled."));
5730
6133
  return;
5731
6134
  }
5732
- const spinner = ora6(`Switching to ${validatedPreset} theme...`).start();
6135
+ const spinner = ora7(`Switching to ${validatedPreset} theme...`).start();
5733
6136
  try {
5734
6137
  const preset = themePresets[validatedPreset];
5735
- const absThemePath = path7.resolve(process.cwd(), config.theme);
5736
- fs5.writeFileSync(absThemePath, generateThemeFile(preset), "utf-8");
5737
- const contextPath = path7.join(path7.dirname(absThemePath), "pdfx-theme-context.tsx");
5738
- if (!fs5.existsSync(contextPath)) {
5739
- ensureDir(path7.dirname(contextPath));
5740
- fs5.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
6138
+ const absThemePath = path10.resolve(process.cwd(), config.theme);
6139
+ fs8.writeFileSync(absThemePath, generateThemeFile(preset), "utf-8");
6140
+ const contextPath = path10.join(path10.dirname(absThemePath), "pdfx-theme-context.tsx");
6141
+ if (!fs8.existsSync(contextPath)) {
6142
+ ensureDir(path10.dirname(contextPath));
6143
+ fs8.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
5741
6144
  }
5742
6145
  spinner.succeed(`Switched to ${validatedPreset} theme`);
5743
6146
  } catch (error) {
5744
6147
  spinner.fail("Failed to switch theme");
5745
6148
  const message = error instanceof Error ? error.message : String(error);
5746
- console.error(chalk6.dim(` ${message}`));
6149
+ console.error(chalk8.dim(` ${message}`));
5747
6150
  process.exit(1);
5748
6151
  }
5749
6152
  }
@@ -5785,7 +6188,7 @@ function toPlainValue(node) {
5785
6188
  return void 0;
5786
6189
  }
5787
6190
  function parseThemeObject(themePath) {
5788
- const content = fs5.readFileSync(themePath, "utf-8");
6191
+ const content = fs8.readFileSync(themePath, "utf-8");
5789
6192
  const sourceFile = ts.createSourceFile(
5790
6193
  themePath,
5791
6194
  content,
@@ -5811,29 +6214,29 @@ function parseThemeObject(themePath) {
5811
6214
  throw new Error("No exported `theme` object found.");
5812
6215
  }
5813
6216
  async function themeValidate() {
5814
- const configPath = path7.join(process.cwd(), "pdfx.json");
5815
- if (!fs5.existsSync(configPath)) {
5816
- console.error(chalk6.red('No pdfx.json found. Run "pdfx init" first.'));
6217
+ const configPath = path10.join(process.cwd(), "pdfx.json");
6218
+ if (!fs8.existsSync(configPath)) {
6219
+ console.error(chalk8.red('No pdfx.json found. Run "pdfx init" first.'));
5817
6220
  process.exit(1);
5818
6221
  }
5819
6222
  const rawConfig = readJsonFile(configPath);
5820
6223
  const configResult = configSchema.safeParse(rawConfig);
5821
6224
  if (!configResult.success) {
5822
- console.error(chalk6.red("Invalid pdfx.json configuration."));
6225
+ console.error(chalk8.red("Invalid pdfx.json configuration."));
5823
6226
  process.exit(1);
5824
6227
  }
5825
6228
  if (!configResult.data.theme) {
5826
6229
  console.error(
5827
- chalk6.red('No theme path in pdfx.json. Run "pdfx theme init" to set up theming.')
6230
+ chalk8.red('No theme path in pdfx.json. Run "pdfx theme init" to set up theming.')
5828
6231
  );
5829
6232
  process.exit(1);
5830
6233
  }
5831
- const absThemePath = path7.resolve(process.cwd(), configResult.data.theme);
5832
- if (!fs5.existsSync(absThemePath)) {
5833
- console.error(chalk6.red(`Theme file not found: ${configResult.data.theme}`));
6234
+ const absThemePath = path10.resolve(process.cwd(), configResult.data.theme);
6235
+ if (!fs8.existsSync(absThemePath)) {
6236
+ console.error(chalk8.red(`Theme file not found: ${configResult.data.theme}`));
5834
6237
  process.exit(1);
5835
6238
  }
5836
- const spinner = ora6("Validating theme file...").start();
6239
+ const spinner = ora7("Validating theme file...").start();
5837
6240
  try {
5838
6241
  const parsedTheme = parseThemeObject(absThemePath);
5839
6242
  const result = themeSchema.safeParse(parsedTheme);
@@ -5843,13 +6246,13 @@ async function themeValidate() {
5843
6246
  process.exit(1);
5844
6247
  }
5845
6248
  spinner.succeed("Theme file is valid");
5846
- console.log(chalk6.dim(`
6249
+ console.log(chalk8.dim(`
5847
6250
  Validated: ${configResult.data.theme}
5848
6251
  `));
5849
6252
  } catch (error) {
5850
6253
  spinner.fail("Failed to validate theme");
5851
6254
  const message = error instanceof Error ? error.message : String(error);
5852
- console.error(chalk6.dim(` ${message}`));
6255
+ console.error(chalk8.dim(` ${message}`));
5853
6256
  process.exit(1);
5854
6257
  }
5855
6258
  }