@akii09/pdfx-cli 0.1.2 → 0.1.4

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 +728 -235
  2. package/package.json +4 -1
package/dist/index.js CHANGED
@@ -6,10 +6,13 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/index.ts
9
+ import { readFileSync } from "fs";
10
+ import { join } from "path";
11
+ import { fileURLToPath } from "url";
9
12
  import { Command } from "commander";
10
13
 
11
14
  // src/commands/add.ts
12
- import path2 from "path";
15
+ import path3 from "path";
13
16
 
14
17
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
15
18
  var external_exports = {};
@@ -489,8 +492,8 @@ function getErrorMap() {
489
492
 
490
493
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
491
494
  var makeIssue = (params) => {
492
- const { data, path: path8, errorMaps, issueData } = params;
493
- const fullPath = [...path8, ...issueData.path || []];
495
+ const { data, path: path11, errorMaps, issueData } = params;
496
+ const fullPath = [...path11, ...issueData.path || []];
494
497
  const fullIssue = {
495
498
  ...issueData,
496
499
  path: fullPath
@@ -606,11 +609,11 @@ var errorUtil;
606
609
 
607
610
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
608
611
  var ParseInputLazyPath = class {
609
- constructor(parent, value, path8, key) {
612
+ constructor(parent, value, path11, key) {
610
613
  this._cachedPath = [];
611
614
  this.parent = parent;
612
615
  this.data = value;
613
- this._path = path8;
616
+ this._path = path11;
614
617
  this._key = key;
615
618
  }
616
619
  get path() {
@@ -989,11 +992,11 @@ function datetimeRegex(args) {
989
992
  regex = `${regex}(${opts.join("|")})`;
990
993
  return new RegExp(`^${regex}$`);
991
994
  }
992
- function isValidIP(ip, version) {
993
- if ((version === "v4" || !version) && ipv4Regex.test(ip)) {
995
+ function isValidIP(ip, version2) {
996
+ if ((version2 === "v4" || !version2) && ipv4Regex.test(ip)) {
994
997
  return true;
995
998
  }
996
- if ((version === "v6" || !version) && ipv6Regex.test(ip)) {
999
+ if ((version2 === "v6" || !version2) && ipv6Regex.test(ip)) {
997
1000
  return true;
998
1001
  }
999
1002
  return false;
@@ -1020,11 +1023,11 @@ function isValidJWT(jwt, alg) {
1020
1023
  return false;
1021
1024
  }
1022
1025
  }
1023
- function isValidCidr(ip, version) {
1024
- if ((version === "v4" || !version) && ipv4CidrRegex.test(ip)) {
1026
+ function isValidCidr(ip, version2) {
1027
+ if ((version2 === "v4" || !version2) && ipv4CidrRegex.test(ip)) {
1025
1028
  return true;
1026
1029
  }
1027
- if ((version === "v6" || !version) && ipv6CidrRegex.test(ip)) {
1030
+ if ((version2 === "v6" || !version2) && ipv6CidrRegex.test(ip)) {
1028
1031
  return true;
1029
1032
  }
1030
1033
  return false;
@@ -4461,30 +4464,156 @@ import chalk from "chalk";
4461
4464
  import ora from "ora";
4462
4465
  import prompts from "prompts";
4463
4466
 
4464
- // src/utils/file-system.ts
4465
- import fs from "fs";
4467
+ // src/utils/dependency-validator.ts
4468
+ import fs2 from "fs";
4466
4469
  import path from "path";
4470
+ import semver from "semver";
4471
+
4472
+ // src/utils/read-json.ts
4473
+ import fs from "fs";
4474
+ function readJsonFile(filePath) {
4475
+ const raw = fs.readFileSync(filePath, "utf-8");
4476
+ try {
4477
+ return JSON.parse(raw);
4478
+ } catch (error) {
4479
+ const details = error instanceof Error ? error.message : String(error);
4480
+ throw new ConfigError(`Invalid JSON in ${filePath}: ${details}`);
4481
+ }
4482
+ }
4483
+
4484
+ // src/utils/dependency-validator.ts
4485
+ var REQUIRED_VERSIONS = {
4486
+ "@react-pdf/renderer": ">=3.0.0",
4487
+ react: ">=16.8.0",
4488
+ node: ">=24.0.0"
4489
+ };
4490
+ function getPackageJson(cwd = process.cwd()) {
4491
+ const pkgPath = path.join(cwd, "package.json");
4492
+ if (!fs2.existsSync(pkgPath)) {
4493
+ return null;
4494
+ }
4495
+ return readJsonFile(pkgPath);
4496
+ }
4497
+ function getInstalledVersion(packageName, cwd = process.cwd()) {
4498
+ const pkg = getPackageJson(cwd);
4499
+ if (!pkg) return null;
4500
+ const deps = {
4501
+ ...pkg.dependencies,
4502
+ ...pkg.devDependencies
4503
+ };
4504
+ const version2 = deps[packageName];
4505
+ if (!version2) return null;
4506
+ return semver.clean(version2) || semver.coerce(version2)?.version || null;
4507
+ }
4508
+ function validateReactPdfRenderer(cwd = process.cwd()) {
4509
+ const version2 = getInstalledVersion("@react-pdf/renderer", cwd);
4510
+ const required = REQUIRED_VERSIONS["@react-pdf/renderer"];
4511
+ if (!version2) {
4512
+ return {
4513
+ valid: false,
4514
+ installed: false,
4515
+ requiredVersion: required,
4516
+ message: "@react-pdf/renderer is not installed"
4517
+ };
4518
+ }
4519
+ const isCompatible = semver.satisfies(version2, required);
4520
+ return {
4521
+ valid: isCompatible,
4522
+ installed: true,
4523
+ currentVersion: version2,
4524
+ requiredVersion: required,
4525
+ message: isCompatible ? "@react-pdf/renderer version is compatible" : `@react-pdf/renderer version ${version2} does not meet requirement ${required}`
4526
+ };
4527
+ }
4528
+ function validateReact(cwd = process.cwd()) {
4529
+ const version2 = getInstalledVersion("react", cwd);
4530
+ const required = REQUIRED_VERSIONS.react;
4531
+ if (!version2) {
4532
+ return {
4533
+ valid: false,
4534
+ installed: false,
4535
+ requiredVersion: required,
4536
+ message: "React is not installed"
4537
+ };
4538
+ }
4539
+ const isCompatible = semver.satisfies(version2, required);
4540
+ return {
4541
+ valid: isCompatible,
4542
+ installed: true,
4543
+ currentVersion: version2,
4544
+ requiredVersion: required,
4545
+ message: isCompatible ? "React version is compatible" : `React version ${version2} does not meet requirement ${required}`
4546
+ };
4547
+ }
4548
+ function validateNodeVersion() {
4549
+ const version2 = process.version;
4550
+ const required = REQUIRED_VERSIONS.node;
4551
+ const cleanVersion = semver.clean(version2);
4552
+ if (!cleanVersion) {
4553
+ return {
4554
+ valid: false,
4555
+ installed: true,
4556
+ currentVersion: version2,
4557
+ requiredVersion: required,
4558
+ message: `Unable to parse Node.js version: ${version2}`
4559
+ };
4560
+ }
4561
+ const isCompatible = semver.satisfies(cleanVersion, required);
4562
+ return {
4563
+ valid: isCompatible,
4564
+ installed: true,
4565
+ currentVersion: cleanVersion,
4566
+ requiredVersion: required,
4567
+ message: isCompatible ? "Node.js version is compatible" : `Node.js version ${cleanVersion} does not meet requirement ${required}`
4568
+ };
4569
+ }
4570
+ function validateTypeScript(cwd = process.cwd()) {
4571
+ const tsVersion = getInstalledVersion("typescript", cwd);
4572
+ if (!tsVersion) {
4573
+ return null;
4574
+ }
4575
+ const typesInstalled = getInstalledVersion("@types/react-pdf", cwd);
4576
+ return {
4577
+ valid: !!typesInstalled,
4578
+ installed: !!typesInstalled,
4579
+ currentVersion: typesInstalled || void 0,
4580
+ requiredVersion: "latest",
4581
+ message: typesInstalled ? "TypeScript types for @react-pdf/renderer are installed" : "@types/react-pdf is recommended for TypeScript projects"
4582
+ };
4583
+ }
4584
+ function validateDependencies(cwd = process.cwd()) {
4585
+ return {
4586
+ reactPdfRenderer: validateReactPdfRenderer(cwd),
4587
+ react: validateReact(cwd),
4588
+ nodeJs: validateNodeVersion(),
4589
+ typescript: validateTypeScript(cwd) || void 0
4590
+ };
4591
+ }
4592
+
4593
+ // src/utils/file-system.ts
4594
+ import fs3 from "fs";
4595
+ import path2 from "path";
4467
4596
  function ensureDir(dir) {
4468
- if (!fs.existsSync(dir)) {
4469
- fs.mkdirSync(dir, { recursive: true });
4597
+ if (!fs3.existsSync(dir)) {
4598
+ fs3.mkdirSync(dir, { recursive: true });
4470
4599
  }
4471
4600
  }
4472
4601
  function writeFile(filePath, content) {
4473
- const dir = path.dirname(filePath);
4602
+ const dir = path2.dirname(filePath);
4474
4603
  ensureDir(dir);
4475
- fs.writeFileSync(filePath, content, "utf-8");
4604
+ fs3.writeFileSync(filePath, content, "utf-8");
4476
4605
  }
4477
4606
  function checkFileExists(filePath) {
4478
- return fs.existsSync(filePath);
4607
+ return fs3.existsSync(filePath);
4479
4608
  }
4480
4609
  function normalizePath(...segments) {
4481
- return path.resolve(...segments);
4610
+ return path2.resolve(...segments);
4482
4611
  }
4483
4612
  function isPathWithinDirectory(resolvedPath, targetDir) {
4484
4613
  const normalizedTarget = normalizePath(targetDir);
4485
4614
  const normalizedResolved = normalizePath(resolvedPath);
4486
4615
  if (normalizedResolved === normalizedTarget) return true;
4487
- const prefix = normalizedTarget.endsWith(path.sep) ? normalizedTarget : normalizedTarget + path.sep;
4616
+ const prefix = normalizedTarget.endsWith(path2.sep) ? normalizedTarget : normalizedTarget + path2.sep;
4488
4617
  return normalizedResolved.startsWith(prefix);
4489
4618
  }
4490
4619
  function safePath(targetDir, fileName) {
@@ -4754,18 +4883,6 @@ export function useSafeMemo<T>(factory: () => T, deps: DependencyList): T {
4754
4883
  `;
4755
4884
  }
4756
4885
 
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
4886
  // src/commands/add.ts
4770
4887
  function readConfig(configPath) {
4771
4888
  const raw = readJsonFile(configPath);
@@ -4787,7 +4904,9 @@ async function fetchComponent(name, registryUrl) {
4787
4904
  } catch (err) {
4788
4905
  const isTimeout = err instanceof Error && err.name === "TimeoutError";
4789
4906
  throw new NetworkError(
4790
- isTimeout ? "Registry request timed out" : `Could not reach ${registryUrl}`
4907
+ isTimeout ? `Registry request timed out after 10 seconds.
4908
+ ${chalk.dim("Check your internet connection or try again later.")}` : `Could not reach registry at ${registryUrl}
4909
+ ${chalk.dim("Verify the URL is correct and you have internet access.")}`
4791
4910
  );
4792
4911
  }
4793
4912
  if (!response.ok) {
@@ -4810,15 +4929,15 @@ async function fetchComponent(name, registryUrl) {
4810
4929
  return result.data;
4811
4930
  }
4812
4931
  function resolveThemeImport(componentDir, themePath, fileContent) {
4813
- const absComponentDir = path2.resolve(process.cwd(), componentDir);
4814
- const absThemePath = path2.resolve(process.cwd(), themePath);
4932
+ const absComponentDir = path3.resolve(process.cwd(), componentDir);
4933
+ const absThemePath = path3.resolve(process.cwd(), themePath);
4815
4934
  const themeImportTarget = absThemePath.replace(/\.tsx?$/, "");
4816
- let relativePath = path2.relative(absComponentDir, themeImportTarget);
4935
+ let relativePath = path3.relative(absComponentDir, themeImportTarget);
4817
4936
  if (!relativePath.startsWith(".")) {
4818
4937
  relativePath = `./${relativePath}`;
4819
4938
  }
4820
- const absContextPath = path2.join(path2.dirname(absThemePath), "pdfx-theme-context");
4821
- let relativeContextPath = path2.relative(absComponentDir, absContextPath);
4939
+ const absContextPath = path3.join(path3.dirname(absThemePath), "pdfx-theme-context");
4940
+ let relativeContextPath = path3.relative(absComponentDir, absContextPath);
4822
4941
  if (!relativeContextPath.startsWith(".")) {
4823
4942
  relativeContextPath = `./${relativeContextPath}`;
4824
4943
  }
@@ -4834,13 +4953,13 @@ function resolveThemeImport(componentDir, themePath, fileContent) {
4834
4953
  }
4835
4954
  async function installComponent(name, config, force) {
4836
4955
  const component = await fetchComponent(name, config.registry);
4837
- const targetDir = path2.resolve(process.cwd(), config.componentDir);
4838
- const componentDir = path2.join(targetDir, component.name);
4956
+ const targetDir = path3.resolve(process.cwd(), config.componentDir);
4957
+ const componentDir = path3.join(targetDir, component.name);
4839
4958
  ensureDir(componentDir);
4840
- const componentRelDir = path2.join(config.componentDir, component.name);
4959
+ const componentRelDir = path3.join(config.componentDir, component.name);
4841
4960
  const filesToWrite = [];
4842
4961
  for (const file of component.files) {
4843
- const fileName = path2.basename(file.path);
4962
+ const fileName = path3.basename(file.path);
4844
4963
  const filePath = safePath(componentDir, fileName);
4845
4964
  let content = file.content;
4846
4965
  if (config.theme && (content.includes("pdfx-theme") || content.includes("pdfx-theme-context"))) {
@@ -4851,7 +4970,7 @@ async function installComponent(name, config, force) {
4851
4970
  if (!force) {
4852
4971
  const existing = filesToWrite.filter((f) => checkFileExists(f.filePath));
4853
4972
  if (existing.length > 0) {
4854
- const fileNames = existing.map((f) => path2.basename(f.filePath)).join(", ");
4973
+ const fileNames = existing.map((f) => path3.basename(f.filePath)).join(", ");
4855
4974
  const { overwrite } = await prompts({
4856
4975
  type: "confirm",
4857
4976
  name: "overwrite",
@@ -4867,17 +4986,41 @@ async function installComponent(name, config, force) {
4867
4986
  writeFile(file.filePath, file.content);
4868
4987
  }
4869
4988
  if (config.theme) {
4870
- const absThemePath = path2.resolve(process.cwd(), config.theme);
4871
- const contextPath = path2.join(path2.dirname(absThemePath), "pdfx-theme-context.tsx");
4989
+ const absThemePath = path3.resolve(process.cwd(), config.theme);
4990
+ const contextPath = path3.join(path3.dirname(absThemePath), "pdfx-theme-context.tsx");
4872
4991
  if (!checkFileExists(contextPath)) {
4873
- ensureDir(path2.dirname(contextPath));
4992
+ ensureDir(path3.dirname(contextPath));
4874
4993
  writeFile(contextPath, generateThemeContextFile());
4875
4994
  }
4876
4995
  }
4877
4996
  return;
4878
4997
  }
4879
4998
  async function add(components, options = {}) {
4880
- const configPath = path2.join(process.cwd(), "pdfx.json");
4999
+ if (!components || components.length === 0) {
5000
+ console.error(chalk.red("Error: Component name required"));
5001
+ console.log(chalk.dim("Usage: pdfx add <component...>"));
5002
+ console.log(chalk.dim("Example: pdfx add heading text table\n"));
5003
+ process.exit(1);
5004
+ }
5005
+ const reactPdfCheck = validateReactPdfRenderer();
5006
+ if (!reactPdfCheck.installed) {
5007
+ console.error(chalk.red("\nError: @react-pdf/renderer is not installed\n"));
5008
+ console.log(chalk.yellow(" PDFx components require @react-pdf/renderer to work.\n"));
5009
+ console.log(chalk.cyan(" Run: pdfx init"));
5010
+ console.log(chalk.dim(" or install manually: npm install @react-pdf/renderer\n"));
5011
+ process.exit(1);
5012
+ }
5013
+ if (!reactPdfCheck.valid) {
5014
+ console.log(
5015
+ chalk.yellow(
5016
+ `
5017
+ \u26A0 Warning: ${reactPdfCheck.message}
5018
+ ${chalk.dim("\u2192")} You may encounter compatibility issues
5019
+ `
5020
+ )
5021
+ );
5022
+ }
5023
+ const configPath = path3.join(process.cwd(), "pdfx.json");
4881
5024
  if (!checkFileExists(configPath)) {
4882
5025
  console.error(chalk.red("Error: pdfx.json not found"));
4883
5026
  console.log(chalk.yellow("Run: pdfx init"));
@@ -4886,6 +5029,9 @@ async function add(components, options = {}) {
4886
5029
  let config;
4887
5030
  try {
4888
5031
  config = readConfig(configPath);
5032
+ if (options.registry) {
5033
+ config = { ...config, registry: options.registry };
5034
+ }
4889
5035
  } catch (error) {
4890
5036
  if (error instanceof ConfigError) {
4891
5037
  console.error(chalk.red(error.message));
@@ -4933,7 +5079,7 @@ async function add(components, options = {}) {
4933
5079
  console.log(chalk.yellow(`Failed to add: ${failed.join(", ")}`));
4934
5080
  }
4935
5081
  if (failed.length < components.length) {
4936
- const resolvedDir = path2.resolve(process.cwd(), config.componentDir);
5082
+ const resolvedDir = path3.resolve(process.cwd(), config.componentDir);
4937
5083
  console.log(chalk.green("Done!"));
4938
5084
  console.log(chalk.dim(`Components installed to: ${resolvedDir}
4939
5085
  `));
@@ -4944,13 +5090,13 @@ async function add(components, options = {}) {
4944
5090
  }
4945
5091
 
4946
5092
  // src/commands/diff.ts
4947
- import fs3 from "fs";
4948
- import path3 from "path";
5093
+ import fs4 from "fs";
5094
+ import path4 from "path";
4949
5095
  import chalk2 from "chalk";
4950
5096
  import ora2 from "ora";
4951
5097
  var FETCH_TIMEOUT_MS = 1e4;
4952
5098
  async function diff(components) {
4953
- const configPath = path3.join(process.cwd(), "pdfx.json");
5099
+ const configPath = path4.join(process.cwd(), "pdfx.json");
4954
5100
  if (!checkFileExists(configPath)) {
4955
5101
  console.error(chalk2.red("Error: pdfx.json not found"));
4956
5102
  console.log(chalk2.yellow("Run: pdfx init"));
@@ -4963,7 +5109,7 @@ async function diff(components) {
4963
5109
  process.exit(1);
4964
5110
  }
4965
5111
  const config = configResult.data;
4966
- const targetDir = path3.resolve(process.cwd(), config.componentDir);
5112
+ const targetDir = path4.resolve(process.cwd(), config.componentDir);
4967
5113
  for (const componentName of components) {
4968
5114
  const nameResult = componentNameSchema.safeParse(componentName);
4969
5115
  if (!nameResult.success) {
@@ -4980,7 +5126,9 @@ async function diff(components) {
4980
5126
  } catch (err) {
4981
5127
  const isTimeout = err instanceof Error && err.name === "TimeoutError";
4982
5128
  throw new NetworkError(
4983
- isTimeout ? "Registry request timed out" : `Could not reach ${config.registry}`
5129
+ isTimeout ? `Registry request timed out after 10 seconds.
5130
+ ${chalk2.dim("Check your internet connection or try again later.")}` : `Could not reach registry at ${config.registry}
5131
+ ${chalk2.dim("Verify the URL is correct and you have internet access.")}`
4984
5132
  );
4985
5133
  }
4986
5134
  if (!response.ok) {
@@ -4995,17 +5143,17 @@ async function diff(components) {
4995
5143
  }
4996
5144
  const component = result.data;
4997
5145
  spinner.stop();
4998
- const componentSubDir = path3.join(targetDir, component.name);
5146
+ const componentSubDir = path4.join(targetDir, component.name);
4999
5147
  for (const file of component.files) {
5000
- const fileName = path3.basename(file.path);
5148
+ const fileName = path4.basename(file.path);
5001
5149
  const localPath = safePath(componentSubDir, fileName);
5002
5150
  if (!checkFileExists(localPath)) {
5003
5151
  console.log(chalk2.yellow(` ${fileName}: not installed locally`));
5004
5152
  continue;
5005
5153
  }
5006
- const localContent = fs3.readFileSync(localPath, "utf-8");
5154
+ const localContent = fs4.readFileSync(localPath, "utf-8");
5007
5155
  const registryContent = config.theme && (file.content.includes("pdfx-theme") || file.content.includes("pdfx-theme-context")) ? resolveThemeImport(
5008
- path3.join(config.componentDir, component.name),
5156
+ path4.join(config.componentDir, component.name),
5009
5157
  config.theme,
5010
5158
  file.content
5011
5159
  ) : file.content;
@@ -5015,8 +5163,13 @@ async function diff(components) {
5015
5163
  console.log(chalk2.yellow(` ${fileName}: differs from registry`));
5016
5164
  const localLines = localContent.split("\n");
5017
5165
  const registryLines = registryContent.split("\n");
5166
+ const lineDiff = localLines.length - registryLines.length;
5018
5167
  console.log(chalk2.dim(` Local: ${localLines.length} lines`));
5019
5168
  console.log(chalk2.dim(` Registry: ${registryLines.length} lines`));
5169
+ if (lineDiff !== 0) {
5170
+ const diffText = lineDiff > 0 ? `${Math.abs(lineDiff)} line${Math.abs(lineDiff) > 1 ? "s" : ""} added locally` : `${Math.abs(lineDiff)} line${Math.abs(lineDiff) > 1 ? "s" : ""} removed locally`;
5171
+ console.log(chalk2.dim(` \u2192 ${diffText}`));
5172
+ }
5020
5173
  }
5021
5174
  }
5022
5175
  console.log();
@@ -5028,11 +5181,11 @@ async function diff(components) {
5028
5181
  }
5029
5182
 
5030
5183
  // 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";
5184
+ import fs7 from "fs";
5185
+ import path7 from "path";
5186
+ import chalk5 from "chalk";
5187
+ import ora4 from "ora";
5188
+ import prompts3 from "prompts";
5036
5189
 
5037
5190
  // src/constants.ts
5038
5191
  var DEFAULTS = {
@@ -5046,35 +5199,324 @@ var REGISTRY_SUBPATHS = {
5046
5199
  TEMPLATES: "templates"
5047
5200
  };
5048
5201
 
5202
+ // src/utils/install-dependencies.ts
5203
+ import chalk3 from "chalk";
5204
+ import { execa } from "execa";
5205
+ import ora3 from "ora";
5206
+ import prompts2 from "prompts";
5207
+
5208
+ // src/utils/package-manager.ts
5209
+ import fs5 from "fs";
5210
+ import path5 from "path";
5211
+ var PACKAGE_MANAGERS = {
5212
+ pnpm: {
5213
+ name: "pnpm",
5214
+ lockfile: "pnpm-lock.yaml",
5215
+ installCommand: "pnpm add"
5216
+ },
5217
+ yarn: {
5218
+ name: "yarn",
5219
+ lockfile: "yarn.lock",
5220
+ installCommand: "yarn add"
5221
+ },
5222
+ bun: {
5223
+ name: "bun",
5224
+ lockfile: "bun.lockb",
5225
+ installCommand: "bun add"
5226
+ },
5227
+ npm: {
5228
+ name: "npm",
5229
+ lockfile: "package-lock.json",
5230
+ installCommand: "npm install"
5231
+ }
5232
+ };
5233
+ function detectPackageManager(cwd = process.cwd()) {
5234
+ const managers = ["pnpm", "yarn", "bun", "npm"];
5235
+ for (const manager of managers) {
5236
+ const info = PACKAGE_MANAGERS[manager];
5237
+ const lockfilePath = path5.join(cwd, info.lockfile);
5238
+ if (fs5.existsSync(lockfilePath)) {
5239
+ return info;
5240
+ }
5241
+ }
5242
+ return PACKAGE_MANAGERS.npm;
5243
+ }
5244
+ function getInstallCommand(packageManager, packages, devDependency = false) {
5245
+ const pm = PACKAGE_MANAGERS[packageManager];
5246
+ const devFlag = devDependency ? packageManager === "npm" ? "--save-dev" : "-D" : "";
5247
+ return `${pm.installCommand} ${packages.join(" ")} ${devFlag}`.trim();
5248
+ }
5249
+
5250
+ // src/utils/install-dependencies.ts
5251
+ async function promptAndInstallReactPdf(validation, cwd = process.cwd()) {
5252
+ if (validation.installed && validation.valid) {
5253
+ return {
5254
+ success: true,
5255
+ message: "@react-pdf/renderer is already installed and compatible"
5256
+ };
5257
+ }
5258
+ const pm = detectPackageManager(cwd);
5259
+ const packageName = "@react-pdf/renderer";
5260
+ const installCmd = getInstallCommand(pm.name, [packageName]);
5261
+ console.log(chalk3.yellow("\n \u26A0 @react-pdf/renderer is required but not installed\n"));
5262
+ console.log(chalk3.dim(` This command will run: ${installCmd}
5263
+ `));
5264
+ const { shouldInstall } = await prompts2({
5265
+ type: "confirm",
5266
+ name: "shouldInstall",
5267
+ message: "Install @react-pdf/renderer now?",
5268
+ initial: true
5269
+ });
5270
+ if (!shouldInstall) {
5271
+ return {
5272
+ success: false,
5273
+ message: `Installation cancelled. Please install manually:
5274
+ ${chalk3.cyan(installCmd)}`
5275
+ };
5276
+ }
5277
+ const spinner = ora3("Installing @react-pdf/renderer...").start();
5278
+ try {
5279
+ await execa(pm.name, ["add", packageName], {
5280
+ cwd,
5281
+ stdio: "pipe"
5282
+ });
5283
+ spinner.succeed("Installed @react-pdf/renderer");
5284
+ return {
5285
+ success: true,
5286
+ message: "@react-pdf/renderer installed successfully"
5287
+ };
5288
+ } catch (error) {
5289
+ spinner.fail("Failed to install @react-pdf/renderer");
5290
+ const message = error instanceof Error ? error.message : String(error);
5291
+ return {
5292
+ success: false,
5293
+ message: `Installation failed: ${message}
5294
+ Try manually: ${chalk3.cyan(installCmd)}`
5295
+ };
5296
+ }
5297
+ }
5298
+ async function ensureReactPdfRenderer(validation, cwd = process.cwd()) {
5299
+ if (!validation.installed) {
5300
+ const result = await promptAndInstallReactPdf(validation, cwd);
5301
+ if (!result.success) {
5302
+ console.error(chalk3.red(`
5303
+ ${result.message}
5304
+ `));
5305
+ return false;
5306
+ }
5307
+ return true;
5308
+ }
5309
+ if (!validation.valid) {
5310
+ console.log(
5311
+ chalk3.yellow(
5312
+ `
5313
+ \u26A0 ${validation.message}
5314
+ ${chalk3.dim("\u2192")} You may encounter compatibility issues
5315
+ `
5316
+ )
5317
+ );
5318
+ }
5319
+ return true;
5320
+ }
5321
+
5322
+ // src/utils/pre-flight.ts
5323
+ import chalk4 from "chalk";
5324
+
5325
+ // src/utils/environment-validator.ts
5326
+ import fs6 from "fs";
5327
+ import path6 from "path";
5328
+ function validatePackageJson(cwd = process.cwd()) {
5329
+ const pkgPath = path6.join(cwd, "package.json");
5330
+ const exists = fs6.existsSync(pkgPath);
5331
+ return {
5332
+ valid: exists,
5333
+ message: exists ? "package.json found" : "No package.json found in current directory",
5334
+ fixCommand: exists ? void 0 : 'Run "npm init" or "pnpm init" to create a package.json'
5335
+ };
5336
+ }
5337
+ function validateReactProject(cwd = process.cwd()) {
5338
+ const pkgPath = path6.join(cwd, "package.json");
5339
+ if (!fs6.existsSync(pkgPath)) {
5340
+ return {
5341
+ valid: false,
5342
+ message: "Cannot validate React project without package.json"
5343
+ };
5344
+ }
5345
+ try {
5346
+ const pkg = readJsonFile(pkgPath);
5347
+ const deps = {
5348
+ ...pkg.dependencies,
5349
+ ...pkg.devDependencies
5350
+ };
5351
+ const hasReact = "react" in deps;
5352
+ return {
5353
+ valid: hasReact,
5354
+ message: hasReact ? "React is installed" : "This does not appear to be a React project",
5355
+ fixCommand: hasReact ? void 0 : "Install React: npx create-vite@latest or npx create-react-app"
5356
+ };
5357
+ } catch {
5358
+ return {
5359
+ valid: false,
5360
+ message: "Failed to read package.json"
5361
+ };
5362
+ }
5363
+ }
5364
+ function validatePdfxConfig(cwd = process.cwd()) {
5365
+ const configPath = path6.join(cwd, "pdfx.json");
5366
+ const exists = fs6.existsSync(configPath);
5367
+ return {
5368
+ valid: true,
5369
+ // Not blocking
5370
+ message: exists ? "pdfx.json already exists (will prompt to overwrite)" : "No existing pdfx.json"
5371
+ };
5372
+ }
5373
+ function validateEnvironment(cwd = process.cwd()) {
5374
+ return {
5375
+ hasPackageJson: validatePackageJson(cwd),
5376
+ isReactProject: validateReactProject(cwd),
5377
+ hasPdfxConfig: validatePdfxConfig(cwd)
5378
+ };
5379
+ }
5380
+
5381
+ // src/utils/pre-flight.ts
5382
+ function runPreFlightChecks(cwd = process.cwd()) {
5383
+ const environment = validateEnvironment(cwd);
5384
+ const dependencies = validateDependencies(cwd);
5385
+ const blockingErrors = [];
5386
+ const warnings = [];
5387
+ if (!environment.hasPackageJson.valid) {
5388
+ blockingErrors.push(
5389
+ `${environment.hasPackageJson.message}
5390
+ ${chalk4.dim("\u2192")} ${environment.hasPackageJson.fixCommand}`
5391
+ );
5392
+ } else if (!environment.isReactProject.valid) {
5393
+ blockingErrors.push(
5394
+ `${environment.isReactProject.message}
5395
+ ${chalk4.dim("\u2192")} ${environment.isReactProject.fixCommand}`
5396
+ );
5397
+ } else {
5398
+ if (!dependencies.react.valid && dependencies.react.installed) {
5399
+ warnings.push(
5400
+ `${dependencies.react.message}
5401
+ ${chalk4.dim("\u2192")} Current: ${dependencies.react.currentVersion}, Required: ${dependencies.react.requiredVersion}`
5402
+ );
5403
+ } else if (!dependencies.react.installed) {
5404
+ blockingErrors.push(
5405
+ `${dependencies.react.message}
5406
+ ${chalk4.dim("\u2192")} Install React: npm install react react-dom`
5407
+ );
5408
+ }
5409
+ }
5410
+ if (!dependencies.nodeJs.valid) {
5411
+ blockingErrors.push(
5412
+ `${dependencies.nodeJs.message}
5413
+ ${chalk4.dim("\u2192")} Current: ${dependencies.nodeJs.currentVersion}, Required: ${dependencies.nodeJs.requiredVersion}
5414
+ ${chalk4.dim("\u2192")} Visit https://nodejs.org to upgrade`
5415
+ );
5416
+ }
5417
+ if (dependencies.reactPdfRenderer.installed && !dependencies.reactPdfRenderer.valid) {
5418
+ warnings.push(
5419
+ `${dependencies.reactPdfRenderer.message}
5420
+ ${chalk4.dim("\u2192")} Consider upgrading: npm install @react-pdf/renderer@latest`
5421
+ );
5422
+ }
5423
+ if (dependencies.typescript && !dependencies.typescript.valid) {
5424
+ warnings.push(
5425
+ `${dependencies.typescript.message}
5426
+ ${chalk4.dim("\u2192")} Install types: npm install -D @types/react-pdf`
5427
+ );
5428
+ }
5429
+ return {
5430
+ environment,
5431
+ dependencies,
5432
+ blockingErrors,
5433
+ warnings,
5434
+ canProceed: blockingErrors.length === 0
5435
+ };
5436
+ }
5437
+ function displayPreFlightResults(result) {
5438
+ console.log(chalk4.bold("\n Pre-flight Checks:\n"));
5439
+ if (result.blockingErrors.length > 0) {
5440
+ console.log(chalk4.red(" \u2717 Blocking Issues:\n"));
5441
+ for (const error of result.blockingErrors) {
5442
+ console.log(chalk4.red(` \u2022 ${error}
5443
+ `));
5444
+ }
5445
+ }
5446
+ if (result.warnings.length > 0) {
5447
+ console.log(chalk4.yellow(" \u26A0 Warnings:\n"));
5448
+ for (const warning of result.warnings) {
5449
+ console.log(chalk4.yellow(` \u2022 ${warning}
5450
+ `));
5451
+ }
5452
+ }
5453
+ if (result.blockingErrors.length === 0 && result.warnings.length === 0) {
5454
+ console.log(chalk4.green(" \u2713 All checks passed!\n"));
5455
+ }
5456
+ }
5457
+
5049
5458
  // src/commands/init.ts
5050
5459
  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({
5460
+ console.log(chalk5.bold.cyan("\n Welcome to the pdfx cli\n"));
5461
+ const preFlightResult = runPreFlightChecks();
5462
+ displayPreFlightResults(preFlightResult);
5463
+ if (!preFlightResult.canProceed) {
5464
+ console.error(
5465
+ chalk5.red("\n Cannot proceed due to blocking issues. Please fix them and try again.\n")
5466
+ );
5467
+ process.exit(1);
5468
+ }
5469
+ const hasReactPdf = await ensureReactPdfRenderer(preFlightResult.dependencies.reactPdfRenderer);
5470
+ if (!hasReactPdf) {
5471
+ console.error(
5472
+ chalk5.red("\n @react-pdf/renderer is required. Please install it and try again.\n")
5473
+ );
5474
+ process.exit(1);
5475
+ }
5476
+ const existingConfig = path7.join(process.cwd(), "pdfx.json");
5477
+ if (fs7.existsSync(existingConfig)) {
5478
+ const { overwrite } = await prompts3({
5055
5479
  type: "confirm",
5056
5480
  name: "overwrite",
5057
5481
  message: "pdfx.json already exists. Overwrite?",
5058
5482
  initial: false
5059
5483
  });
5060
5484
  if (!overwrite) {
5061
- console.log(chalk3.yellow("Init cancelled \u2014 existing config preserved."));
5485
+ console.log(chalk5.yellow("Init cancelled \u2014 existing config preserved."));
5062
5486
  return;
5063
5487
  }
5064
5488
  }
5065
- const answers = await prompts2(
5489
+ const answers = await prompts3(
5066
5490
  [
5067
5491
  {
5068
5492
  type: "text",
5069
5493
  name: "componentDir",
5070
5494
  message: "Where should we install components?",
5071
- initial: DEFAULTS.COMPONENT_DIR
5495
+ initial: DEFAULTS.COMPONENT_DIR,
5496
+ validate: (value) => {
5497
+ if (!value || value.trim().length === 0) {
5498
+ return "Component directory is required";
5499
+ }
5500
+ if (path7.isAbsolute(value)) {
5501
+ return "Please use a relative path (e.g., ./src/components/pdfx)";
5502
+ }
5503
+ if (!value.startsWith(".")) {
5504
+ return "Path should start with ./ or ../ (e.g., ./src/components/pdfx)";
5505
+ }
5506
+ return true;
5507
+ }
5072
5508
  },
5073
5509
  {
5074
5510
  type: "text",
5075
5511
  name: "registry",
5076
5512
  message: "Registry URL:",
5077
- initial: DEFAULTS.REGISTRY_URL
5513
+ initial: DEFAULTS.REGISTRY_URL,
5514
+ validate: (value) => {
5515
+ if (!value || !value.startsWith("http")) {
5516
+ return "Please enter a valid HTTP(S) URL";
5517
+ }
5518
+ return true;
5519
+ }
5078
5520
  },
5079
5521
  {
5080
5522
  type: "select",
@@ -5103,18 +5545,30 @@ async function init() {
5103
5545
  type: "text",
5104
5546
  name: "themePath",
5105
5547
  message: "Where should we create the theme file?",
5106
- initial: DEFAULTS.THEME_FILE
5548
+ initial: DEFAULTS.THEME_FILE,
5549
+ validate: (value) => {
5550
+ if (!value || value.trim().length === 0) {
5551
+ return "Theme path is required";
5552
+ }
5553
+ if (path7.isAbsolute(value)) {
5554
+ return "Please use a relative path (e.g., ./src/lib/pdfx-theme.ts)";
5555
+ }
5556
+ if (!value.endsWith(".ts") && !value.endsWith(".tsx")) {
5557
+ return "Theme file must have .ts or .tsx extension (e.g., ./src/lib/pdfx-theme.ts)";
5558
+ }
5559
+ return true;
5560
+ }
5107
5561
  }
5108
5562
  ],
5109
5563
  {
5110
5564
  onCancel: () => {
5111
- console.log(chalk3.yellow("\nSetup cancelled."));
5565
+ console.log(chalk5.yellow("\nSetup cancelled."));
5112
5566
  process.exit(0);
5113
5567
  }
5114
5568
  }
5115
5569
  );
5116
5570
  if (!answers.componentDir || !answers.registry) {
5117
- console.error(chalk3.red("Missing required fields. Run pdfx init again."));
5571
+ console.error(chalk5.red("Missing required fields. Run pdfx init again."));
5118
5572
  process.exit(1);
5119
5573
  }
5120
5574
  const config = {
@@ -5126,54 +5580,63 @@ async function init() {
5126
5580
  const validation = configSchema.safeParse(config);
5127
5581
  if (!validation.success) {
5128
5582
  const issues = validation.error.issues.map((i) => i.message).join(", ");
5129
- console.error(chalk3.red(`Invalid configuration: ${issues}`));
5583
+ console.error(chalk5.red(`Invalid configuration: ${issues}`));
5130
5584
  process.exit(1);
5131
5585
  }
5132
- const spinner = ora3("Creating config and theme files...").start();
5586
+ const spinner = ora4("Creating config and theme files...").start();
5133
5587
  try {
5134
- fs4.writeFileSync(path4.join(process.cwd(), "pdfx.json"), JSON.stringify(config, null, 2));
5588
+ const componentDirPath = path7.resolve(process.cwd(), answers.componentDir);
5589
+ ensureDir(componentDirPath);
5590
+ fs7.writeFileSync(path7.join(process.cwd(), "pdfx.json"), JSON.stringify(config, null, 2));
5135
5591
  const presetName = answers.themePreset || "professional";
5136
5592
  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");
5593
+ const themePath = path7.resolve(process.cwd(), config.theme);
5594
+ ensureDir(path7.dirname(themePath));
5595
+ fs7.writeFileSync(themePath, generateThemeFile(preset), "utf-8");
5596
+ const contextPath = path7.join(path7.dirname(themePath), "pdfx-theme-context.tsx");
5597
+ fs7.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
5142
5598
  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)}
5599
+ console.log(chalk5.green("\nSuccess! You can now run:"));
5600
+ console.log(chalk5.cyan(" pdfx add heading"));
5601
+ console.log(chalk5.dim(`
5602
+ Components: ${path7.resolve(process.cwd(), answers.componentDir)}`));
5603
+ console.log(chalk5.dim(` Theme: ${path7.resolve(process.cwd(), config.theme)}
5148
5604
  `));
5149
5605
  } catch (error) {
5150
5606
  spinner.fail("Failed to create config");
5151
5607
  const message = error instanceof Error ? error.message : String(error);
5152
- console.error(chalk3.dim(` ${message}`));
5608
+ console.error(chalk5.dim(` ${message}`));
5153
5609
  process.exit(1);
5154
5610
  }
5155
5611
  }
5156
5612
 
5157
5613
  // src/commands/list.ts
5158
- import path5 from "path";
5159
- import chalk4 from "chalk";
5160
- import ora4 from "ora";
5614
+ import path8 from "path";
5615
+ import chalk6 from "chalk";
5616
+ import ora5 from "ora";
5161
5617
  var FETCH_TIMEOUT_MS2 = 1e4;
5162
5618
  async function list() {
5163
- const configPath = path5.join(process.cwd(), "pdfx.json");
5164
- if (!checkFileExists(configPath)) {
5165
- console.error(chalk4.red("Error: pdfx.json not found"));
5166
- console.log(chalk4.yellow("Run: pdfx init"));
5167
- process.exit(1);
5168
- }
5169
- const raw = readJsonFile(configPath);
5170
- const configResult = configSchema.safeParse(raw);
5171
- if (!configResult.success) {
5172
- console.error(chalk4.red("Invalid pdfx.json"));
5173
- process.exit(1);
5619
+ const configPath = path8.join(process.cwd(), "pdfx.json");
5620
+ let config;
5621
+ let hasLocalProject = false;
5622
+ if (checkFileExists(configPath)) {
5623
+ const raw = readJsonFile(configPath);
5624
+ const configResult = configSchema.safeParse(raw);
5625
+ if (!configResult.success) {
5626
+ console.error(chalk6.red("Invalid pdfx.json"));
5627
+ process.exit(1);
5628
+ }
5629
+ config = configResult.data;
5630
+ hasLocalProject = true;
5631
+ } else {
5632
+ config = {
5633
+ registry: "https://pdfx.akashpise.dev/r",
5634
+ componentDir: "./src/components/pdfx",
5635
+ theme: "./src/lib/pdfx-theme.ts"
5636
+ };
5637
+ console.log(chalk6.dim("No pdfx.json found. Listing components from default registry.\n"));
5174
5638
  }
5175
- const config = configResult.data;
5176
- const spinner = ora4("Fetching component list...").start();
5639
+ const spinner = ora5("Fetching component list...").start();
5177
5640
  try {
5178
5641
  let response;
5179
5642
  try {
@@ -5183,7 +5646,9 @@ async function list() {
5183
5646
  } catch (err) {
5184
5647
  const isTimeout = err instanceof Error && err.name === "TimeoutError";
5185
5648
  throw new NetworkError(
5186
- isTimeout ? "Registry request timed out" : `Could not reach ${config.registry}`
5649
+ isTimeout ? `Registry request timed out after 10 seconds.
5650
+ ${chalk6.dim("Check your internet connection or try again later.")}` : `Could not reach registry at ${config.registry}
5651
+ ${chalk6.dim("Verify the URL is correct and you have internet access.")}`
5187
5652
  );
5188
5653
  }
5189
5654
  if (!response.ok) {
@@ -5195,18 +5660,22 @@ async function list() {
5195
5660
  throw new RegistryError("Invalid registry format");
5196
5661
  }
5197
5662
  spinner.stop();
5198
- const targetDir = path5.resolve(process.cwd(), config.componentDir);
5199
5663
  const components = result.data.items.filter((item) => item.type === "registry:ui");
5200
- console.log(chalk4.bold(`
5664
+ console.log(chalk6.bold(`
5201
5665
  Available Components (${components.length})
5202
5666
  `));
5203
5667
  for (const item of components) {
5204
- const componentSubDir = path5.join(targetDir, item.name);
5205
- const localPath = safePath(componentSubDir, `pdfx-${item.name}.tsx`);
5206
- 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}`);
5209
- console.log(` ${"".padEnd(20)} ${status}`);
5668
+ if (hasLocalProject) {
5669
+ const targetDir = path8.resolve(process.cwd(), config.componentDir);
5670
+ const componentSubDir = path8.join(targetDir, item.name);
5671
+ const localPath = safePath(componentSubDir, `pdfx-${item.name}.tsx`);
5672
+ const installed = checkFileExists(localPath);
5673
+ const status = installed ? chalk6.green("[installed]") : chalk6.dim("[not installed]");
5674
+ console.log(` ${chalk6.cyan(item.name.padEnd(20))} ${item.description}`);
5675
+ console.log(` ${"".padEnd(20)} ${status}`);
5676
+ } else {
5677
+ console.log(` ${chalk6.cyan(item.name.padEnd(20))} ${item.description}`);
5678
+ }
5210
5679
  console.log();
5211
5680
  }
5212
5681
  } catch (error) {
@@ -5217,10 +5686,10 @@ async function list() {
5217
5686
  }
5218
5687
 
5219
5688
  // src/commands/template.ts
5220
- import path6 from "path";
5221
- import chalk5 from "chalk";
5222
- import ora5 from "ora";
5223
- import prompts3 from "prompts";
5689
+ import path9 from "path";
5690
+ import chalk7 from "chalk";
5691
+ import ora6 from "ora";
5692
+ import prompts4 from "prompts";
5224
5693
  function readConfig2(configPath) {
5225
5694
  const raw = readJsonFile(configPath);
5226
5695
  const result = configSchema.safeParse(raw);
@@ -5228,7 +5697,7 @@ function readConfig2(configPath) {
5228
5697
  const issues = result.error.issues.map((i) => i.message).join(", ");
5229
5698
  throw new ConfigError(
5230
5699
  `Invalid pdfx.json: ${issues}`,
5231
- `Fix the config or re-run ${chalk5.cyan("pdfx init")}`
5700
+ `Fix the config or re-run ${chalk7.cyan("pdfx init")}`
5232
5701
  );
5233
5702
  }
5234
5703
  return result.data;
@@ -5295,7 +5764,7 @@ async function fetchComponent2(name, registryUrl) {
5295
5764
  }
5296
5765
  function resolveTemplateImports(content, templateName, config) {
5297
5766
  const cwd = process.cwd();
5298
- const templateSubdir = path6.resolve(
5767
+ const templateSubdir = path9.resolve(
5299
5768
  cwd,
5300
5769
  config.templateDir ?? DEFAULTS.TEMPLATE_DIR,
5301
5770
  templateName
@@ -5303,26 +5772,26 @@ function resolveTemplateImports(content, templateName, config) {
5303
5772
  let result = content.replace(
5304
5773
  /from '\.\.\/\.\.\/components\/pdfx\/([a-z][a-z0-9-]*)\/pdfx-([a-z][a-z0-9-]*)'/g,
5305
5774
  (_match, componentName) => {
5306
- const absCompFile = path6.resolve(
5775
+ const absCompFile = path9.resolve(
5307
5776
  cwd,
5308
5777
  config.componentDir,
5309
5778
  componentName,
5310
5779
  `pdfx-${componentName}`
5311
5780
  );
5312
- let rel = path6.relative(templateSubdir, absCompFile);
5781
+ let rel = path9.relative(templateSubdir, absCompFile);
5313
5782
  if (!rel.startsWith(".")) rel = `./${rel}`;
5314
5783
  return `from '${rel}'`;
5315
5784
  }
5316
5785
  );
5317
5786
  if (config.theme) {
5318
- const absThemePath = path6.resolve(cwd, config.theme).replace(/\.tsx?$/, "");
5319
- let relTheme = path6.relative(templateSubdir, absThemePath);
5787
+ const absThemePath = path9.resolve(cwd, config.theme).replace(/\.tsx?$/, "");
5788
+ let relTheme = path9.relative(templateSubdir, absThemePath);
5320
5789
  if (!relTheme.startsWith(".")) relTheme = `./${relTheme}`;
5321
- const absContextPath = path6.join(
5322
- path6.dirname(path6.resolve(cwd, config.theme)),
5790
+ const absContextPath = path9.join(
5791
+ path9.dirname(path9.resolve(cwd, config.theme)),
5323
5792
  "pdfx-theme-context"
5324
5793
  );
5325
- let relContext = path6.relative(templateSubdir, absContextPath);
5794
+ let relContext = path9.relative(templateSubdir, absContextPath);
5326
5795
  if (!relContext.startsWith(".")) relContext = `./${relContext}`;
5327
5796
  result = result.replace(/from '\.\.\/\.\.\/lib\/pdfx-theme'/g, `from '${relTheme}'`);
5328
5797
  result = result.replace(/from '\.\.\/\.\.\/lib\/pdfx-theme-context'/g, `from '${relContext}'`);
@@ -5331,10 +5800,10 @@ function resolveTemplateImports(content, templateName, config) {
5331
5800
  }
5332
5801
  async function resolveConflict(fileName, currentDecision) {
5333
5802
  if (currentDecision === "overwrite-all") return "overwrite-all";
5334
- const { action } = await prompts3({
5803
+ const { action } = await prompts4({
5335
5804
  type: "select",
5336
5805
  name: "action",
5337
- message: `${chalk5.yellow(fileName)} already exists. What would you like to do?`,
5806
+ message: `${chalk7.yellow(fileName)} already exists. What would you like to do?`,
5338
5807
  choices: [
5339
5808
  { title: "Skip", value: "skip", description: "Keep the existing file unchanged" },
5340
5809
  { title: "Overwrite", value: "overwrite", description: "Replace this file only" },
@@ -5355,14 +5824,14 @@ async function ensurePeerComponents(template, config, force) {
5355
5824
  if (!template.peerComponents || template.peerComponents.length === 0) {
5356
5825
  return { installedPeers, peerWarnings };
5357
5826
  }
5358
- const componentBaseDir = path6.resolve(process.cwd(), config.componentDir);
5827
+ const componentBaseDir = path9.resolve(process.cwd(), config.componentDir);
5359
5828
  for (const componentName of template.peerComponents) {
5360
- const componentDir = path6.join(componentBaseDir, componentName);
5361
- const expectedMain = path6.join(componentDir, `pdfx-${componentName}.tsx`);
5829
+ const componentDir = path9.join(componentBaseDir, componentName);
5830
+ const expectedMain = path9.join(componentDir, `pdfx-${componentName}.tsx`);
5362
5831
  if (checkFileExists(componentDir)) {
5363
5832
  if (!checkFileExists(expectedMain)) {
5364
5833
  peerWarnings.push(
5365
- `${componentName}: directory exists but expected file missing (${path6.basename(expectedMain)})`
5834
+ `${componentName}: directory exists but expected file missing (${path9.basename(expectedMain)})`
5366
5835
  );
5367
5836
  } else {
5368
5837
  peerWarnings.push(
@@ -5373,9 +5842,9 @@ async function ensurePeerComponents(template, config, force) {
5373
5842
  }
5374
5843
  const component = await fetchComponent2(componentName, config.registry);
5375
5844
  ensureDir(componentDir);
5376
- const componentRelDir = path6.join(config.componentDir, component.name);
5845
+ const componentRelDir = path9.join(config.componentDir, component.name);
5377
5846
  for (const file of component.files) {
5378
- const fileName = path6.basename(file.path);
5847
+ const fileName = path9.basename(file.path);
5379
5848
  const filePath = safePath(componentDir, fileName);
5380
5849
  let content = file.content;
5381
5850
  if (config.theme && (content.includes("pdfx-theme") || content.includes("pdfx-theme-context"))) {
@@ -5396,12 +5865,12 @@ async function ensurePeerComponents(template, config, force) {
5396
5865
  async function installTemplate(name, config, force) {
5397
5866
  const template = await fetchTemplate(name, config.registry);
5398
5867
  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);
5868
+ const templateBaseDir = path9.resolve(process.cwd(), config.templateDir ?? DEFAULTS.TEMPLATE_DIR);
5869
+ const templateDir = path9.join(templateBaseDir, template.name);
5401
5870
  ensureDir(templateDir);
5402
5871
  const filesToWrite = [];
5403
5872
  for (const file of template.files) {
5404
- const fileName = path6.basename(file.path);
5873
+ const fileName = path9.basename(file.path);
5405
5874
  const filePath = safePath(templateDir, fileName);
5406
5875
  let content = file.content;
5407
5876
  if (/\.(tsx?|jsx?)$/.test(fileName) && content.includes("../../")) {
@@ -5414,7 +5883,7 @@ async function installTemplate(name, config, force) {
5414
5883
  const resolved = [];
5415
5884
  for (const file of filesToWrite) {
5416
5885
  if (checkFileExists(file.filePath)) {
5417
- const decision = await resolveConflict(path6.basename(file.filePath), globalDecision);
5886
+ const decision = await resolveConflict(path9.basename(file.filePath), globalDecision);
5418
5887
  if (decision === "overwrite-all") {
5419
5888
  globalDecision = "overwrite-all";
5420
5889
  }
@@ -5427,7 +5896,7 @@ async function installTemplate(name, config, force) {
5427
5896
  if (!file.skip) {
5428
5897
  writeFile(file.filePath, file.content);
5429
5898
  } else {
5430
- console.log(chalk5.dim(` skipped ${path6.basename(file.filePath)}`));
5899
+ console.log(chalk7.dim(` skipped ${path9.basename(file.filePath)}`));
5431
5900
  }
5432
5901
  }
5433
5902
  } else {
@@ -5436,37 +5905,37 @@ async function installTemplate(name, config, force) {
5436
5905
  }
5437
5906
  }
5438
5907
  if (template.peerComponents && template.peerComponents.length > 0) {
5439
- const componentBaseDir = path6.resolve(process.cwd(), config.componentDir);
5908
+ const componentBaseDir = path9.resolve(process.cwd(), config.componentDir);
5440
5909
  const missing = [];
5441
5910
  for (const comp of template.peerComponents) {
5442
- const compDir = path6.join(componentBaseDir, comp);
5911
+ const compDir = path9.join(componentBaseDir, comp);
5443
5912
  if (!checkFileExists(compDir)) {
5444
5913
  missing.push(comp);
5445
5914
  }
5446
5915
  }
5447
5916
  if (missing.length > 0) {
5448
5917
  console.log();
5449
- console.log(chalk5.yellow(" Missing peer components:"));
5918
+ console.log(chalk7.yellow(" Missing peer components:"));
5450
5919
  for (const comp of missing) {
5451
- console.log(chalk5.dim(` ${comp} \u2192 run: ${chalk5.cyan(`pdfx add ${comp}`)}`));
5920
+ console.log(chalk7.dim(` ${comp} \u2192 run: ${chalk7.cyan(`pdfx add ${comp}`)}`));
5452
5921
  }
5453
5922
  }
5454
5923
  }
5455
5924
  if (config.theme) {
5456
- const absThemePath = path6.resolve(process.cwd(), config.theme);
5457
- const contextPath = path6.join(path6.dirname(absThemePath), "pdfx-theme-context.tsx");
5925
+ const absThemePath = path9.resolve(process.cwd(), config.theme);
5926
+ const contextPath = path9.join(path9.dirname(absThemePath), "pdfx-theme-context.tsx");
5458
5927
  if (!checkFileExists(contextPath)) {
5459
- ensureDir(path6.dirname(contextPath));
5928
+ ensureDir(path9.dirname(contextPath));
5460
5929
  writeFile(contextPath, generateThemeContextFile());
5461
5930
  }
5462
5931
  }
5463
5932
  return peerResult;
5464
5933
  }
5465
5934
  async function templateAdd(names, options = {}) {
5466
- const configPath = path6.join(process.cwd(), "pdfx.json");
5935
+ const configPath = path9.join(process.cwd(), "pdfx.json");
5467
5936
  if (!checkFileExists(configPath)) {
5468
- console.error(chalk5.red("Error: pdfx.json not found"));
5469
- console.log(chalk5.yellow("Run: pdfx init"));
5937
+ console.error(chalk7.red("Error: pdfx.json not found"));
5938
+ console.log(chalk7.yellow("Run: pdfx init"));
5470
5939
  process.exit(1);
5471
5940
  }
5472
5941
  let config;
@@ -5474,11 +5943,11 @@ async function templateAdd(names, options = {}) {
5474
5943
  config = readConfig2(configPath);
5475
5944
  } catch (error) {
5476
5945
  if (error instanceof ConfigError) {
5477
- console.error(chalk5.red(error.message));
5478
- if (error.suggestion) console.log(chalk5.yellow(` Hint: ${error.suggestion}`));
5946
+ console.error(chalk7.red(error.message));
5947
+ if (error.suggestion) console.log(chalk7.yellow(` Hint: ${error.suggestion}`));
5479
5948
  } else {
5480
5949
  const message = error instanceof Error ? error.message : String(error);
5481
- console.error(chalk5.red(message));
5950
+ console.error(chalk7.red(message));
5482
5951
  }
5483
5952
  process.exit(1);
5484
5953
  }
@@ -5487,24 +5956,24 @@ async function templateAdd(names, options = {}) {
5487
5956
  for (const templateName of names) {
5488
5957
  const nameResult = componentNameSchema.safeParse(templateName);
5489
5958
  if (!nameResult.success) {
5490
- console.error(chalk5.red(`Invalid template name: "${templateName}"`));
5959
+ console.error(chalk7.red(`Invalid template name: "${templateName}"`));
5491
5960
  console.log(
5492
- chalk5.dim(' Names must be lowercase alphanumeric with hyphens (e.g., "invoice-classic")')
5961
+ chalk7.dim(' Names must be lowercase alphanumeric with hyphens (e.g., "invoice-classic")')
5493
5962
  );
5494
5963
  failed.push(templateName);
5495
5964
  continue;
5496
5965
  }
5497
- const spinner = ora5(`Adding template ${templateName}...`).start();
5966
+ const spinner = ora6(`Adding template ${templateName}...`).start();
5498
5967
  try {
5499
5968
  const result = await installTemplate(templateName, config, force);
5500
- spinner.succeed(`Added template ${chalk5.cyan(templateName)}`);
5969
+ spinner.succeed(`Added template ${chalk7.cyan(templateName)}`);
5501
5970
  if (result.installedPeers.length > 0) {
5502
5971
  console.log(
5503
- chalk5.green(` Installed required components: ${result.installedPeers.join(", ")}`)
5972
+ chalk7.green(` Installed required components: ${result.installedPeers.join(", ")}`)
5504
5973
  );
5505
5974
  }
5506
5975
  for (const warning of result.peerWarnings) {
5507
- console.log(chalk5.yellow(` Warning: ${warning}`));
5976
+ console.log(chalk7.yellow(` Warning: ${warning}`));
5508
5977
  }
5509
5978
  } catch (error) {
5510
5979
  if (error instanceof ValidationError && error.message.includes("Cancelled")) {
@@ -5513,24 +5982,24 @@ async function templateAdd(names, options = {}) {
5513
5982
  } else if (error instanceof NetworkError || error instanceof RegistryError || error instanceof ValidationError) {
5514
5983
  spinner.fail(error.message);
5515
5984
  if (error.suggestion) {
5516
- console.log(chalk5.dim(` Hint: ${error.suggestion}`));
5985
+ console.log(chalk7.dim(` Hint: ${error.suggestion}`));
5517
5986
  }
5518
5987
  } else {
5519
5988
  spinner.fail(`Failed to add template ${templateName}`);
5520
5989
  const message = error instanceof Error ? error.message : String(error);
5521
- console.error(chalk5.dim(` ${message}`));
5990
+ console.error(chalk7.dim(` ${message}`));
5522
5991
  }
5523
5992
  failed.push(templateName);
5524
5993
  }
5525
5994
  }
5526
5995
  console.log();
5527
5996
  if (failed.length > 0) {
5528
- console.log(chalk5.yellow(`Failed: ${failed.join(", ")}`));
5997
+ console.log(chalk7.yellow(`Failed: ${failed.join(", ")}`));
5529
5998
  }
5530
5999
  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}
6000
+ const resolvedDir = path9.resolve(process.cwd(), config.templateDir ?? DEFAULTS.TEMPLATE_DIR);
6001
+ console.log(chalk7.green("Done!"));
6002
+ console.log(chalk7.dim(`Templates installed to: ${resolvedDir}
5534
6003
  `));
5535
6004
  }
5536
6005
  if (failed.length > 0) {
@@ -5538,20 +6007,20 @@ async function templateAdd(names, options = {}) {
5538
6007
  }
5539
6008
  }
5540
6009
  async function templateList() {
5541
- const configPath = path6.join(process.cwd(), "pdfx.json");
6010
+ const configPath = path9.join(process.cwd(), "pdfx.json");
5542
6011
  if (!checkFileExists(configPath)) {
5543
- console.error(chalk5.red("Error: pdfx.json not found"));
5544
- console.log(chalk5.yellow("Run: pdfx init"));
6012
+ console.error(chalk7.red("Error: pdfx.json not found"));
6013
+ console.log(chalk7.yellow("Run: pdfx init"));
5545
6014
  process.exit(1);
5546
6015
  }
5547
6016
  const raw = readJsonFile(configPath);
5548
6017
  const configResult = configSchema.safeParse(raw);
5549
6018
  if (!configResult.success) {
5550
- console.error(chalk5.red("Invalid pdfx.json"));
6019
+ console.error(chalk7.red("Invalid pdfx.json"));
5551
6020
  process.exit(1);
5552
6021
  }
5553
6022
  const config = configResult.data;
5554
- const spinner = ora5("Fetching template list...").start();
6023
+ const spinner = ora6("Fetching template list...").start();
5555
6024
  try {
5556
6025
  let response;
5557
6026
  try {
@@ -5575,28 +6044,28 @@ async function templateList() {
5575
6044
  spinner.stop();
5576
6045
  const templates = result.data.items.filter((item) => item.type === "registry:template");
5577
6046
  if (templates.length === 0) {
5578
- console.log(chalk5.dim("\n No templates available in the registry.\n"));
6047
+ console.log(chalk7.dim("\n No templates available in the registry.\n"));
5579
6048
  return;
5580
6049
  }
5581
- const templateBaseDir = path6.resolve(
6050
+ const templateBaseDir = path9.resolve(
5582
6051
  process.cwd(),
5583
6052
  config.templateDir ?? DEFAULTS.TEMPLATE_DIR
5584
6053
  );
5585
- console.log(chalk5.bold(`
6054
+ console.log(chalk7.bold(`
5586
6055
  Available Templates (${templates.length})
5587
6056
  `));
5588
6057
  for (const item of templates) {
5589
- const templateDir = path6.join(templateBaseDir, item.name);
6058
+ const templateDir = path9.join(templateBaseDir, item.name);
5590
6059
  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 ?? ""}`);
6060
+ const status = installed ? chalk7.green("[installed]") : chalk7.dim("[not installed]");
6061
+ console.log(` ${chalk7.cyan(item.name.padEnd(22))} ${item.description ?? ""}`);
5593
6062
  console.log(` ${"".padEnd(22)} ${status}`);
5594
6063
  if (item.peerComponents && item.peerComponents.length > 0) {
5595
- console.log(chalk5.dim(` ${"".padEnd(22)} requires: ${item.peerComponents.join(", ")}`));
6064
+ console.log(chalk7.dim(` ${"".padEnd(22)} requires: ${item.peerComponents.join(", ")}`));
5596
6065
  }
5597
6066
  console.log();
5598
6067
  }
5599
- console.log(chalk5.dim(` Install with: ${chalk5.cyan("pdfx template add <template-name>")}
6068
+ console.log(chalk7.dim(` Install with: ${chalk7.cyan("pdfx template add <template-name>")}
5600
6069
  `));
5601
6070
  } catch (error) {
5602
6071
  const message = error instanceof Error ? error.message : String(error);
@@ -5606,15 +6075,23 @@ async function templateList() {
5606
6075
  }
5607
6076
 
5608
6077
  // 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";
6078
+ import fs8 from "fs";
6079
+ import path10 from "path";
6080
+ import chalk8 from "chalk";
6081
+ import ora7 from "ora";
6082
+ import prompts5 from "prompts";
5614
6083
  import ts from "typescript";
5615
6084
  async function themeInit() {
5616
- console.log(chalk6.bold.cyan("\n PDFx Theme Setup\n"));
5617
- const answers = await prompts4(
6085
+ const configPath = path10.join(process.cwd(), "pdfx.json");
6086
+ if (!fs8.existsSync(configPath)) {
6087
+ console.error(chalk8.red("\nError: pdfx.json not found"));
6088
+ console.log(chalk8.yellow("\n PDFx is not initialized in this project.\n"));
6089
+ console.log(chalk8.cyan(" Run: pdfx init"));
6090
+ console.log(chalk8.dim(" This will set up your project configuration and theme.\n"));
6091
+ process.exit(1);
6092
+ }
6093
+ console.log(chalk8.bold.cyan("\n PDFx Theme Setup\n"));
6094
+ const answers = await prompts5(
5618
6095
  [
5619
6096
  {
5620
6097
  type: "select",
@@ -5648,102 +6125,104 @@ async function themeInit() {
5648
6125
  ],
5649
6126
  {
5650
6127
  onCancel: () => {
5651
- console.log(chalk6.yellow("\nTheme setup cancelled."));
6128
+ console.log(chalk8.yellow("\nTheme setup cancelled."));
5652
6129
  process.exit(0);
5653
6130
  }
5654
6131
  }
5655
6132
  );
5656
6133
  if (!answers.preset || !answers.themePath) {
5657
- console.error(chalk6.red("Missing required fields."));
6134
+ console.error(chalk8.red("Missing required fields."));
5658
6135
  process.exit(1);
5659
6136
  }
5660
6137
  const presetName = answers.preset;
5661
6138
  const themePath = answers.themePath;
5662
6139
  const preset = themePresets[presetName];
5663
- const spinner = ora6(`Scaffolding ${presetName} theme...`).start();
6140
+ const spinner = ora7(`Scaffolding ${presetName} theme...`).start();
5664
6141
  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");
6142
+ const absThemePath = path10.resolve(process.cwd(), themePath);
6143
+ ensureDir(path10.dirname(absThemePath));
6144
+ fs8.writeFileSync(absThemePath, generateThemeFile(preset), "utf-8");
6145
+ const contextPath = path10.join(path10.dirname(absThemePath), "pdfx-theme-context.tsx");
6146
+ fs8.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
5670
6147
  spinner.succeed(`Created ${themePath} with ${presetName} theme`);
5671
- const configPath = path7.join(process.cwd(), "pdfx.json");
5672
- if (fs5.existsSync(configPath)) {
6148
+ const configPath2 = path10.join(process.cwd(), "pdfx.json");
6149
+ if (fs8.existsSync(configPath2)) {
5673
6150
  try {
5674
- const rawConfig = readJsonFile(configPath);
6151
+ const rawConfig = readJsonFile(configPath2);
5675
6152
  const result = configSchema.safeParse(rawConfig);
5676
6153
  if (result.success) {
5677
6154
  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"));
6155
+ fs8.writeFileSync(configPath2, JSON.stringify(updatedConfig, null, 2), "utf-8");
6156
+ console.log(chalk8.green(" Updated pdfx.json with theme path"));
5680
6157
  }
5681
6158
  } catch {
5682
- console.log(chalk6.yellow(' Could not update pdfx.json \u2014 add "theme" field manually'));
6159
+ console.log(chalk8.yellow(' Could not update pdfx.json \u2014 add "theme" field manually'));
5683
6160
  }
5684
6161
  }
5685
- console.log(chalk6.dim(`
6162
+ console.log(chalk8.dim(`
5686
6163
  Edit ${themePath} to customize your theme.
5687
6164
  `));
5688
6165
  } catch (error) {
5689
6166
  spinner.fail("Failed to create theme file");
5690
6167
  const message = error instanceof Error ? error.message : String(error);
5691
- console.error(chalk6.dim(` ${message}`));
6168
+ console.error(chalk8.dim(` ${message}`));
5692
6169
  process.exit(1);
5693
6170
  }
5694
6171
  }
5695
6172
  async function themeSwitch(presetName) {
6173
+ const resolvedPreset = presetName === "default" ? "professional" : presetName;
5696
6174
  const validPresets = Object.keys(themePresets);
5697
- if (!validPresets.includes(presetName)) {
5698
- console.error(
5699
- chalk6.red(`Invalid preset: "${presetName}". Valid presets: ${validPresets.join(", ")}`)
5700
- );
6175
+ if (!validPresets.includes(resolvedPreset)) {
6176
+ console.error(chalk8.red(`\u2716 Invalid theme preset: "${presetName}"`));
6177
+ console.log(chalk8.dim(` Available presets: ${validPresets.join(", ")}, default
6178
+ `));
6179
+ console.log(chalk8.dim(" Usage: pdfx theme switch <preset>"));
5701
6180
  process.exit(1);
5702
6181
  }
5703
- 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.'));
6182
+ const validatedPreset = resolvedPreset;
6183
+ const configPath = path10.join(process.cwd(), "pdfx.json");
6184
+ if (!fs8.existsSync(configPath)) {
6185
+ console.error(chalk8.red('No pdfx.json found. Run "pdfx init" first.'));
5707
6186
  process.exit(1);
5708
6187
  }
5709
6188
  const rawConfig = readJsonFile(configPath);
5710
6189
  const result = configSchema.safeParse(rawConfig);
5711
6190
  if (!result.success) {
5712
- console.error(chalk6.red("Invalid pdfx.json configuration."));
6191
+ console.error(chalk8.red("Invalid pdfx.json configuration."));
5713
6192
  process.exit(1);
5714
6193
  }
5715
6194
  const config = result.data;
5716
6195
  if (!config.theme) {
5717
6196
  console.error(
5718
- chalk6.red('No theme path in pdfx.json. Run "pdfx theme init" to set up theming.')
6197
+ chalk8.red('No theme path in pdfx.json. Run "pdfx theme init" to set up theming.')
5719
6198
  );
5720
6199
  process.exit(1);
5721
6200
  }
5722
- const answer = await prompts4({
6201
+ const answer = await prompts5({
5723
6202
  type: "confirm",
5724
6203
  name: "confirm",
5725
6204
  message: `This will overwrite ${config.theme} with the ${validatedPreset} preset. Continue?`,
5726
6205
  initial: false
5727
6206
  });
5728
6207
  if (!answer.confirm) {
5729
- console.log(chalk6.yellow("Cancelled."));
6208
+ console.log(chalk8.yellow("Cancelled."));
5730
6209
  return;
5731
6210
  }
5732
- const spinner = ora6(`Switching to ${validatedPreset} theme...`).start();
6211
+ const spinner = ora7(`Switching to ${validatedPreset} theme...`).start();
5733
6212
  try {
5734
6213
  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");
6214
+ const absThemePath = path10.resolve(process.cwd(), config.theme);
6215
+ fs8.writeFileSync(absThemePath, generateThemeFile(preset), "utf-8");
6216
+ const contextPath = path10.join(path10.dirname(absThemePath), "pdfx-theme-context.tsx");
6217
+ if (!fs8.existsSync(contextPath)) {
6218
+ ensureDir(path10.dirname(contextPath));
6219
+ fs8.writeFileSync(contextPath, generateThemeContextFile(), "utf-8");
5741
6220
  }
5742
6221
  spinner.succeed(`Switched to ${validatedPreset} theme`);
5743
6222
  } catch (error) {
5744
6223
  spinner.fail("Failed to switch theme");
5745
6224
  const message = error instanceof Error ? error.message : String(error);
5746
- console.error(chalk6.dim(` ${message}`));
6225
+ console.error(chalk8.dim(` ${message}`));
5747
6226
  process.exit(1);
5748
6227
  }
5749
6228
  }
@@ -5785,7 +6264,7 @@ function toPlainValue(node) {
5785
6264
  return void 0;
5786
6265
  }
5787
6266
  function parseThemeObject(themePath) {
5788
- const content = fs5.readFileSync(themePath, "utf-8");
6267
+ const content = fs8.readFileSync(themePath, "utf-8");
5789
6268
  const sourceFile = ts.createSourceFile(
5790
6269
  themePath,
5791
6270
  content,
@@ -5811,54 +6290,68 @@ function parseThemeObject(themePath) {
5811
6290
  throw new Error("No exported `theme` object found.");
5812
6291
  }
5813
6292
  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.'));
6293
+ const configPath = path10.join(process.cwd(), "pdfx.json");
6294
+ if (!fs8.existsSync(configPath)) {
6295
+ console.error(chalk8.red('No pdfx.json found. Run "pdfx init" first.'));
5817
6296
  process.exit(1);
5818
6297
  }
5819
6298
  const rawConfig = readJsonFile(configPath);
5820
6299
  const configResult = configSchema.safeParse(rawConfig);
5821
6300
  if (!configResult.success) {
5822
- console.error(chalk6.red("Invalid pdfx.json configuration."));
6301
+ console.error(chalk8.red("Invalid pdfx.json configuration."));
5823
6302
  process.exit(1);
5824
6303
  }
5825
6304
  if (!configResult.data.theme) {
5826
6305
  console.error(
5827
- chalk6.red('No theme path in pdfx.json. Run "pdfx theme init" to set up theming.')
6306
+ chalk8.red('No theme path in pdfx.json. Run "pdfx theme init" to set up theming.')
5828
6307
  );
5829
6308
  process.exit(1);
5830
6309
  }
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}`));
6310
+ const absThemePath = path10.resolve(process.cwd(), configResult.data.theme);
6311
+ if (!fs8.existsSync(absThemePath)) {
6312
+ console.error(chalk8.red(`Theme file not found: ${configResult.data.theme}`));
5834
6313
  process.exit(1);
5835
6314
  }
5836
- const spinner = ora6("Validating theme file...").start();
6315
+ const spinner = ora7("Validating theme file...").start();
5837
6316
  try {
5838
6317
  const parsedTheme = parseThemeObject(absThemePath);
5839
6318
  const result = themeSchema.safeParse(parsedTheme);
5840
6319
  if (!result.success) {
5841
- const message = result.error.issues.map((issue) => issue.message).join(", ");
5842
- spinner.fail(`Theme validation failed: ${message}`);
6320
+ const issues = result.error.issues.map((issue) => ` \u2192 ${chalk8.yellow(issue.path.join("."))}: ${issue.message}`).join("\n");
6321
+ spinner.fail("Theme validation failed");
6322
+ console.log(chalk8.red("\n Missing or invalid fields:\n"));
6323
+ console.log(issues);
6324
+ console.log(chalk8.dim("\n Fix these fields in your theme file and run validate again.\n"));
5843
6325
  process.exit(1);
5844
6326
  }
5845
6327
  spinner.succeed("Theme file is valid");
5846
- console.log(chalk6.dim(`
6328
+ console.log(chalk8.dim(`
5847
6329
  Validated: ${configResult.data.theme}
5848
6330
  `));
5849
6331
  } catch (error) {
5850
6332
  spinner.fail("Failed to validate theme");
5851
6333
  const message = error instanceof Error ? error.message : String(error);
5852
- console.error(chalk6.dim(` ${message}`));
6334
+ console.error(chalk8.dim(` ${message}`));
5853
6335
  process.exit(1);
5854
6336
  }
5855
6337
  }
5856
6338
 
5857
6339
  // src/index.ts
5858
6340
  var program = new Command();
5859
- program.name("pdfx").description("CLI for PDFx components").version("0.1.0");
6341
+ var __filename = fileURLToPath(import.meta.url);
6342
+ var __dirname = join(__filename, "..");
6343
+ var packageJsonPath = join(__dirname, "../package.json");
6344
+ var version = "0.1.3";
6345
+ try {
6346
+ const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
6347
+ version = pkg.version;
6348
+ } catch {
6349
+ }
6350
+ program.name("pdfx").description("CLI for PDFx components").version(version);
5860
6351
  program.command("init").description("Initialize pdfx in your project").action(init);
5861
- program.command("add <components...>").description("Add components to your project").option("-f, --force", "Overwrite existing files without prompting").action((components, options) => add(components, options));
6352
+ program.command("add <components...>").description("Add components to your project").option("-f, --force", "Overwrite existing files without prompting").option("-r, --registry <url>", "Override registry URL").action(
6353
+ (components, options) => add(components, options)
6354
+ );
5862
6355
  program.command("list").description("List available components from registry").action(list);
5863
6356
  program.command("diff <components...>").description("Compare local components with registry versions").action(diff);
5864
6357
  var themeCmd = program.command("theme").description("Manage PDF themes");