hostctl 0.1.48 → 0.1.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2718,7 +2718,7 @@ var Verbosity = {
2718
2718
  };
2719
2719
 
2720
2720
  // src/version.ts
2721
- var version = "0.1.48";
2721
+ var version = "0.1.49";
2722
2722
 
2723
2723
  // src/commands/pkg/create.ts
2724
2724
  import { promises as fs5 } from "fs";
@@ -2942,7 +2942,7 @@ dist/
2942
2942
  .DS_Store
2943
2943
  .env
2944
2944
  `;
2945
- async function createPackage(packageName, options) {
2945
+ async function createPackage(packageName, options, output) {
2946
2946
  const resolvedName = expandTildePath(packageName);
2947
2947
  const packageDir = path3.isAbsolute(resolvedName) ? resolvedName : path3.join(process.cwd(), resolvedName);
2948
2948
  const packageSlug = path3.basename(resolvedName);
@@ -2965,27 +2965,35 @@ async function createPackage(packageName, options) {
2965
2965
  await fs5.writeFile(path3.join(packageDir, "README.md"), readmeTemplate(packageJsonName, registryPrefix, false));
2966
2966
  await fs5.writeFile(path3.join(packageDir, ".gitignore"), gitignoreTemplate);
2967
2967
  }
2968
- console.log(`Created new hostctl package '${resolvedName}' at ${packageDir}`);
2969
- console.log(`
2970
- Next steps:`);
2971
- console.log(`1. cd ${packageDir}`);
2972
- console.log(`2. npm install`);
2973
- let step = 3;
2968
+ const nextSteps = [];
2969
+ nextSteps.push(`cd ${packageDir}`);
2970
+ nextSteps.push("npm install");
2974
2971
  if (options.lang === "typescript") {
2975
- console.log(`${step}. Edit src/index.ts and src/tasks/hello.ts to implement your tasks`);
2976
- step += 1;
2977
- console.log(`${step}. npm run build`);
2978
- step += 1;
2972
+ nextSteps.push("Edit src/index.ts and src/tasks/hello.ts to implement your tasks");
2973
+ nextSteps.push("npm run build");
2979
2974
  } else {
2980
- console.log(`${step}. Edit src/index.js and src/tasks/hello.js to implement your tasks`);
2981
- step += 1;
2975
+ nextSteps.push("Edit src/index.js and src/tasks/hello.js to implement your tasks");
2982
2976
  }
2983
- console.log(`${step}. Test your package with: hostctl tasks .`);
2984
- step += 1;
2985
- console.log(`${step}. Run it with: hostctl run . ${registryPrefix}.hello`);
2986
- console.log(`
2977
+ nextSteps.push("Test your package with: hostctl tasks .");
2978
+ nextSteps.push(`Run it with: hostctl run . ${registryPrefix}.hello`);
2979
+ if (!output?.quiet) {
2980
+ console.log(`Created new hostctl package '${resolvedName}' at ${packageDir}`);
2981
+ console.log(`
2982
+ Next steps:`);
2983
+ nextSteps.forEach((step, index) => {
2984
+ console.log(`${index + 1}. ${step}`);
2985
+ });
2986
+ console.log(`
2987
2987
  Note: The package includes 'hostctl' as a dependency for local development.`);
2988
- console.log(`For production, you may want to add it as a peer dependency instead.`);
2988
+ console.log(`For production, you may want to add it as a peer dependency instead.`);
2989
+ }
2990
+ return {
2991
+ packageDir,
2992
+ packageName: packageJsonName,
2993
+ registryPrefix,
2994
+ language: options.lang,
2995
+ nextSteps
2996
+ };
2989
2997
  }
2990
2998
 
2991
2999
  // src/commands/pkg/package-manager.ts
@@ -3469,7 +3477,9 @@ var PackageManager = class {
3469
3477
  this.manifest = { packages: [], version: "1.0" };
3470
3478
  }
3471
3479
  } catch (error) {
3472
- console.warn("Failed to load manifest, creating new one:", error);
3480
+ if (this.app.outputPlain()) {
3481
+ console.warn("Failed to load manifest, creating new one:", error);
3482
+ }
3473
3483
  this.manifest = { packages: [], version: "1.0" };
3474
3484
  }
3475
3485
  }
@@ -3628,8 +3638,8 @@ var PackageManager = class {
3628
3638
  const packageToRemove = this.findPackageToRemove(packageIdentifier);
3629
3639
  if (!packageToRemove) {
3630
3640
  return {
3631
- success: false,
3632
- error: `Package '${packageIdentifier}' not found. Use 'hostctl pkg list' to see installed packages.`
3641
+ success: true,
3642
+ warning: `Package '${packageIdentifier}' not found. Use 'hostctl pkg list' to see installed packages.`
3633
3643
  };
3634
3644
  }
3635
3645
  await this.removePackageFiles(packageToRemove);
@@ -3661,7 +3671,9 @@ var PackageManager = class {
3661
3671
  prefix: packagesDir.toString()
3662
3672
  });
3663
3673
  } catch (error) {
3664
- console.log(`DEBUG: Error during npm uninstall: ${error}`);
3674
+ if (this.app.outputPlain()) {
3675
+ console.log(`DEBUG: Error during npm uninstall: ${error}`);
3676
+ }
3665
3677
  }
3666
3678
  }
3667
3679
  /**
@@ -3720,7 +3732,9 @@ var PackageManager = class {
3720
3732
  const installDir = packagesDir.join(filenamifiedSource);
3721
3733
  const existingPackage = this.findPackageBySource(normalizedSource);
3722
3734
  if (existingPackage) {
3723
- console.log(`Package '${existingPackage.name}' is already installed from ${normalizedSource}`);
3735
+ if (this.app.outputPlain()) {
3736
+ console.log(`Package '${existingPackage.name}' is already installed from ${normalizedSource}`);
3737
+ }
3724
3738
  return {
3725
3739
  success: true,
3726
3740
  packageInfo: existingPackage,
@@ -3824,7 +3838,9 @@ var PackageManager = class {
3824
3838
  async findRealInstalledNpmPackagePath(packagesDir, source) {
3825
3839
  const nodeModulesPath = packagesDir.join("node_modules");
3826
3840
  if (!await nodeModulesPath.exists()) {
3827
- console.log(`DEBUG: node_modules does not exist at ${nodeModulesPath.toString()}`);
3841
+ if (this.app.outputPlain()) {
3842
+ console.log(`DEBUG: node_modules does not exist at ${nodeModulesPath.toString()}`);
3843
+ }
3828
3844
  return { path: null, name: null };
3829
3845
  }
3830
3846
  const entries = await fs6.readdir(nodeModulesPath.toString());
@@ -3865,6 +3881,9 @@ var PackageManager = class {
3865
3881
  async handleDuplicateNames(finalPackageInfo) {
3866
3882
  const actualPackageName = finalPackageInfo.name;
3867
3883
  if (this.hasPackageWithName(actualPackageName)) {
3884
+ if (!this.app.outputPlain()) {
3885
+ return;
3886
+ }
3868
3887
  const existingPackages = this.getPackagesWithName(actualPackageName);
3869
3888
  console.warn(`\u26A0\uFE0F Warning: Package name '${actualPackageName}' already exists.`);
3870
3889
  console.warn(` Existing packages:`);
@@ -3907,91 +3926,102 @@ var PackageManager = class {
3907
3926
  };
3908
3927
 
3909
3928
  // src/commands/pkg/install.ts
3910
- async function installPackage(source, app) {
3929
+ async function installPackage(source, app, output) {
3911
3930
  const packageManager = new PackageManager(app);
3912
3931
  const result = await packageManager.installPackage(source);
3913
- if (result.success) {
3914
- console.log(`Installed package '${result.packageInfo.name}' from ${source} to ${result.installPath}`);
3915
- } else {
3916
- console.error(`Failed to install package from ${source}: ${result.error}`);
3917
- throw new Error(result.error);
3932
+ if (!output?.quiet) {
3933
+ if (result.success) {
3934
+ console.log(`Installed package '${result.packageInfo.name}' from ${source} to ${result.installPath}`);
3935
+ } else {
3936
+ console.error(`Failed to install package from ${source}: ${result.error}`);
3937
+ }
3918
3938
  }
3939
+ return { ...result, source };
3919
3940
  }
3920
3941
 
3921
3942
  // src/commands/pkg/list.ts
3922
3943
  import chalk from "chalk";
3923
3944
  async function listPackages(app) {
3924
3945
  const packageManager = new PackageManager(app);
3925
- try {
3926
- const packages = await packageManager.listPackages();
3927
- if (packages.length === 0) {
3928
- console.log("No packages installed.");
3929
- return;
3946
+ const packages = await packageManager.listPackages();
3947
+ const packagesByName = /* @__PURE__ */ new Map();
3948
+ packages.forEach((pkg) => {
3949
+ if (!packagesByName.has(pkg.name)) {
3950
+ packagesByName.set(pkg.name, []);
3930
3951
  }
3931
- const packagesByName = /* @__PURE__ */ new Map();
3932
- packages.forEach((pkg) => {
3933
- if (!packagesByName.has(pkg.name)) {
3934
- packagesByName.set(pkg.name, []);
3935
- }
3936
- packagesByName.get(pkg.name).push(pkg);
3937
- });
3938
- console.log(`Found ${packages.length} package(s):
3952
+ packagesByName.get(pkg.name).push(pkg);
3953
+ });
3954
+ const duplicateNames = Array.from(packagesByName.entries()).filter(([_, pkgs]) => pkgs.length > 1).map(([name]) => name);
3955
+ return { packages, duplicateNames };
3956
+ }
3957
+ function printPackageList(packages, duplicateNames) {
3958
+ if (packages.length === 0) {
3959
+ console.log("No packages installed.");
3960
+ return;
3961
+ }
3962
+ const packagesByName = /* @__PURE__ */ new Map();
3963
+ packages.forEach((pkg) => {
3964
+ if (!packagesByName.has(pkg.name)) {
3965
+ packagesByName.set(pkg.name, []);
3966
+ }
3967
+ packagesByName.get(pkg.name).push(pkg);
3968
+ });
3969
+ console.log(`Found ${packages.length} package(s):
3939
3970
  `);
3940
- packages.forEach((pkg) => {
3941
- const packagesWithSameName = packagesByName.get(pkg.name);
3942
- const hasDuplicates = packagesWithSameName.length > 1;
3943
- let output = `\u2022 ${pkg.name}`;
3944
- if (pkg.version) {
3945
- output += ` (v${pkg.version})`;
3946
- }
3947
- if (pkg.description) {
3948
- output += ` - ${pkg.description}`;
3949
- }
3950
- if (hasDuplicates) {
3951
- output = chalk.yellow(output);
3952
- output += chalk.yellow(" \u26A0\uFE0F (duplicate name)");
3953
- }
3954
- if (pkg.source) {
3955
- if (pkg.source.startsWith("http") || pkg.source.startsWith("git@")) {
3956
- output += `
3971
+ packages.forEach((pkg) => {
3972
+ const packagesWithSameName = packagesByName.get(pkg.name);
3973
+ const hasDuplicates = packagesWithSameName.length > 1;
3974
+ let output = `\u2022 ${pkg.name}`;
3975
+ if (pkg.version) {
3976
+ output += ` (v${pkg.version})`;
3977
+ }
3978
+ if (pkg.description) {
3979
+ output += ` - ${pkg.description}`;
3980
+ }
3981
+ if (hasDuplicates) {
3982
+ output = chalk.yellow(output);
3983
+ output += chalk.yellow(" \u26A0\uFE0F (duplicate name)");
3984
+ }
3985
+ if (pkg.source) {
3986
+ if (pkg.source.startsWith("http") || pkg.source.startsWith("git@")) {
3987
+ output += `
3957
3988
  \u{1F4E6} Source: ${pkg.source}`;
3958
- } else if (!pkg.source.startsWith(".") && !pkg.source.startsWith("/")) {
3959
- output += `
3989
+ } else if (!pkg.source.startsWith(".") && !pkg.source.startsWith("/")) {
3990
+ output += `
3960
3991
  \u{1F4E6} Source: https://www.npmjs.com/package/${pkg.source}`;
3961
- } else {
3962
- output += `
3992
+ } else {
3993
+ output += `
3963
3994
  \u{1F4E6} Source: ${pkg.source}`;
3964
- }
3965
3995
  }
3966
- console.log(output);
3967
- console.log(` \u2514\u2500 (run "hostctl tasks ${pkg.name}" to list tasks)`);
3968
- console.log("");
3969
- });
3970
- const duplicateNames = Array.from(packagesByName.entries()).filter(([_, pkgs]) => pkgs.length > 1).map(([name, _]) => name);
3971
- if (duplicateNames.length > 0) {
3972
- console.log(chalk.yellow("\u26A0\uFE0F Warning: The following package names have duplicates:"));
3973
- duplicateNames.forEach((name) => {
3974
- console.log(chalk.yellow(` - ${name}`));
3975
- });
3976
- console.log(chalk.yellow(" Use the full source URL to run tasks from these packages."));
3977
- console.log("");
3978
3996
  }
3979
- } catch (error) {
3980
- console.error("Error listing packages:", error);
3981
- throw error;
3997
+ console.log(output);
3998
+ console.log(` \u2514\u2500 (run "hostctl tasks ${pkg.name}" to list tasks)`);
3999
+ console.log("");
4000
+ });
4001
+ if (duplicateNames.length > 0) {
4002
+ console.log(chalk.yellow("\u26A0\uFE0F Warning: The following package names have duplicates:"));
4003
+ duplicateNames.forEach((name) => {
4004
+ console.log(chalk.yellow(` - ${name}`));
4005
+ });
4006
+ console.log(chalk.yellow(" Use the full source URL to run tasks from these packages."));
4007
+ console.log("");
3982
4008
  }
3983
4009
  }
3984
4010
 
3985
4011
  // src/commands/pkg/remove.ts
3986
- async function removePackage(packageIdentifier, app) {
4012
+ async function removePackage(packageIdentifier, app, output) {
3987
4013
  const packageManager = new PackageManager(app);
3988
4014
  const result = await packageManager.removePackage(packageIdentifier);
3989
- if (result.success && result.packageInfo) {
3990
- console.log(`Successfully removed package '${result.packageInfo.name}' (${result.packageInfo.directory})`);
3991
- } else {
3992
- console.error(`Failed to remove package: ${result.error}`);
3993
- return;
4015
+ if (!output?.quiet) {
4016
+ if (result.success && result.packageInfo) {
4017
+ console.log(`Successfully removed package '${result.packageInfo.name}' (${result.packageInfo.directory})`);
4018
+ } else if (result.success && result.warning) {
4019
+ console.warn(result.warning);
4020
+ } else {
4021
+ console.error(`Failed to remove package: ${result.error}`);
4022
+ }
3994
4023
  }
4024
+ return result;
3995
4025
  }
3996
4026
 
3997
4027
  // src/cli.ts
@@ -4810,26 +4840,86 @@ var Cli = class {
4810
4840
  }
4811
4841
  }
4812
4842
  async handlePkgCreate(packageName, options) {
4843
+ const opts = this.program.opts();
4844
+ if (opts.json) {
4845
+ try {
4846
+ const result = await createPackage(packageName, options, { quiet: true });
4847
+ console.log(JSON.stringify({ success: true, ...result }, null, 2));
4848
+ } catch (error) {
4849
+ console.log(
4850
+ JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }, null, 2)
4851
+ );
4852
+ process3.exitCode = 1;
4853
+ }
4854
+ return;
4855
+ }
4813
4856
  await createPackage(packageName, options);
4814
4857
  }
4815
4858
  async handlePkgInstall(source) {
4816
- await this.loadApp(this.program.opts());
4817
- try {
4818
- await installPackage(source, this.app);
4819
- } catch (error) {
4820
- console.error(
4821
- `Failed to install package from ${source}: ${error instanceof Error ? error.message : String(error)}`
4859
+ const opts = this.program.opts();
4860
+ await this.loadApp(opts);
4861
+ const result = await installPackage(source, this.app, { quiet: Boolean(opts.json) });
4862
+ if (opts.json) {
4863
+ console.log(
4864
+ JSON.stringify(
4865
+ {
4866
+ success: result.success,
4867
+ source: result.source,
4868
+ package: result.packageInfo,
4869
+ installPath: result.installPath,
4870
+ error: result.error
4871
+ },
4872
+ null,
4873
+ 2
4874
+ )
4822
4875
  );
4876
+ }
4877
+ if (!result.success) {
4823
4878
  process3.exitCode = 1;
4824
4879
  }
4825
4880
  }
4826
4881
  async handlePkgList() {
4827
- await this.loadApp(this.program.opts());
4828
- await listPackages(this.app);
4882
+ const opts = this.program.opts();
4883
+ await this.loadApp(opts);
4884
+ const result = await listPackages(this.app);
4885
+ if (opts.json) {
4886
+ console.log(
4887
+ JSON.stringify(
4888
+ {
4889
+ count: result.packages.length,
4890
+ duplicates: result.duplicateNames,
4891
+ packages: result.packages
4892
+ },
4893
+ null,
4894
+ 2
4895
+ )
4896
+ );
4897
+ return;
4898
+ }
4899
+ printPackageList(result.packages, result.duplicateNames);
4829
4900
  }
4830
4901
  async handlePkgRemove(packageIdentifier) {
4831
- await this.loadApp(this.program.opts());
4832
- await removePackage(packageIdentifier, this.app);
4902
+ const opts = this.program.opts();
4903
+ await this.loadApp(opts);
4904
+ const result = await removePackage(packageIdentifier, this.app, { quiet: Boolean(opts.json) });
4905
+ if (opts.json) {
4906
+ console.log(
4907
+ JSON.stringify(
4908
+ {
4909
+ success: result.success,
4910
+ identifier: packageIdentifier,
4911
+ package: result.packageInfo,
4912
+ error: result.error,
4913
+ warning: result.warning
4914
+ },
4915
+ null,
4916
+ 2
4917
+ )
4918
+ );
4919
+ }
4920
+ if (!result.success) {
4921
+ process3.exitCode = 1;
4922
+ }
4833
4923
  }
4834
4924
  async handleTasksList(specParts, options, cmd) {
4835
4925
  const opts = cmd.optsWithGlobals();