multicloud_rule_manager 1.1.80 → 1.1.81

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.
@@ -5,167 +5,201 @@ import { getAlias } from "../utils/aliasManager.js";
5
5
  export default {
6
6
  command: "retrieveproduct <alias> <productName>",
7
7
  describe: "Recupera struttura prodotto e genera Excel",
8
- handler: async (argv) => {
8
+
9
+ handler: async (argv) => {
9
10
  try {
10
11
  console.log("🔹 Retrieve in corso..");
11
12
  console.log("🔹 Recupero credenziali per alias:", argv.alias);
13
+
12
14
  const cred = getAlias(argv.alias);
13
15
 
14
- // --- PRIMA CHIAMATA: token ---
16
+ // =========================
17
+ // 🔢 CONTATORI GLOBALI
18
+ // =========================
19
+ let totalCategories = 0;
20
+ let totalChildren = 0;
21
+ let totalFamilies = 0;
22
+ let totalAttributes = 0;
23
+ let totalDomains = 0;
24
+
25
+ // =========================
26
+ // 🔑 TOKEN
27
+ // =========================
15
28
  console.log("🔹 Inizio richiesta token...");
16
- const loginResp = await fetch(`https://login-eon-no-prod.bit2win.cloud/auth/realms/${cred.realm}/protocol/openid-connect/token`, {
17
- method: "POST",
18
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
19
- body: new URLSearchParams({
20
- client_id: cred.clientId,
21
- client_secret: cred.clientSecret,
22
- username: cred.username,
23
- password: cred.password,
24
- grant_type: "password"
25
- })
26
- });
27
-
28
- const loginData = await loginResp.json(); // leggi direttamente JSON
29
+
30
+ const loginResp = await fetch(
31
+ `https://login-eon-no-prod.bit2win.cloud/auth/realms/${cred.realm}/protocol/openid-connect/token`,
32
+ {
33
+ method: "POST",
34
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
35
+ body: new URLSearchParams({
36
+ client_id: cred.clientId,
37
+ client_secret: cred.clientSecret,
38
+ username: cred.username,
39
+ password: cred.password,
40
+ grant_type: "password",
41
+ }),
42
+ }
43
+ );
44
+
45
+ const loginData = await loginResp.json();
29
46
  const access_token = loginData.access_token;
30
47
 
31
48
  if (!access_token) {
32
- throw new Error("Token non ricevuto nel campo 'access_token'");
49
+ throw new Error("Token non ricevuto");
33
50
  }
34
51
 
52
+ console.log("✅ Token ricevuto");
35
53
 
54
+ // =========================
55
+ // 📦 PRODUCTS
56
+ // =========================
57
+ console.log("🔹 Chiamo products...");
36
58
 
37
-
38
- // --- SECONDA CHIAMATA: retrieve ---
39
- console.log("🔹 Inizio richiesta dati API...");
40
59
  const apiResp = await fetch(
41
60
  `https://${cred.realm}.bit2win.cloud/api/data/v1/products`,
42
- {
43
- method: "GET",
61
+ {
44
62
  headers: {
45
- "Authorization": `Bearer ${access_token}`,
46
- "Accept": "application/json"
63
+ Authorization: `Bearer ${access_token}`,
64
+ Accept: "application/json",
47
65
  },
48
- redirect: "manual"
49
66
  }
50
67
  );
51
68
 
52
-
53
-
54
- console.log(" Chiamo products"+argv.productName);
55
69
  const products = await safeJson(apiResp, "products");
70
+ console.log(`📦 Totale products ricevuti: ${products.length}`);
56
71
 
57
- console.log(" Chiamo products finita "+argv.productName);
58
- const product = products.find(p => p.name === argv.productName);
72
+ const product = products.find(
73
+ (p) => p.name === argv.productName
74
+ );
59
75
 
60
76
  if (!product) {
61
77
  throw new Error(`Prodotto "${argv.productName}" non trovato`);
62
78
  }
63
79
 
64
- const rootGuid = product.guid;
65
-
66
-
80
+ console.log(`✅ Prodotto trovato: ${product.name}`);
67
81
 
82
+ const rootGuid = product.guid;
68
83
 
69
84
  // =========================
70
85
  // 🌳 STRUCTURE
71
86
  // =========================
72
-
73
- console.log("Chiamo products structure");
87
+ console.log("🔹 Chiamo structure...");
74
88
 
75
89
  const structResp = await fetch(
76
90
  `https://${cred.realm}.bit2win.cloud/api/data/v1/products_structure`,
77
- {
78
- method: "GET",
91
+ {
79
92
  headers: {
80
- "Authorization": `Bearer ${access_token}`,
81
- "Accept": "application/json"
93
+ Authorization: `Bearer ${access_token}`,
94
+ Accept: "application/json",
82
95
  },
83
- redirect: "manual"
84
96
  }
85
97
  );
86
98
 
87
- const structure = await safeJson(structResp, "products_structure");
99
+ const structure = await safeJson(
100
+ structResp,
101
+ "products_structure"
102
+ );
103
+
104
+ console.log(`🌳 Totale elementi structure: ${structure.length}`);
88
105
 
89
106
  // =========================
90
107
  // 📂 HELPERS
91
108
  // =========================
92
- const sortByName = arr =>
93
- arr.sort((a, b) => (a.name || "").localeCompare(b.name || ""));
109
+ const sortByName = (arr) =>
110
+ arr.sort((a, b) =>
111
+ (a.name || "").localeCompare(b.name || "")
112
+ );
94
113
 
95
114
  const getCategories = () =>
96
115
  sortByName(
97
116
  structure.filter(
98
- e => e.parent_guid === rootGuid && e.type === "category"
117
+ (e) =>
118
+ e.parent_guid === rootGuid &&
119
+ e.type === "category"
99
120
  )
100
121
  );
101
122
 
102
123
  const getChildren = (categoryGuid) =>
103
124
  sortByName(
104
- structure.filter(e => e.parent_guid === categoryGuid)
125
+ structure.filter(
126
+ (e) => e.parent_guid === categoryGuid
127
+ )
105
128
  );
106
129
 
107
130
  // =========================
108
131
  // 📡 FAMILIES
109
132
  // =========================
110
-
111
- console.log("Chiamo families");
112
-
113
133
  const getFamilies = async (productId) => {
114
134
  const resp = await fetch(
115
135
  `https://${cred.realm}.bit2win.cloud/api/catalog/v1/products/${productId}/families`,
116
- {
117
- method: "GET",
118
- headers: {
119
- "Authorization": `Bearer ${access_token}`,
120
- "Accept": "application/json"
121
- },
122
- redirect: "manual"
123
- }
124
- );
125
-
136
+ {
137
+ headers: {
138
+ Authorization: `Bearer ${access_token}`,
139
+ Accept: "application/json",
140
+ },
141
+ }
142
+ );
143
+
144
+ const data = await safeJson(
145
+ resp,
146
+ `families:${productId}`
147
+ );
148
+
149
+ console.log(
150
+ `👨‍👩‍👧 Product ${productId} → ${data.length} families`
151
+ );
152
+
153
+ totalFamilies += data.length;
126
154
 
127
- const data = await safeJson(resp, `families:${productId}`);
155
+ return (data || []).map((f) => {
156
+ totalAttributes += (f.attributes || []).length;
128
157
 
129
- return (data || [])
130
- .sort((a, b) => a.name.localeCompare(b.name))
131
- .map(f => ({
158
+ return {
132
159
  name: f.name,
133
160
  visible: f.visible,
134
161
  visible_web: f.visible_web,
135
- attributes: (f.attributes || [])
136
- .sort((a, b) => a.name.localeCompare(b.name))
137
- .map(a => ({
162
+ attributes: (f.attributes || []).map((a) => {
163
+ totalDomains += (a.domains || []).length;
164
+
165
+ return {
138
166
  name: a.name,
139
167
  value_default: a.value_default,
140
168
  read_only: a.read_only,
141
169
  required: a.required,
142
170
  visible: a.visible,
143
- domains: (a.domains || [])
144
- .sort((a, b) => (a.value || "").localeCompare(b.value || ""))
145
- .map(d => ({
146
- value: d.value,
147
- visible: d.visible,
148
- default: d.default
149
- }))
150
- }))
151
- }));
171
+ domains: a.domains || [],
172
+ };
173
+ }),
174
+ };
175
+ });
152
176
  };
153
177
 
154
178
  // =========================
155
- // 📊 DATASET 1
179
+ // 📊 DATASET
156
180
  // =========================
157
181
  const rows1 = [];
182
+ const rows2 = [];
158
183
 
159
184
  const categories = getCategories();
185
+ totalCategories = categories.length;
186
+
187
+ console.log(`📂 Totale categorie: ${categories.length}`);
160
188
 
161
189
  for (const cat of categories) {
162
190
  const children = getChildren(cat.guid);
163
191
 
192
+ console.log(
193
+ `➡️ Categoria "${cat.name}" → ${children.length} children`
194
+ );
195
+
196
+ totalChildren += children.length;
197
+
164
198
  if (children.length === 0) {
165
199
  rows1.push({
166
200
  product: product.name,
167
201
  category: cat.name,
168
- child: ""
202
+ child: "",
169
203
  });
170
204
  }
171
205
 
@@ -173,23 +207,14 @@ export default {
173
207
  rows1.push({
174
208
  product: product.name,
175
209
  category: cat.name,
176
- child: child.name
210
+ child: child.name,
177
211
  });
178
- }
179
- }
180
212
 
181
- // =========================
182
- // 📊 DATASET 2
183
- // =========================
184
- const rows2 = [];
185
-
186
- for (const cat of categories) {
187
- const children = getChildren(cat.guid);
188
-
189
- for (const child of children) {
190
213
  if (!child.product_id) continue;
191
214
 
192
- const families = await getFamilies(child.product_id);
215
+ const families = await getFamilies(
216
+ child.product_id
217
+ );
193
218
 
194
219
  for (const f of families) {
195
220
  for (const attr of f.attributes) {
@@ -199,15 +224,8 @@ export default {
199
224
  category: cat.name,
200
225
  child: child.name,
201
226
  family: f.name,
202
- family_visible: f.visible,
203
- family_visible_web: f.visible_web,
204
227
  attribute: attr.name,
205
- attr_default: attr.value_default,
206
- attr_required: attr.required,
207
- attr_visible: attr.visible,
208
228
  domain_value: dom.value,
209
- domain_visible: dom.visible,
210
- domain_default: dom.default
211
229
  });
212
230
  }
213
231
  }
@@ -216,15 +234,17 @@ export default {
216
234
  }
217
235
 
218
236
  // =========================
219
- // 🔤 SORT GLOBALE
237
+ // 📊 RISULTATI
220
238
  // =========================
221
- const sortRows = (rows) =>
222
- rows.sort((a, b) =>
223
- Object.values(a).join("|").localeCompare(Object.values(b).join("|"))
224
- );
239
+ console.log(`📊 Righe dataset 1: ${rows1.length}`);
240
+ console.log(`📊 Righe dataset 2: ${rows2.length}`);
225
241
 
226
- const sorted1 = sortRows(rows1);
227
- const sorted2 = sortRows(rows2);
242
+ console.log("📈 STATISTICHE GLOBALI:");
243
+ console.log(`Categorie: ${totalCategories}`);
244
+ console.log(`Children: ${totalChildren}`);
245
+ console.log(`Families: ${totalFamilies}`);
246
+ console.log(`Attributi: ${totalAttributes}`);
247
+ console.log(`Domini: ${totalDomains}`);
228
248
 
229
249
  // =========================
230
250
  // 📁 EXCEL
@@ -236,8 +256,8 @@ export default {
236
256
  XLSX.writeFile(wb, fileName);
237
257
  };
238
258
 
239
- writeExcel("product_structure.xlsx", sorted1);
240
- writeExcel("product_details.xlsx", sorted2);
259
+ writeExcel("product_structure.xlsx", rows1);
260
+ writeExcel("product_details.xlsx", rows2);
241
261
 
242
262
  console.log("✅ Excel generati con successo");
243
263
 
@@ -245,28 +265,20 @@ export default {
245
265
  console.error("❌ Errore:", err.message);
246
266
  }
247
267
 
248
-
249
-
250
268
  async function safeJson(resp, label) {
251
269
  const text = await resp.text();
252
- console.log("RAW products:", resp);
253
- console.log("RAW products:", text);
254
270
 
255
271
  if (!resp.ok) {
256
- throw new Error(`${label} HTTP ${resp.status}: ${text.slice(0, 200)}`);
272
+ throw new Error(
273
+ `${label} HTTP ${resp.status}: ${text.slice(0, 200)}`
274
+ );
257
275
  }
258
276
 
259
277
  if (!text) {
260
278
  throw new Error(`${label} risposta vuota`);
261
279
  }
262
280
 
263
- try {
264
- return JSON.parse(text);
265
- } catch (e) {
266
- throw new Error(`${label} NON JSON valido: ${text.slice(0, 200)}`);
267
- }
281
+ return JSON.parse(text);
268
282
  }
269
-
270
-
271
- }
283
+ },
272
284
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multicloud_rule_manager",
3
- "version": "1.1.80",
3
+ "version": "1.1.81",
4
4
  "description": "CLI interna per retrieve/upload con token",
5
5
  "main": "index.js",
6
6
  "type": "module",