multicloud_rule_manager 1.1.79 โ†’ 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,175 +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
- `https://${cred.realm}.bit2win.cloud/api/data/v1/rules/`,
42
- {
43
- method: "GET",
60
+ `https://${cred.realm}.bit2win.cloud/api/data/v1/products`,
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
- const data = await apiResp.json();
55
-
56
-
57
- // Controlla che sia array
58
- if (!Array.isArray(data)) {
59
- throw new Error("La risposta API non รจ una lista di oggetti");
60
- }
61
-
62
- console.log(" Chiamo products"+argv.productName);
63
69
  const products = await safeJson(apiResp, "products");
70
+ console.log(`๐Ÿ“ฆ Totale products ricevuti: ${products.length}`);
64
71
 
65
- console.log(" Chiamo products finita "+argv.productName);
66
- const product = products.find(p => p.name === argv.productName);
72
+ const product = products.find(
73
+ (p) => p.name === argv.productName
74
+ );
67
75
 
68
76
  if (!product) {
69
77
  throw new Error(`Prodotto "${argv.productName}" non trovato`);
70
78
  }
71
79
 
72
- const rootGuid = product.guid;
73
-
74
-
80
+ console.log(`โœ… Prodotto trovato: ${product.name}`);
75
81
 
82
+ const rootGuid = product.guid;
76
83
 
77
84
  // =========================
78
85
  // ๐ŸŒณ STRUCTURE
79
86
  // =========================
80
-
81
- console.log("Chiamo products structure");
87
+ console.log("๐Ÿ”น Chiamo structure...");
82
88
 
83
89
  const structResp = await fetch(
84
- `https://${cred.realm}.bit2win.cloud/api/data/v1/products_structure/`,
85
- {
86
- method: "GET",
90
+ `https://${cred.realm}.bit2win.cloud/api/data/v1/products_structure`,
91
+ {
87
92
  headers: {
88
- "Authorization": `Bearer ${access_token}`,
89
- "Accept": "application/json"
93
+ Authorization: `Bearer ${access_token}`,
94
+ Accept: "application/json",
90
95
  },
91
- redirect: "manual"
92
96
  }
93
97
  );
94
98
 
95
- 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}`);
96
105
 
97
106
  // =========================
98
107
  // ๐Ÿ“‚ HELPERS
99
108
  // =========================
100
- const sortByName = arr =>
101
- 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
+ );
102
113
 
103
114
  const getCategories = () =>
104
115
  sortByName(
105
116
  structure.filter(
106
- e => e.parent_guid === rootGuid && e.type === "category"
117
+ (e) =>
118
+ e.parent_guid === rootGuid &&
119
+ e.type === "category"
107
120
  )
108
121
  );
109
122
 
110
123
  const getChildren = (categoryGuid) =>
111
124
  sortByName(
112
- structure.filter(e => e.parent_guid === categoryGuid)
125
+ structure.filter(
126
+ (e) => e.parent_guid === categoryGuid
127
+ )
113
128
  );
114
129
 
115
130
  // =========================
116
131
  // ๐Ÿ“ก FAMILIES
117
132
  // =========================
118
-
119
- console.log("Chiamo families");
120
-
121
133
  const getFamilies = async (productId) => {
122
134
  const resp = await fetch(
123
135
  `https://${cred.realm}.bit2win.cloud/api/catalog/v1/products/${productId}/families`,
124
- {
125
- method: "GET",
126
- headers: {
127
- "Authorization": `Bearer ${access_token}`,
128
- "Accept": "application/json"
129
- },
130
- redirect: "manual"
131
- }
132
- );
133
-
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
+ );
134
152
 
135
- const data = await safeJson(resp, `families:${productId}`);
153
+ totalFamilies += data.length;
136
154
 
137
- return (data || [])
138
- .sort((a, b) => a.name.localeCompare(b.name))
139
- .map(f => ({
155
+ return (data || []).map((f) => {
156
+ totalAttributes += (f.attributes || []).length;
157
+
158
+ return {
140
159
  name: f.name,
141
160
  visible: f.visible,
142
161
  visible_web: f.visible_web,
143
- attributes: (f.attributes || [])
144
- .sort((a, b) => a.name.localeCompare(b.name))
145
- .map(a => ({
162
+ attributes: (f.attributes || []).map((a) => {
163
+ totalDomains += (a.domains || []).length;
164
+
165
+ return {
146
166
  name: a.name,
147
167
  value_default: a.value_default,
148
168
  read_only: a.read_only,
149
169
  required: a.required,
150
170
  visible: a.visible,
151
- domains: (a.domains || [])
152
- .sort((a, b) => (a.value || "").localeCompare(b.value || ""))
153
- .map(d => ({
154
- value: d.value,
155
- visible: d.visible,
156
- default: d.default
157
- }))
158
- }))
159
- }));
171
+ domains: a.domains || [],
172
+ };
173
+ }),
174
+ };
175
+ });
160
176
  };
161
177
 
162
178
  // =========================
163
- // ๐Ÿ“Š DATASET 1
179
+ // ๐Ÿ“Š DATASET
164
180
  // =========================
165
181
  const rows1 = [];
182
+ const rows2 = [];
166
183
 
167
184
  const categories = getCategories();
185
+ totalCategories = categories.length;
186
+
187
+ console.log(`๐Ÿ“‚ Totale categorie: ${categories.length}`);
168
188
 
169
189
  for (const cat of categories) {
170
190
  const children = getChildren(cat.guid);
171
191
 
192
+ console.log(
193
+ `โžก๏ธ Categoria "${cat.name}" โ†’ ${children.length} children`
194
+ );
195
+
196
+ totalChildren += children.length;
197
+
172
198
  if (children.length === 0) {
173
199
  rows1.push({
174
200
  product: product.name,
175
201
  category: cat.name,
176
- child: ""
202
+ child: "",
177
203
  });
178
204
  }
179
205
 
@@ -181,23 +207,14 @@ export default {
181
207
  rows1.push({
182
208
  product: product.name,
183
209
  category: cat.name,
184
- child: child.name
210
+ child: child.name,
185
211
  });
186
- }
187
- }
188
-
189
- // =========================
190
- // ๐Ÿ“Š DATASET 2
191
- // =========================
192
- const rows2 = [];
193
-
194
- for (const cat of categories) {
195
- const children = getChildren(cat.guid);
196
212
 
197
- for (const child of children) {
198
213
  if (!child.product_id) continue;
199
214
 
200
- const families = await getFamilies(child.product_id);
215
+ const families = await getFamilies(
216
+ child.product_id
217
+ );
201
218
 
202
219
  for (const f of families) {
203
220
  for (const attr of f.attributes) {
@@ -207,15 +224,8 @@ export default {
207
224
  category: cat.name,
208
225
  child: child.name,
209
226
  family: f.name,
210
- family_visible: f.visible,
211
- family_visible_web: f.visible_web,
212
227
  attribute: attr.name,
213
- attr_default: attr.value_default,
214
- attr_required: attr.required,
215
- attr_visible: attr.visible,
216
228
  domain_value: dom.value,
217
- domain_visible: dom.visible,
218
- domain_default: dom.default
219
229
  });
220
230
  }
221
231
  }
@@ -224,15 +234,17 @@ export default {
224
234
  }
225
235
 
226
236
  // =========================
227
- // ๐Ÿ”ค SORT GLOBALE
237
+ // ๐Ÿ“Š RISULTATI
228
238
  // =========================
229
- const sortRows = (rows) =>
230
- rows.sort((a, b) =>
231
- Object.values(a).join("|").localeCompare(Object.values(b).join("|"))
232
- );
239
+ console.log(`๐Ÿ“Š Righe dataset 1: ${rows1.length}`);
240
+ console.log(`๐Ÿ“Š Righe dataset 2: ${rows2.length}`);
233
241
 
234
- const sorted1 = sortRows(rows1);
235
- 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}`);
236
248
 
237
249
  // =========================
238
250
  // ๐Ÿ“ EXCEL
@@ -244,8 +256,8 @@ export default {
244
256
  XLSX.writeFile(wb, fileName);
245
257
  };
246
258
 
247
- writeExcel("product_structure.xlsx", sorted1);
248
- writeExcel("product_details.xlsx", sorted2);
259
+ writeExcel("product_structure.xlsx", rows1);
260
+ writeExcel("product_details.xlsx", rows2);
249
261
 
250
262
  console.log("โœ… Excel generati con successo");
251
263
 
@@ -253,28 +265,20 @@ export default {
253
265
  console.error("โŒ Errore:", err.message);
254
266
  }
255
267
 
256
-
257
-
258
268
  async function safeJson(resp, label) {
259
269
  const text = await resp.text();
260
- console.log("RAW products:", resp);
261
- console.log("RAW products:", text);
262
270
 
263
271
  if (!resp.ok) {
264
- 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
+ );
265
275
  }
266
276
 
267
277
  if (!text) {
268
278
  throw new Error(`${label} risposta vuota`);
269
279
  }
270
280
 
271
- try {
272
- return JSON.parse(text);
273
- } catch (e) {
274
- throw new Error(`${label} NON JSON valido: ${text.slice(0, 200)}`);
275
- }
281
+ return JSON.parse(text);
276
282
  }
277
-
278
-
279
- }
283
+ },
280
284
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multicloud_rule_manager",
3
- "version": "1.1.79",
3
+ "version": "1.1.81",
4
4
  "description": "CLI interna per retrieve/upload con token",
5
5
  "main": "index.js",
6
6
  "type": "module",