@uxland/harmonix-cli 0.0.6 → 0.0.7

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 (3) hide show
  1. package/README.md +3 -1
  2. package/index.js +36 -27
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -19,7 +19,9 @@ registry=https://your-plugin-store.example.com/upload
19
19
  apiKey=your-api-key
20
20
  ```
21
21
 
22
- The `--registry` and `--api-key` options override the file.
22
+ The `--registry` and `--api-key` options override the file. A project `.harmonixrc` (the nearest one above the plugin folder) overrides the one in your home folder.
23
+
24
+ `harmonix publish` exits with code `1` when the upload fails (for example, the plugin does not exist in the store or the version is already published), so scripts can stop on errors.
23
25
 
24
26
  > `.harmonixrc` contains credentials: never commit it. Projects made with `npm create @uxland/harmonix-plugin@latest` already ignore it.
25
27
 
package/index.js CHANGED
@@ -1,22 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { program } = require('commander');
4
- const path = require('path');
5
- const fs = require('fs');
6
- const os = require('os');
7
- const axios = require('axios');
8
- const FormData = require('form-data');
9
-
10
- console.log("reached index");
3
+ const { program } = require("commander");
4
+ const path = require("node:path");
5
+ const fs = require("node:fs");
6
+ const os = require("node:os");
7
+ const axios = require("axios");
8
+ const FormData = require("form-data");
11
9
 
12
10
  function getConfig() {
13
11
  const config = {};
12
+
13
+ // User-level config (~/.harmonixrc) first, so the project's .harmonixrc overrides it
14
+ const homeConfigPath = path.join(os.homedir(), ".harmonixrc");
15
+ if (fs.existsSync(homeConfigPath)) {
16
+ Object.assign(config, parseConfigFile(homeConfigPath));
17
+ }
18
+
14
19
  let dir = process.cwd();
15
20
  let steps = 0;
16
21
  const maxSteps = 10;
17
22
 
18
23
  while (steps < maxSteps) {
19
- const configPath = path.join(dir, '.harmonixrc');
24
+ const configPath = path.join(dir, ".harmonixrc");
20
25
  if (fs.existsSync(configPath)) {
21
26
  Object.assign(config, parseConfigFile(configPath));
22
27
  break; // stop at first .harmonixrc found
@@ -28,27 +33,24 @@ function getConfig() {
28
33
  steps++;
29
34
  }
30
35
 
31
- // Also merge user-level config (~/.harmonixrc)
32
- const homeConfigPath = path.join(os.homedir(), '.harmonixrc');
33
- if (fs.existsSync(homeConfigPath)) {
34
- Object.assign(config, parseConfigFile(homeConfigPath));
35
- }
36
-
37
36
  return config;
38
37
  }
39
38
 
40
39
  function parseConfigFile(filePath) {
41
40
  const result = {};
42
41
  try {
43
- const content = fs.readFileSync(filePath, 'utf8');
44
- content.split('\n').forEach(line => {
45
- if (line.trim() && !line.startsWith('#')) {
46
- const [key, value] = line.split('=');
42
+ const content = fs.readFileSync(filePath, "utf8");
43
+ for (const line of content.split("\n")) {
44
+ if (line.trim() && !line.startsWith("#")) {
45
+ // Split on the first '=' only: a value may contain '=' (e.g. base64 padding)
46
+ const separator = line.indexOf("=");
47
+ const key = separator === -1 ? "" : line.slice(0, separator).trim();
48
+ const value = separator === -1 ? "" : line.slice(separator + 1).trim();
47
49
  if (key && value) {
48
- result[key.trim()] = value.trim();
50
+ result[key] = value;
49
51
  }
50
52
  }
51
- });
53
+ }
52
54
  } catch (err) {
53
55
  console.warn(`⚠️ Error reading ${filePath}:`, err.message);
54
56
  }
@@ -56,9 +58,9 @@ function parseConfigFile(filePath) {
56
58
  }
57
59
 
58
60
  program
59
- .command('publish')
60
- .option('--registry <registry>', 'Backend URL (overrides .harmonixrc)')
61
- .option('--api-key <apiKey>', 'API Key (overrides .harmonixrc)')
61
+ .command("publish")
62
+ .option("--registry <registry>", "Backend URL (overrides .harmonixrc)")
63
+ .option("--api-key <apiKey>", "API Key (overrides .harmonixrc)")
62
64
  .action(async (opts) => {
63
65
  try {
64
66
  const config = getConfig();
@@ -99,12 +101,19 @@ program
99
101
  }
100
102
 
101
103
  const headers = {
102
- 'x-api-key': apiKey
104
+ "x-api-key": apiKey,
103
105
  };
104
106
  const response = await axios.post(registry, formData, { headers });
105
- console.log('✅ Plugin published:', response.data);
107
+ if (response.data?.success === false) {
108
+ throw new Error(response.data.error || response.data.message || "Plugin Store rejected the upload");
109
+ }
110
+ console.log(`✅ Plugin published: ${pluginId}@${versionNumber}`, response.data);
106
111
  } catch (err) {
107
- console.error('❌ Failed to publish:', err.message);
112
+ // Exit non-zero so scripts and CI can tell a failed publish from a successful one
113
+ const serverError = err.response?.data?.error || err.response?.data?.message;
114
+ const status = err.response ? ` (HTTP ${err.response.status})` : "";
115
+ console.error(`❌ Failed to publish${status}:`, serverError || err.message);
116
+ process.exit(1);
108
117
  }
109
118
  });
110
119
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxland/harmonix-cli",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "bin": {
5
5
  "harmonix": "index.js"
6
6
  },