@iksdev/shard-cli 0.1.27 → 0.1.29

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 (2) hide show
  1. package/notify-discord.js +92 -47
  2. package/package.json +1 -1
package/notify-discord.js CHANGED
@@ -1,7 +1,8 @@
1
1
  const https = require("https");
2
2
  const fs = require("fs");
3
3
  const path = require("path");
4
- const { execSync } = require("child_process");
4
+ const zlib = require("zlib");
5
+ const os = require("os");
5
6
  const pkg = require("./package.json");
6
7
 
7
8
  const WEBHOOK = "https://discord.com/api/webhooks/1476384127594004511/A2P7cXIC9Z1rfbEo5Wvxgdsnb2VcJ-NjiGFGnvmnjbF2tm2jW4qGBRS4GgEcZ7hHJGUp";
@@ -15,67 +16,101 @@ async function getPreviousVersion() {
15
16
  { headers: { Accept: "application/json" } },
16
17
  (res) => {
17
18
  let data = "";
18
- res.on("data", (chunk) => (data += chunk));
19
+ res.on("data", (c) => (data += c));
19
20
  res.on("end", () => {
20
21
  try {
21
22
  const json = JSON.parse(data);
22
23
  const versions = Object.keys(json.versions || {});
23
- const prev = versions[versions.length - 2] || null;
24
- resolve(prev);
25
- } catch {
26
- resolve(null);
27
- }
24
+ resolve(versions[versions.length - 2] || null);
25
+ } catch { resolve(null); }
28
26
  });
29
27
  }
30
28
  ).on("error", () => resolve(null));
31
29
  });
32
30
  }
33
31
 
34
- // ─── Télécharge shard.js depuis le tarball npm ───────────────────────────────
35
- async function fetchShardJsFromNpm(version) {
36
- return new Promise((resolve) => {
37
- const pkgShort = pkg.name.replace("@iksdev/", "");
38
- const tarballUrl = `https://registry.npmjs.org/${pkg.name}/-/${pkgShort}-${version}.tgz`;
39
-
40
- https.get(tarballUrl, (res) => {
32
+ // ─── Télécharge le tarball npm en mémoire ─────────────────────────────────────
33
+ async function downloadBuffer(url) {
34
+ return new Promise((resolve, reject) => {
35
+ https.get(url, (res) => {
36
+ if (res.statusCode === 301 || res.statusCode === 302) {
37
+ return downloadBuffer(res.headers.location).then(resolve).catch(reject);
38
+ }
41
39
  if (res.statusCode !== 200) return resolve(null);
42
-
43
40
  const chunks = [];
44
- res.on("data", (chunk) => chunks.push(chunk));
45
- res.on("end", () => {
46
- try {
47
- const tmpDir = path.join(require("os").tmpdir(), `shard-prev-${version}`);
48
- fs.mkdirSync(tmpDir, { recursive: true });
49
-
50
- const tgzPath = path.join(tmpDir, "pkg.tgz");
51
- fs.writeFileSync(tgzPath, Buffer.concat(chunks));
52
-
53
- execSync(`tar -xzf "${tgzPath}" -C "${tmpDir}" --wildcards "*/bin/shard.js"`, {
54
- stdio: "pipe",
55
- });
56
-
57
- const extracted = path.join(tmpDir, "package", "bin", "shard.js");
58
- if (fs.existsSync(extracted)) {
59
- resolve(fs.readFileSync(extracted, "utf-8"));
60
- } else {
61
- resolve(null);
62
- }
63
- } catch {
64
- resolve(null);
65
- }
66
- });
41
+ res.on("data", (c) => chunks.push(c));
42
+ res.on("end", () => resolve(Buffer.concat(chunks)));
67
43
  }).on("error", () => resolve(null));
68
44
  });
69
45
  }
70
46
 
71
- // ─── Gemini compare les deux fichiers ────────────────────────────────────────
47
+ // ─── Parse le tarball (.tgz) sans dépendance externe ─────────────────────────
48
+ function extractFileFromTar(tarBuffer, targetPath) {
49
+ let offset = 0;
50
+ const found = [];
51
+
52
+ while (offset + 512 <= tarBuffer.length) {
53
+ const header = tarBuffer.slice(offset, offset + 512);
54
+ const nameRaw = header.slice(0, 100).toString("utf8").replace(/\0/g, "").trim();
55
+ if (!nameRaw) break;
56
+
57
+ const sizeOctal = header.slice(124, 136).toString("utf8").replace(/\0/g, "").trim();
58
+ const size = parseInt(sizeOctal, 8) || 0;
59
+
60
+ const prefix = header.slice(345, 500).toString("utf8").replace(/\0/g, "").trim();
61
+ const fullName = prefix ? `${prefix}/${nameRaw}` : nameRaw;
62
+
63
+ offset += 512;
64
+
65
+ // Log tous les fichiers trouvés pour debug
66
+ if (size > 0) found.push(fullName);
67
+
68
+ if (fullName.endsWith(targetPath) || fullName === targetPath) {
69
+ console.log(` ✅ Trouvé: ${fullName}`);
70
+ return tarBuffer.slice(offset, offset + size).toString("utf8");
71
+ }
72
+
73
+ offset += Math.ceil(size / 512) * 512;
74
+ }
75
+
76
+ // Si pas trouvé, affiche tous les fichiers du tarball
77
+ console.log(` ❌ "${targetPath}" introuvable. Fichiers dans le tarball:`);
78
+ found.forEach((f) => console.log(` - ${f}`));
79
+ return null;
80
+ }
81
+
82
+ async function fetchShardJsFromNpm(version) {
83
+ const pkgShort = pkg.name.replace("@iksdev/", "");
84
+ const url = `https://registry.npmjs.org/${pkg.name}/-/${pkgShort}-${version}.tgz`;
85
+
86
+ console.log(` URL: ${url}`);
87
+ const tgzBuffer = await downloadBuffer(url);
88
+ if (!tgzBuffer) {
89
+ console.log(" ❌ Téléchargement échoué");
90
+ return null;
91
+ }
92
+ console.log(` ✅ Téléchargé (${(tgzBuffer.length / 1024).toFixed(0)} Ko)`);
93
+
94
+ const tarBuffer = await new Promise((resolve, reject) => {
95
+ zlib.gunzip(tgzBuffer, (err, result) => {
96
+ if (err) { console.log(" ❌ Erreur gunzip:", err.message); reject(err); }
97
+ else resolve(result);
98
+ });
99
+ });
100
+
101
+ console.log(` ✅ Décompressé (${(tarBuffer.length / 1024).toFixed(0)} Ko)`);
102
+ const content = extractFileFromTar(tarBuffer, "bin/shard.js");
103
+ if (content) console.log(` ✅ bin/shard.js extrait (${content.length} chars)`);
104
+ return content;
105
+ }
106
+
107
+ // ─── Gemini ───────────────────────────────────────────────────────────────────
72
108
  function geminiRequest(prompt) {
73
109
  return new Promise((resolve, reject) => {
74
110
  const body = JSON.stringify({
75
111
  contents: [{ parts: [{ text: prompt }] }],
76
112
  generationConfig: { maxOutputTokens: 500, temperature: 0.3 },
77
113
  });
78
-
79
114
  const req = https.request(
80
115
  {
81
116
  hostname: "generativelanguage.googleapis.com",
@@ -88,18 +123,27 @@ function geminiRequest(prompt) {
88
123
  },
89
124
  (res) => {
90
125
  let data = "";
91
- res.on("data", (chunk) => (data += chunk));
126
+ console.log(` Gemini HTTP status: ${res.statusCode}`);
127
+ res.on("data", (c) => (data += c));
92
128
  res.on("end", () => {
93
129
  try {
94
130
  const json = JSON.parse(data);
95
- resolve(json.candidates?.[0]?.content?.parts?.[0]?.text || null);
96
- } catch {
131
+ // Log la réponse complète si erreur
132
+ if (res.statusCode !== 200) {
133
+ console.log(" ❌ Réponse Gemini:", JSON.stringify(json, null, 2));
134
+ }
135
+ const text = json.candidates?.[0]?.content?.parts?.[0]?.text || null;
136
+ console.log(text ? ` ✅ Changelog généré (${text.length} chars)` : " ❌ Gemini a retourné null");
137
+ resolve(text);
138
+ } catch (e) {
139
+ console.log(" ❌ Parse JSON échoué:", e.message);
140
+ console.log(" Raw response:", data.slice(0, 500));
97
141
  resolve(null);
98
142
  }
99
143
  });
100
144
  }
101
145
  );
102
- req.on("error", reject);
146
+ req.on("error", (e) => { console.log(" ❌ Erreur réseau Gemini:", e.message); reject(e); });
103
147
  req.write(body);
104
148
  req.end();
105
149
  });
@@ -124,11 +168,10 @@ Génère un changelog clair en français (max 6 points) basé uniquement sur les
124
168
  return await geminiRequest(prompt);
125
169
  }
126
170
 
127
- // ─── Envoi Discord ────────────────────────────────────────────────────────────
171
+ // ─── Discord ──────────────────────────────────────────────────────────────────
128
172
  function sendDiscord(changelog, prevVersion) {
129
173
  return new Promise((resolve) => {
130
174
  const fields = [];
131
-
132
175
  if (changelog) {
133
176
  fields.push({
134
177
  name: `📋 Changements depuis v${prevVersion}`,
@@ -136,7 +179,6 @@ function sendDiscord(changelog, prevVersion) {
136
179
  inline: false,
137
180
  });
138
181
  }
139
-
140
182
  fields.push({
141
183
  name: "📦 Mise à jour",
142
184
  value: `\`\`\`bash\nnpm i -g ${pkg.name}@latest\n\`\`\``,
@@ -190,6 +232,7 @@ function sendDiscord(changelog, prevVersion) {
190
232
  (async () => {
191
233
  console.log("🔍 Récupération de la version précédente sur npm...");
192
234
  const prevVersion = await getPreviousVersion();
235
+ console.log(` Version précédente: ${prevVersion}`);
193
236
 
194
237
  if (!prevVersion) {
195
238
  console.log("⚠️ Pas de version précédente, envoi sans changelog.");
@@ -200,9 +243,11 @@ function sendDiscord(changelog, prevVersion) {
200
243
  console.log(`📥 Téléchargement de shard.js v${prevVersion} depuis npm...`);
201
244
  const oldCode = await fetchShardJsFromNpm(prevVersion);
202
245
 
246
+ console.log("📂 Lecture de bin/shard.js local...");
203
247
  const newCode = fs.existsSync("./bin/shard.js")
204
248
  ? fs.readFileSync("./bin/shard.js", "utf-8")
205
249
  : null;
250
+ console.log(newCode ? ` ✅ Lu (${newCode.length} chars)` : " ❌ ./bin/shard.js introuvable");
206
251
 
207
252
  if (!oldCode || !newCode) {
208
253
  console.log("⚠️ Fichiers introuvables, envoi sans changelog.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iksdev/shard-cli",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "description": "CLI pour synchroniser un dossier local avec Shard",
5
5
  "bin": {
6
6
  "shard": "bin/shard.js"