@uxland/harmonix-cli 0.0.3 → 0.0.5
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/README.md +113 -0
- package/index.js +49 -27
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# 📦 Documentació de `harmonix-cli`
|
|
2
|
+
|
|
3
|
+
`harmonix-cli` és una eina de línia de comandes per publicar plugins al plugin store de Harmonix.
|
|
4
|
+
|
|
5
|
+
## 🔧 Instal·lació
|
|
6
|
+
|
|
7
|
+
Assegura’t de tenir `node` i `npm` instal·lats. Afegeix `harmonix-cli` com a dependència del teu projecte o de forma global:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @uxland/harmonix-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🚀 Publicació d’un plugin
|
|
16
|
+
|
|
17
|
+
### Comanda principal
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
harmonix publish
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Aquesa comanda llegeix la informació del `package.json` i puja el fitxer compilat especificat al registry (plugin store) configurat.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 📁 Estructura requerida
|
|
28
|
+
|
|
29
|
+
### `package.json`
|
|
30
|
+
|
|
31
|
+
El fitxer `package.json` del teu plugin ha de contenir obligatòriament els següents camps:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"name": "plugin-id",
|
|
36
|
+
"version": "1.0.0",
|
|
37
|
+
"module": "dist/plugin.js"
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- `name`: identificador únic del plugin (id del plugin).
|
|
42
|
+
- `version`: versió que es publicarà.
|
|
43
|
+
- `module`: ruta al fitxer compilat que es pujarà.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## ⚙️ Configuració amb `.harmonixrc`
|
|
48
|
+
|
|
49
|
+
Crea un fitxer `.harmonixrc` a la carpeta arrel del projecte (en cas de monorepo també serveix) amb el següent contingut:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
registry=https://plugins.harmonix.dev/upload
|
|
53
|
+
apiKey=la_teva_clau_api
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- `registry`: URL del plugin store.
|
|
57
|
+
- `apiKey`: clau API per a l’autenticació.
|
|
58
|
+
|
|
59
|
+
> 🛑 **Important**: El fitxer `.harmonixrc` conté credencials sensibles. No l’incloguis al repositori de codi. Afegeix-lo al `.gitignore`:
|
|
60
|
+
>
|
|
61
|
+
> ```
|
|
62
|
+
> .harmonixrc
|
|
63
|
+
> ```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🧰 Paràmetres opcionals (substitueixen `.harmonixrc`)
|
|
68
|
+
|
|
69
|
+
També pots passar les opcions directament per línia de comandes:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
harmonix publish --registry https://plugins.harmonix.dev/upload --api-key la_teva_clau_api
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
- `--registry`: URL del servidor.
|
|
76
|
+
- `--api-key`: clau API d’autenticació.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 🫠 Errors comuns i solucions
|
|
81
|
+
|
|
82
|
+
| Error | Possible causa | Solució |
|
|
83
|
+
| ------------------------------------------ | -------------------------------------------------------------------------- | -------------------------------------------------------- |
|
|
84
|
+
| `package.json not found` | No s’ha trobat el fitxer `package.json` a la carpeta actual | Executa `harmonix publish` des de la carpeta del plugin |
|
|
85
|
+
| `'module' field not found in package.json` | Falta el camp `module` al `package.json` | Afegeix "module": "ruta/al/fitxer.js" |
|
|
86
|
+
| `Compiled bundle file not found` | El fitxer indicat al `module` no existeix | Compila el plugin abans de publicar o verifica la ruta |
|
|
87
|
+
| `No registry configured` | No s’ha especificat `registry` ni a `.harmonixrc` ni per línia de comandes | Afegeix `registry=` a `.harmonixrc` o passa `--registry` |
|
|
88
|
+
| `No api key configured` | Falta la clau API (`apiKey`) | Afegeix-la a `.harmonixrc` o passa `--api-key` |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 📖 Ajuda
|
|
93
|
+
|
|
94
|
+
Per veure els comandaments disponibles:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npx harmonix --help
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## ✅ Exemple complet
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx harmonix publish --registry https://plugins.harmonix.dev/upload --api-key ABC123XYZ
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
O bé, si tens `.harmonixrc` configurat:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npx harmonix publish
|
|
112
|
+
```
|
|
113
|
+
|
package/index.js
CHANGED
|
@@ -3,35 +3,58 @@
|
|
|
3
3
|
const { program } = require('commander');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
|
+
const os = require('os');
|
|
6
7
|
const axios = require('axios');
|
|
7
8
|
const FormData = require('form-data');
|
|
8
9
|
|
|
9
10
|
console.log("reached index");
|
|
10
11
|
|
|
11
12
|
function getConfig() {
|
|
12
|
-
const configPath = path.resolve(process.cwd(), ".harmonixrc");
|
|
13
13
|
const config = {};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
console.log(config)
|
|
27
|
-
} catch (err) {
|
|
28
|
-
console.warn("⚠️ Warning: Error reading .harmonixrc:", err.message);
|
|
14
|
+
let dir = process.cwd();
|
|
15
|
+
let steps = 0;
|
|
16
|
+
const maxSteps = 10;
|
|
17
|
+
|
|
18
|
+
while (steps < maxSteps) {
|
|
19
|
+
const configPath = path.join(dir, '.harmonixrc');
|
|
20
|
+
if (fs.existsSync(configPath)) {
|
|
21
|
+
Object.assign(config, parseConfigFile(configPath));
|
|
22
|
+
break; // stop at first .harmonixrc found
|
|
29
23
|
}
|
|
24
|
+
|
|
25
|
+
const parent = path.dirname(dir);
|
|
26
|
+
if (parent === dir) break; // reached filesystem root
|
|
27
|
+
dir = parent;
|
|
28
|
+
steps++;
|
|
29
|
+
}
|
|
30
|
+
|
|
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));
|
|
30
35
|
}
|
|
31
|
-
|
|
36
|
+
|
|
32
37
|
return config;
|
|
33
38
|
}
|
|
34
39
|
|
|
40
|
+
function parseConfigFile(filePath) {
|
|
41
|
+
const result = {};
|
|
42
|
+
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('=');
|
|
47
|
+
if (key && value) {
|
|
48
|
+
result[key.trim()] = value.trim();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.warn(`⚠️ Error reading ${filePath}:`, err.message);
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
35
58
|
program
|
|
36
59
|
.command('publish')
|
|
37
60
|
.option('--registry <registry>', 'Backend URL (overrides .harmonixrc)')
|
|
@@ -42,7 +65,7 @@ program
|
|
|
42
65
|
const packageJsonPath = path.resolve(process.cwd(), "package.json");
|
|
43
66
|
|
|
44
67
|
if (!fs.existsSync(packageJsonPath)) {
|
|
45
|
-
console.error(
|
|
68
|
+
console.error(`❌ package.json not found in: ${process.cwd()}`);
|
|
46
69
|
process.exit(1);
|
|
47
70
|
}
|
|
48
71
|
|
|
@@ -56,30 +79,29 @@ program
|
|
|
56
79
|
|
|
57
80
|
const filePath = path.resolve(process.cwd(), module);
|
|
58
81
|
if (!fs.existsSync(filePath)) {
|
|
59
|
-
console.error(
|
|
82
|
+
console.error(`❌ Compiled bundle file not found: ${filePath}`);
|
|
60
83
|
process.exit(1);
|
|
61
84
|
}
|
|
62
85
|
|
|
63
86
|
const formData = new FormData();
|
|
64
87
|
formData.append("versionNumber", versionNumber);
|
|
65
88
|
formData.append("pluginId", pluginId);
|
|
66
|
-
formData.append(
|
|
89
|
+
formData.append("file", fs.createReadStream(filePath));
|
|
67
90
|
|
|
68
91
|
const registry = opts.registry || config.registry;
|
|
69
92
|
const apiKey = opts.apiKey || config.apiKey;
|
|
70
93
|
|
|
71
|
-
if(!registry){
|
|
72
|
-
throw new Error("No registry configured")
|
|
94
|
+
if (!registry) {
|
|
95
|
+
throw new Error("No registry configured");
|
|
73
96
|
}
|
|
74
|
-
if(!apiKey){
|
|
75
|
-
throw new Error("No
|
|
97
|
+
if (!apiKey) {
|
|
98
|
+
throw new Error("No API key configured");
|
|
76
99
|
}
|
|
77
|
-
|
|
78
|
-
const headers =
|
|
100
|
+
|
|
101
|
+
const headers = {
|
|
79
102
|
'x-api-key': apiKey
|
|
80
103
|
};
|
|
81
104
|
const response = await axios.post(registry, formData, { headers });
|
|
82
|
-
|
|
83
105
|
console.log('✅ Plugin published:', response.data);
|
|
84
106
|
} catch (err) {
|
|
85
107
|
console.error('❌ Failed to publish:', err.message);
|