uvako-cli 0.3.0 → 0.4.0

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/src/remote.js CHANGED
@@ -5,6 +5,7 @@ import { printReport } from "./check.js";
5
5
  import { dropSession, saveSession, session, sessions, storeOrigin } from "./config.js";
6
6
  import { buildArchive } from "./package.js";
7
7
  import { unzip } from "./zip.js";
8
+ import { t, tm } from "./i18n.js";
8
9
 
9
10
  // Mağazayla konuşan komutlar: giriş, yükleme, canlı geliştirme, indirme, incelemeye gönderme.
10
11
 
@@ -35,7 +36,7 @@ function askSecret(question) {
35
36
  const onData = (chunk) => {
36
37
  for (const char of chunk) {
37
38
  if (char === "\r" || char === "\n") return done(resolve, value.trim());
38
- if (char === "\u0003") return done(reject, new Error("İptal edildi."));
39
+ if (char === "\u0003") return done(reject, new Error(t("İptal edildi.")));
39
40
  if (char === "\u007f" || char === "\b") value = value.slice(0, -1);
40
41
  else if (char >= " ") value += char;
41
42
  }
@@ -46,9 +47,9 @@ function askSecret(question) {
46
47
 
47
48
  function explain(error) {
48
49
  if (!(error instanceof ApiError)) throw error;
49
- console.error(`✖ ${error.message}`);
50
- for (const problem of error.problems) console.error(` ✖ ${problem}`);
51
- if (error.status === 401) console.error(" Yeni anahtar: mağaza paneli → Ayarlar → Temalar → Geliştirici erişimi, sonra `uvako login`.");
50
+ console.error(`✖ ${tm(error.message)}`);
51
+ for (const problem of error.problems) console.error(` ✖ ${tm(problem)}`);
52
+ if (error.status === 401) console.error(t(" Yeni anahtar: mağaza paneli → Ayarlar → Temalar → Geliştirici erişimi, sonra `uvako login`."));
52
53
  return 1;
53
54
  }
54
55
 
@@ -56,16 +57,16 @@ const previewUrl = (origin, installationId) => `${origin}/?preview=${installatio
56
57
  const editorUrl = (origin, installationId) => `${origin}/admin/ayarlar/temalar/${installationId}/editor`;
57
58
 
58
59
  export async function login(options) {
59
- if (!options.store || options.store === true) throw new Error("Mağaza adresi gerekli: uvako login --store <mağaza>");
60
- if (options.token) throw new Error("Erişim anahtarı komut satırına yazılmaz. Komutu --token olmadan çalıştırın; anahtar sorulacak (ya da UVAKO_TOKEN ortam değişkenini kullanın).");
60
+ if (!options.store || options.store === true) throw new Error(t("Mağaza adresi gerekli: uvako login --store <mağaza>"));
61
+ if (options.token) throw new Error(t("Erişim anahtarı komut satırına yazılmaz. Komutu --token olmadan çalıştırın; anahtar sorulacak (ya da UVAKO_TOKEN ortam değişkenini kullanın)."));
61
62
  const origin = storeOrigin(options.store);
62
- const token = (process.env.UVAKO_TOKEN || (await askSecret(`${origin} için tema erişim anahtarı (panel → Ayarlar → Temalar → Geliştirici erişimi): `))).trim();
63
- if (!/^uvt_[A-Za-z0-9_-]{20,}$/.test(token)) throw new Error("Bu bir tema erişim anahtarı değil (uvt_ ile başlar).");
63
+ const token = (process.env.UVAKO_TOKEN || (await askSecret(t("{0} için tema erişim anahtarı (panel → Ayarlar → Temalar → Geliştirici erişimi): ", origin)))).trim();
64
+ if (!/^uvt_[A-Za-z0-9_-]{20,}$/.test(token)) throw new Error(t("Bu bir tema erişim anahtarı değil (uvt_ ile başlar)."));
64
65
  try {
65
66
  const me = await call({ origin, token }, "GET", "/me");
66
67
  saveSession(origin, token, me.store?.name ?? "");
67
- console.log(`Giriş yapıldı: ${me.store?.name ?? origin} (${origin})`);
68
- if (me.uploadBlocked) console.warn("! Bu mağaza için tema yükleme kapatılmış. Uvako desteğine yazın.");
68
+ console.log(t("Giriş yapıldı: {0} ({1})", me.store?.name ?? origin, origin));
69
+ if (me.uploadBlocked) console.warn(t("! Bu mağaza için tema yükleme kapatılmış. Uvako desteğine yazın."));
69
70
  return 0;
70
71
  } catch (error) {
71
72
  return explain(error);
@@ -74,8 +75,8 @@ export async function login(options) {
74
75
 
75
76
  export function logout(options) {
76
77
  const origin = dropSession(typeof options.store === "string" ? options.store : "");
77
- console.log(origin ? `Çıkış yapıldı: ${origin}` : "Kayıtlı giriş yok.");
78
- console.log("Anahtarı tamamen geçersiz kılmak için mağaza panelinden iptal edin.");
78
+ console.log(origin ? t("Çıkış yapıldı: {0}", origin) : t("Kayıtlı giriş yok."));
79
+ console.log(t("Anahtarı tamamen geçersiz kılmak için mağaza panelinden iptal edin."));
79
80
  return 0;
80
81
  }
81
82
 
@@ -84,14 +85,14 @@ export async function whoami(options) {
84
85
  const current = session(typeof options.store === "string" ? options.store : "");
85
86
  const me = await call(current, "GET", "/me");
86
87
  console.log(`${me.store?.name ?? ""} — ${current.origin} (anahtar: ${me.token})`);
87
- for (const other of sessions()) if (!other.current) console.log(` diğer giriş: ${other.name || other.origin} — ${other.origin}`);
88
+ for (const other of sessions()) if (!other.current) console.log(t(" diğer giriş: {0} — {1}", other.name || other.origin, other.origin));
88
89
  return 0;
89
90
  } catch (error) {
90
91
  return explain(error);
91
92
  }
92
93
  }
93
94
 
94
- const statusLabels = { private: "yalnızca bu mağazada", pending: "incelemede", approved: "tema mağazasında", rejected: "reddedildi" };
95
+ const statusLabels = { private: t("yalnızca bu mağazada"), pending: "incelemede", approved: t("tema mağazasında"), rejected: "reddedildi" };
95
96
 
96
97
  export async function list(options) {
97
98
  try {
@@ -101,11 +102,11 @@ export async function list(options) {
101
102
  console.log(JSON.stringify(data, null, 2));
102
103
  return 0;
103
104
  }
104
- console.log(`Mağazadaki temalar (${current.origin}):`);
105
- for (const item of data.installations) console.log(` ${item.role === "published" ? "● yayında " : "○ kütüphane"} ${item.name} [${item.key}]${item.custom ? " (paket)" : ""}`);
106
- console.log(data.packages.length ? "\nYüklediğiniz paketler:" : "\nYüklediğiniz paket yok.");
105
+ console.log(t("Mağazadaki temalar ({0}):", current.origin));
106
+ for (const item of data.installations) console.log(` ${item.role === "published" ? t("● yayında ") : t("○ kütüphane")} ${item.name} [${item.key}]${item.custom ? " (paket)" : ""}`);
107
+ console.log(data.packages.length ? t("\nYüklediğiniz paketler:") : t("\nYüklediğiniz paket yok."));
107
108
  for (const pkg of data.packages) {
108
- console.log(` ${pkg.key} ${pkg.version} (temel: ${pkg.base}) ${statusLabels[pkg.status] ?? pkg.status}${pkg.publishedVersion ? ` · mağazadaki sürüm ${pkg.publishedVersion}` : ""}`);
109
+ console.log(` ${pkg.key} ${pkg.version} (temel: ${pkg.base}) ${statusLabels[pkg.status] ?? pkg.status}${pkg.publishedVersion ? t(" · mağazadaki sürüm {0}", pkg.publishedVersion) : ""}`);
109
110
  if (pkg.status === "rejected" && pkg.reviewNote) console.log(` not: ${pkg.reviewNote}`);
110
111
  }
111
112
  return 0;
@@ -132,15 +133,15 @@ export async function push(target, options) {
132
133
  const current = session(typeof options.store === "string" ? options.store : "");
133
134
  const result = await upload(current, dir);
134
135
  if (!result) {
135
- console.error("Yüklenmedi: önce hataları düzeltin.");
136
+ console.error(t("Yüklenmedi: önce hataları düzeltin."));
136
137
  return 1;
137
138
  }
138
139
  const pkg = result.package;
139
- console.log(`${result.created ? "Yüklendi" : "Güncellendi"}: ${pkg.name} ${pkg.version} (sürüm no ${pkg.revision}) → ${current.origin}`);
140
- console.log(`Önizleme: ${previewUrl(current.origin, result.installationId)}`);
141
- console.log(`Düzenleme: ${editorUrl(current.origin, result.installationId)}`);
142
- console.log("Önizleme için tarayıcıda mağaza paneline giriş yapmış olmalısınız. Tema, panelden yayınlanana kadar vitrini değiştirmez.");
143
- if (pkg.publishedVersion) console.log(`Tema mağazasındaki sürüm (${pkg.publishedVersion}) değişmedi. Yeni sürümü incelemeye göndermek için: uvako theme submit ${pkg.key}`);
140
+ console.log(t("{0}: {1} {2} (sürüm no {3}) → {4}", result.created ? t("Yüklendi") : t("Güncellendi"), pkg.name, pkg.version, pkg.revision, current.origin));
141
+ console.log(t("Önizleme: {0}", previewUrl(current.origin, result.installationId)));
142
+ console.log(t("Düzenleme: {0}", editorUrl(current.origin, result.installationId)));
143
+ console.log(t("Önizleme için tarayıcıda mağaza paneline giriş yapmış olmalısınız. Tema, panelden yayınlanana kadar vitrini değiştirmez."));
144
+ if (pkg.publishedVersion) console.log(t("Tema mağazasındaki sürüm ({0}) değişmedi. Yeni sürümü incelemeye göndermek için: uvako theme submit {1}", pkg.publishedVersion, pkg.key));
144
145
  return 0;
145
146
  } catch (error) {
146
147
  return explain(error);
@@ -167,18 +168,18 @@ export async function dev(target, options) {
167
168
  first = await upload(current, dir);
168
169
  } catch (error) {
169
170
  if (error instanceof ApiError) return explain(error);
170
- console.error(`✖ ${error.message}`);
171
+ console.error(`✖ ${tm(error.message)}`);
171
172
  return 1;
172
173
  }
173
174
  if (!first) {
174
- console.error("Başlatılamadı: önce hataları düzeltin.");
175
+ console.error(t("Başlatılamadı: önce hataları düzeltin."));
175
176
  return 1;
176
177
  }
177
- console.log(`\nCanlı geliştirme: ${first.package.name} → ${current.origin}`);
178
- console.log(`Önizleme: ${previewUrl(current.origin, first.installationId)}`);
179
- console.log(`Düzenleme: ${editorUrl(current.origin, first.installationId)}`);
180
- console.log("Önizleme için tarayıcıda mağaza paneline giriş yapın. Dosyaları kaydettikçe sayfa yenilenir. Durdurmak için Ctrl+C.\n");
181
- console.log(options.keep ? "Durdurduğunuzda tema son hâliyle kütüphanede kalır (--keep)." : existed ? "Durdurduğunuzda mağazadaki paket geliştirme öncesindeki sürümüne döner. Kalıcı yüklemek için: uvako theme push" : "Durdurduğunuzda geliştirme kopyası mağazadan silinir. Kalıcı yüklemek için: uvako theme push");
178
+ console.log(t("\nCanlı geliştirme: {0} → {1}", first.package.name, current.origin));
179
+ console.log(t("Önizleme: {0}", previewUrl(current.origin, first.installationId)));
180
+ console.log(t("Düzenleme: {0}", editorUrl(current.origin, first.installationId)));
181
+ console.log(t("Önizleme için tarayıcıda mağaza paneline giriş yapın. Dosyaları kaydettikçe sayfa yenilenir. Durdurmak için Ctrl+C.\n"));
182
+ console.log(options.keep ? t("Durdurduğunuzda tema son hâliyle kütüphanede kalır (--keep).") : existed ? t("Durdurduğunuzda mağazadaki paket geliştirme öncesindeki sürümüne döner. Kalıcı yüklemek için: uvako theme push") : t("Durdurduğunuzda geliştirme kopyası mağazadan silinir. Kalıcı yüklemek için: uvako theme push"));
182
183
  console.log("");
183
184
 
184
185
  let timer = null;
@@ -193,15 +194,15 @@ export async function dev(target, options) {
193
194
  running = true;
194
195
  try {
195
196
  const result = await upload(current, dir, true);
196
- if (result) console.log(`[${stamp()}] yüklendi (sürüm no ${result.package.revision})`);
197
- else console.error(`[${stamp()}] yüklenmedi: hataları düzeltip kaydedin.`);
197
+ if (result) console.log(t("[{0}] yüklendi (sürüm no {1})", stamp(), result.package.revision));
198
+ else console.error(t("[{0}] yüklenmedi: hataları düzeltip kaydedin.", stamp()));
198
199
  } catch (error) {
199
200
  if (error instanceof ApiError) {
200
- console.error(`[${stamp()}] ✖ ${error.message}`);
201
- for (const problem of error.problems) console.error(` ✖ ${problem}`);
201
+ console.error(`[${stamp()}] ✖ ${tm(error.message)}`);
202
+ for (const problem of error.problems) console.error(` ✖ ${tm(problem)}`);
202
203
  if (error.status === 401 || error.status === 403) process.exit(1);
203
204
  } else {
204
- console.error(`[${stamp()}] ✖ ${error.message}`);
205
+ console.error(`[${stamp()}] ✖ ${tm(error.message)}`);
205
206
  }
206
207
  } finally {
207
208
  running = false;
@@ -227,18 +228,18 @@ export async function dev(target, options) {
227
228
  const key = first.package.key;
228
229
  try {
229
230
  if (options.keep) {
230
- console.log("\nCanlı geliştirme durdu. Tema son hâliyle mağaza kütüphanesinde duruyor.");
231
+ console.log(t("\nCanlı geliştirme durdu. Tema son hâliyle mağaza kütüphanesinde duruyor."));
231
232
  } else if (before) {
232
233
  await call(current, "PUT", "/themes", { body: before });
233
- console.log("\nCanlı geliştirme durdu. Mağazadaki paket geliştirme öncesindeki sürümüne döndü.");
234
+ console.log(t("\nCanlı geliştirme durdu. Mağazadaki paket geliştirme öncesindeki sürümüne döndü."));
234
235
  } else {
235
236
  await call(current, "DELETE", `/themes/${encodeURIComponent(key)}`);
236
- console.log("\nCanlı geliştirme durdu. Geliştirme kopyası mağazadan silindi; vitrin ve kütüphane eski hâlinde.");
237
+ console.log(t("\nCanlı geliştirme durdu. Geliştirme kopyası mağazadan silindi; vitrin ve kütüphane eski hâlinde."));
237
238
  }
238
239
  resolve(0);
239
240
  } catch (error) {
240
- console.error(`\nCanlı geliştirme durdu ama mağaza eski hâline döndürülemedi: ${error.message}`);
241
- console.error(`Elle kaldırmak için: uvako theme delete ${key} --yes`);
241
+ console.error(t("\nCanlı geliştirme durdu ama mağaza eski hâline döndürülemedi: {0}", error.message));
242
+ console.error(t("Elle kaldırmak için: uvako theme delete {0} --yes", key));
242
243
  resolve(1);
243
244
  }
244
245
  });
@@ -246,10 +247,10 @@ export async function dev(target, options) {
246
247
  }
247
248
 
248
249
  export async function pull(key, options) {
249
- if (!key) throw new Error("Tema anahtarı gerekli: uvako theme pull <anahtar>");
250
+ if (!key) throw new Error(t("Tema anahtarı gerekli: uvako theme pull <anahtar>"));
250
251
  const parent = path.resolve(typeof options.dir === "string" ? options.dir : ".");
251
252
  const dir = path.join(parent, key);
252
- if (existsSync(dir) && !options.force) throw new Error(`Klasör zaten var: ${dir}\nÜstüne yazmak için --force ekleyin.`);
253
+ if (existsSync(dir) && !options.force) throw new Error(t("Klasör zaten var: {0}\nÜstüne yazmak için --force ekleyin.", dir));
253
254
  try {
254
255
  const current = session(typeof options.store === "string" ? options.store : "");
255
256
  const archive = await call(current, "GET", `/themes/${encodeURIComponent(key)}/package`, { raw: true });
@@ -258,12 +259,12 @@ export async function pull(key, options) {
258
259
  // Paket yalnızca kendi klasörünün içine açılır.
259
260
  const rel = entry.name.split("/").slice(1).join("/");
260
261
  const file = path.resolve(dir, rel);
261
- if (!rel || !entry.name.startsWith(`${key}/`) || rel.split("/").includes("..") || !file.startsWith(dir + path.sep)) throw new Error(`Paketteki yol güvenli değil: ${entry.name}`);
262
+ if (!rel || !entry.name.startsWith(`${key}/`) || rel.split("/").includes("..") || !file.startsWith(dir + path.sep)) throw new Error(t("Paketteki yol güvenli değil: {0}", entry.name));
262
263
  mkdirSync(path.dirname(file), { recursive: true });
263
264
  writeFileSync(file, entry.data);
264
265
  count++;
265
266
  }
266
- console.log(`İndirildi: ${path.relative(process.cwd(), dir) || "."} (${count} dosya)`);
267
+ console.log(t("İndirildi: {0} ({1} dosya)", path.relative(process.cwd(), dir) || ".", count));
267
268
  return 0;
268
269
  } catch (error) {
269
270
  return explain(error);
@@ -271,12 +272,12 @@ export async function pull(key, options) {
271
272
  }
272
273
 
273
274
  export async function submit(key, options) {
274
- if (!key) throw new Error("Tema anahtarı gerekli: uvako theme submit <anahtar>");
275
+ if (!key) throw new Error(t("Tema anahtarı gerekli: uvako theme submit <anahtar>"));
275
276
  try {
276
277
  const current = session(typeof options.store === "string" ? options.store : "");
277
278
  const pkg = await call(current, "POST", `/themes/${encodeURIComponent(key)}/submit`);
278
- console.log(`İncelemeye gönderildi: ${pkg.name} ${pkg.version}. Uvako ekibi onayladığında themes.uvako.com'da yayınlanır.`);
279
- console.log("İnceleme sürerken yeni sürüm yüklerseniz onay o sürüm için yeniden istenir.");
279
+ console.log(t("İncelemeye gönderildi: {0} {1}. Uvako ekibi onayladığında themes.uvako.com'da yayınlanır.", pkg.name, pkg.version));
280
+ console.log(t("İnceleme sürerken yeni sürüm yüklerseniz onay o sürüm için yeniden istenir."));
280
281
  return 0;
281
282
  } catch (error) {
282
283
  return explain(error);
@@ -284,8 +285,8 @@ export async function submit(key, options) {
284
285
  }
285
286
 
286
287
  export async function remove(key, options) {
287
- if (!key) throw new Error("Tema anahtarı gerekli: uvako theme delete <anahtar>");
288
- if (!options.yes) throw new Error(`"${key}" paketi ve mağazadaki kopyaları silinir; geri alınamaz. Onaylamak için --yes ekleyin.`);
288
+ if (!key) throw new Error(t("Tema anahtarı gerekli: uvako theme delete <anahtar>"));
289
+ if (!options.yes) throw new Error(t("\"{0}\" paketi ve mağazadaki kopyaları silinir; geri alınamaz. Onaylamak için --yes ekleyin.", key));
289
290
  try {
290
291
  const current = session(typeof options.store === "string" ? options.store : "");
291
292
  await call(current, "DELETE", `/themes/${encodeURIComponent(key)}`);
package/src/zip.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import zlib from "node:zlib";
2
+ import { t } from "./i18n.js";
2
3
 
3
4
  // Bağımlılıksız zip yazıcı ve okuyucu. Dosya tarihleri sabit tutulur; aynı içerik her zaman aynı
4
5
  // özeti verir.
@@ -62,12 +63,12 @@ export function unzip(buffer) {
62
63
  break;
63
64
  }
64
65
  }
65
- if (end < 0) throw new Error("Geçerli bir zip dosyası değil.");
66
+ if (end < 0) throw new Error(t("Geçerli bir zip dosyası değil."));
66
67
  const count = buffer.readUInt16LE(end + 10);
67
68
  let cursor = buffer.readUInt32LE(end + 16);
68
69
  const entries = [];
69
70
  for (let i = 0; i < count; i++) {
70
- if (buffer.readUInt32LE(cursor) !== 0x02014b50) throw new Error("Zip dizini okunamadı.");
71
+ if (buffer.readUInt32LE(cursor) !== 0x02014b50) throw new Error(t("Zip dizini okunamadı."));
71
72
  const method = buffer.readUInt16LE(cursor + 10);
72
73
  const compressedSize = buffer.readUInt32LE(cursor + 20);
73
74
  const size = buffer.readUInt32LE(cursor + 24);
@@ -78,13 +79,13 @@ export function unzip(buffer) {
78
79
  const name = buffer.subarray(cursor + 46, cursor + 46 + nameLength).toString("utf8");
79
80
  cursor += 46 + nameLength + extraLength + commentLength;
80
81
  if (name.endsWith("/")) continue;
81
- if (size > maxEntryBytes) throw new Error(`${name}: dosya çok büyük.`);
82
+ if (size > maxEntryBytes) throw new Error(t("{0}: dosya çok büyük.", name));
82
83
  const dataStart = localOffset + 30 + buffer.readUInt16LE(localOffset + 26) + buffer.readUInt16LE(localOffset + 28);
83
84
  const raw = buffer.subarray(dataStart, dataStart + compressedSize);
84
85
  let data;
85
86
  if (method === 0) data = Buffer.from(raw);
86
87
  else if (method === 8) data = zlib.inflateRawSync(raw, { maxOutputLength: maxEntryBytes });
87
- else throw new Error(`${name}: desteklenmeyen sıkıştırma yöntemi.`);
88
+ else throw new Error(t("{0}: desteklenmeyen sıkıştırma yöntemi.", name));
88
89
  entries.push({ name, data });
89
90
  }
90
91
  return entries;