@intlpullhq/cli 0.1.10 → 0.1.11

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.
@@ -12,19 +12,19 @@ import {
12
12
  WebhooksApi,
13
13
  WorkflowsApi,
14
14
  createApiClient
15
- } from "./chunk-WVCVQFBI.js";
15
+ } from "./chunk-QOUDOZX4.js";
16
16
  import {
17
17
  ProjectsApi
18
- } from "./chunk-KCZQUMQP.js";
18
+ } from "./chunk-RQI7KQQ5.js";
19
19
  import {
20
20
  TranslationsApi
21
- } from "./chunk-WSY27J6N.js";
21
+ } from "./chunk-OMGFIATE.js";
22
22
  import {
23
23
  KeysApi
24
- } from "./chunk-BULIQM4U.js";
24
+ } from "./chunk-DSTFGTTF.js";
25
25
  import {
26
26
  BaseApiClient
27
- } from "./chunk-KIDP7N6D.js";
27
+ } from "./chunk-ZYZSONV6.js";
28
28
  import "./chunk-IWYURZV2.js";
29
29
  export {
30
30
  ApiClient,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BaseApiClient
3
- } from "./chunk-KIDP7N6D.js";
3
+ } from "./chunk-ZYZSONV6.js";
4
4
 
5
5
  // src/lib/api/keys.ts
6
6
  var KeysApi = class extends BaseApiClient {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BaseApiClient
3
- } from "./chunk-KIDP7N6D.js";
3
+ } from "./chunk-ZYZSONV6.js";
4
4
  import {
5
5
  getProjectConfig
6
6
  } from "./chunk-IWYURZV2.js";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  ProjectsApi
3
- } from "./chunk-KCZQUMQP.js";
3
+ } from "./chunk-RQI7KQQ5.js";
4
4
  import {
5
5
  TranslationsApi
6
- } from "./chunk-WSY27J6N.js";
6
+ } from "./chunk-OMGFIATE.js";
7
7
  import {
8
8
  KeysApi
9
- } from "./chunk-BULIQM4U.js";
9
+ } from "./chunk-DSTFGTTF.js";
10
10
  import {
11
11
  BaseApiClient
12
- } from "./chunk-KIDP7N6D.js";
12
+ } from "./chunk-ZYZSONV6.js";
13
13
  import {
14
14
  getAuthErrorMessage
15
15
  } from "./chunk-IWYURZV2.js";
@@ -21,7 +21,8 @@ var ImportExportApi = class extends BaseApiClient {
21
21
  const params = new URLSearchParams();
22
22
  params.set("format", options.format);
23
23
  if (options.languages?.length) {
24
- params.set("languages", options.languages.join(","));
24
+ const normalizedLanguages = options.languages.map((lang) => lang.trim());
25
+ params.set("languages", normalizedLanguages.join(","));
25
26
  }
26
27
  if (options.namespaces?.length) {
27
28
  params.set("namespaces", options.namespaces.join(","));
@@ -493,7 +494,7 @@ var SnapshotsApi = class extends BaseApiClient {
493
494
  */
494
495
  async createSnapshot(projectId, data) {
495
496
  const response = await this.request(
496
- `/projects/${projectId}/snapshots`,
497
+ `/api/v1/projects/${projectId}/snapshots`,
497
498
  {
498
499
  method: "POST",
499
500
  body: JSON.stringify(data)
@@ -506,18 +507,18 @@ var SnapshotsApi = class extends BaseApiClient {
506
507
  */
507
508
  async listSnapshots(projectId) {
508
509
  const response = await this.request(
509
- `/projects/${projectId}/snapshots`,
510
+ `/api/v1/projects/${projectId}/snapshots`,
510
511
  {
511
512
  method: "GET"
512
513
  }
513
514
  );
514
- return response.snapshots;
515
+ return response?.snapshots ?? [];
515
516
  }
516
517
  /**
517
518
  * Get snapshot details
518
519
  */
519
520
  async getSnapshot(projectId, snapshotId) {
520
- return this.request(`/projects/${projectId}/snapshots/${snapshotId}`, {
521
+ return this.request(`/api/v1/projects/${projectId}/snapshots/${snapshotId}`, {
521
522
  method: "GET"
522
523
  });
523
524
  }
@@ -526,7 +527,7 @@ var SnapshotsApi = class extends BaseApiClient {
526
527
  */
527
528
  async restoreSnapshot(projectId, snapshotId) {
528
529
  return this.request(
529
- `/projects/${projectId}/snapshots/${snapshotId}/restore`,
530
+ `/api/v1/projects/${projectId}/snapshots/${snapshotId}/restore`,
530
531
  {
531
532
  method: "POST"
532
533
  }
@@ -536,7 +537,7 @@ var SnapshotsApi = class extends BaseApiClient {
536
537
  * Delete a snapshot
537
538
  */
538
539
  async deleteSnapshot(projectId, snapshotId) {
539
- await this.request(`/projects/${projectId}/snapshots/${snapshotId}`, {
540
+ await this.request(`/api/v1/projects/${projectId}/snapshots/${snapshotId}`, {
540
541
  method: "DELETE"
541
542
  });
542
543
  }
@@ -595,8 +596,8 @@ var TMApi = class extends BaseApiClient {
595
596
  * This fetches keys without translations and applies TM matches
596
597
  */
597
598
  async applyTMMatches(projectId, data) {
598
- const { KeysApi: KeysApi2 } = await import("./keys-P3F5IKS2.js");
599
- const { TranslationsApi: TranslationsApi2 } = await import("./translations-7GWEFVRG.js");
599
+ const { KeysApi: KeysApi2 } = await import("./keys-WDJKXFH3.js");
600
+ const { TranslationsApi: TranslationsApi2 } = await import("./translations-45NWLMJR.js");
600
601
  const keysApi = new KeysApi2();
601
602
  const translationsApi = new TranslationsApi2();
602
603
  const { keys } = await keysApi.listKeys(projectId, {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BaseApiClient
3
- } from "./chunk-KIDP7N6D.js";
3
+ } from "./chunk-ZYZSONV6.js";
4
4
 
5
5
  // src/lib/api/projects.ts
6
6
  var ProjectsApi = class extends BaseApiClient {
@@ -130,6 +130,9 @@ var BaseApiClient = class {
130
130
  const contentType = response.headers.get("content-type") || "";
131
131
  if (contentType.includes("application/json")) {
132
132
  const jsonData = await response.json();
133
+ if (jsonData.error && typeof jsonData.error === "string") {
134
+ throw new Error(jsonData.error);
135
+ }
133
136
  if (jsonData.url && typeof jsonData.url === "string") {
134
137
  const fileResponse = await fetch(jsonData.url);
135
138
  if (!fileResponse.ok) {
@@ -137,6 +140,9 @@ var BaseApiClient = class {
137
140
  }
138
141
  return fileResponse.blob();
139
142
  }
143
+ if (typeof jsonData === "object" && Object.keys(jsonData).length === 0) {
144
+ throw new Error("no translations found for the requested languages");
145
+ }
140
146
  const jsonString = JSON.stringify(jsonData, null, 2);
141
147
  return new Blob([jsonString], { type: "application/json" });
142
148
  }
package/dist/index.js CHANGED
@@ -5,15 +5,15 @@ import {
5
5
  TMApi,
6
6
  WebhooksApi,
7
7
  createApiClient
8
- } from "./chunk-WVCVQFBI.js";
8
+ } from "./chunk-QOUDOZX4.js";
9
9
  import {
10
10
  ProjectsApi
11
- } from "./chunk-KCZQUMQP.js";
12
- import "./chunk-WSY27J6N.js";
11
+ } from "./chunk-RQI7KQQ5.js";
12
+ import "./chunk-OMGFIATE.js";
13
13
  import {
14
14
  KeysApi
15
- } from "./chunk-BULIQM4U.js";
16
- import "./chunk-KIDP7N6D.js";
15
+ } from "./chunk-DSTFGTTF.js";
16
+ import "./chunk-ZYZSONV6.js";
17
17
  import {
18
18
  detectFramework,
19
19
  getAuthErrorMessage,
@@ -4816,8 +4816,8 @@ function ExportComponent({ options }) {
4816
4816
  json: "json",
4817
4817
  yaml: "yaml",
4818
4818
  ts: "ts",
4819
- android: "zip",
4820
- ios: "zip",
4819
+ android: "xml",
4820
+ ios: "strings",
4821
4821
  xliff: "xliff",
4822
4822
  po: "po",
4823
4823
  arb: "arb",
@@ -9268,6 +9268,22 @@ async function fetchProjects7(apiUrl, apiKey) {
9268
9268
  return data.projects || [];
9269
9269
  }
9270
9270
  var isInteractiveTerminal7 = process.stdin.isTTY && process.stdout.isTTY;
9271
+ var NON_LANGUAGE_FIELDS = /* @__PURE__ */ new Set(["url", "filename", "expires_at", "size", "download_url", "content_type", "error", "message"]);
9272
+ function isTranslationData(value) {
9273
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
9274
+ return false;
9275
+ }
9276
+ const entries = Object.entries(value);
9277
+ if (entries.length === 0) return false;
9278
+ const validCount = entries.filter(([, v]) => typeof v === "string" || typeof v === "object" && v !== null).length;
9279
+ return validCount >= entries.length * 0.5;
9280
+ }
9281
+ function isValidLanguageCode(key) {
9282
+ if (NON_LANGUAGE_FIELDS.has(key)) {
9283
+ return false;
9284
+ }
9285
+ return /^[a-z]{2,3}(-[A-Z]{2,3}|-[A-Za-z]{4})?$/i.test(key);
9286
+ }
9271
9287
  async function fetchTranslationsFromExport(projectId, apiUrl, apiKey, options) {
9272
9288
  const params = new URLSearchParams();
9273
9289
  params.set("format", "json");
@@ -9295,9 +9311,16 @@ async function fetchTranslationsFromExport(projectId, apiUrl, apiKey, options) {
9295
9311
  data = { [lang]: data };
9296
9312
  }
9297
9313
  }
9298
- const languages = Object.keys(data);
9299
- const keyCount = languages.length > 0 && data[languages[0]] ? Object.keys(data[languages[0]]).length : 0;
9300
- return { bundle: data, languages, keyCount };
9314
+ const filteredData = {};
9315
+ for (const key of Object.keys(data)) {
9316
+ const value = data[key];
9317
+ if (isValidLanguageCode(key) && isTranslationData(value)) {
9318
+ filteredData[key] = value;
9319
+ }
9320
+ }
9321
+ const languages = Object.keys(filteredData);
9322
+ const keyCount = languages.length > 0 && filteredData[languages[0]] ? Object.keys(filteredData[languages[0]]).length : 0;
9323
+ return { bundle: filteredData, languages, keyCount };
9301
9324
  }
9302
9325
  async function fetchNamespaces2(projectId, apiUrl, apiKey) {
9303
9326
  const response = await fetch(`${apiUrl}/api/v1/projects/${projectId}/namespaces`, {
@@ -11716,7 +11739,7 @@ var KeysCreate = ({ keyName, options }) => {
11716
11739
  }
11717
11740
  const api = new KeysApi();
11718
11741
  const tags = options.tags ? options.tags.split(",").map((t) => t.trim()) : void 0;
11719
- const { ProjectsApi: ProjectsApi2 } = await import("./projects-AMQMORAR.js");
11742
+ const { ProjectsApi: ProjectsApi2 } = await import("./projects-C6BDSZVS.js");
11720
11743
  const projectsApi = new ProjectsApi2();
11721
11744
  const project = await projectsApi.getProject(projectId);
11722
11745
  const created = await api.createKey(projectId, {
@@ -12619,37 +12642,40 @@ var TMStatsComponent = ({ options }) => {
12619
12642
  if (!stats) {
12620
12643
  return /* @__PURE__ */ jsx50(Text47, { children: "No statistics available" });
12621
12644
  }
12645
+ const totalEntries = stats.total_entries ?? 0;
12646
+ const avgQuality = stats.avg_quality ?? 0;
12647
+ const languagePairs = stats.language_pairs ?? [];
12622
12648
  return /* @__PURE__ */ jsxs47(Box44, { flexDirection: "column", children: [
12623
12649
  /* @__PURE__ */ jsx50(Text47, { bold: true, children: "Translation Memory Statistics" }),
12624
12650
  /* @__PURE__ */ jsx50(Newline6, {}),
12625
12651
  /* @__PURE__ */ jsxs47(Text47, { children: [
12626
12652
  /* @__PURE__ */ jsx50(Text47, { bold: true, children: "Total Entries:" }),
12627
12653
  " ",
12628
- stats.total_entries.toLocaleString()
12654
+ totalEntries.toLocaleString()
12629
12655
  ] }),
12630
12656
  /* @__PURE__ */ jsxs47(Text47, { children: [
12631
12657
  /* @__PURE__ */ jsx50(Text47, { bold: true, children: "Average Quality:" }),
12632
12658
  " ",
12633
- stats.avg_quality.toFixed(1),
12659
+ avgQuality.toFixed(1),
12634
12660
  "%"
12635
12661
  ] }),
12636
12662
  /* @__PURE__ */ jsx50(Newline6, {}),
12637
- stats.language_pairs.length > 0 && /* @__PURE__ */ jsxs47(Fragment8, { children: [
12663
+ languagePairs.length > 0 && /* @__PURE__ */ jsxs47(Fragment8, { children: [
12638
12664
  /* @__PURE__ */ jsx50(Text47, { bold: true, children: "Language Pairs:" }),
12639
12665
  /* @__PURE__ */ jsx50(Newline6, {}),
12640
- /* @__PURE__ */ jsx50(Box44, { flexDirection: "column", children: stats.language_pairs.map((pair, idx) => /* @__PURE__ */ jsxs47(Text47, { children: [
12666
+ /* @__PURE__ */ jsx50(Box44, { flexDirection: "column", children: languagePairs.map((pair, idx) => /* @__PURE__ */ jsxs47(Text47, { children: [
12641
12667
  /* @__PURE__ */ jsxs47(Text47, { color: "cyan", children: [
12642
12668
  pair.source,
12643
12669
  " \u2192 ",
12644
12670
  pair.target
12645
12671
  ] }),
12646
12672
  ": ",
12647
- pair.count.toLocaleString(),
12673
+ (pair.count ?? 0).toLocaleString(),
12648
12674
  " ",
12649
12675
  pair.count === 1 ? "entry" : "entries"
12650
12676
  ] }, idx)) })
12651
12677
  ] }),
12652
- stats.language_pairs.length === 0 && /* @__PURE__ */ jsx50(Text47, { dimColor: true, children: "No language pairs found. Add entries with `intlpull tm add`" })
12678
+ languagePairs.length === 0 && /* @__PURE__ */ jsx50(Text47, { dimColor: true, children: "No language pairs found. Add entries with `intlpull tm add`" })
12653
12679
  ] });
12654
12680
  };
12655
12681
  function runTMStats(options) {
@@ -13056,7 +13082,12 @@ var SnapshotsList = ({ options }) => {
13056
13082
  const result = await api.listSnapshots(projectId);
13057
13083
  setSnapshots(result);
13058
13084
  } catch (err) {
13059
- setError(err instanceof Error ? err.message : "Failed to list snapshots");
13085
+ const errorMessage = err instanceof Error ? err.message : "Failed to list snapshots";
13086
+ if (errorMessage.includes("404")) {
13087
+ setError("Snapshots feature is not available for this project. This feature may require a plan upgrade or is not yet enabled.");
13088
+ } else {
13089
+ setError(errorMessage);
13090
+ }
13060
13091
  } finally {
13061
13092
  setIsLoading(false);
13062
13093
  }
@@ -13421,7 +13452,7 @@ var WebhooksList = ({ options }) => {
13421
13452
  }
13422
13453
  const api = new WebhooksApi();
13423
13454
  const result = await api.listWebhooks(projectId);
13424
- setWebhooks(result.webhooks);
13455
+ setWebhooks(result?.webhooks ?? []);
13425
13456
  } catch (err) {
13426
13457
  setError(err instanceof Error ? err.message : "Failed to fetch webhooks");
13427
13458
  } finally {
@@ -13879,10 +13910,16 @@ var ContributorsList = ({ options }) => {
13879
13910
  console.log(JSON.stringify(members, null, 2));
13880
13911
  return null;
13881
13912
  }
13913
+ const formatJoinedDate = (dateString) => {
13914
+ if (!dateString) return "Unknown";
13915
+ const date = new Date(dateString);
13916
+ if (isNaN(date.getTime())) return "Unknown";
13917
+ return date.toLocaleDateString();
13918
+ };
13882
13919
  const data = members.map((member) => {
13883
13920
  const emailDisplay = member.email.length > 25 ? member.email.substring(0, 22) + "..." : member.email;
13884
13921
  const languagesDisplay = member.languages && member.languages.length > 0 ? member.languages.length > 3 ? member.languages.slice(0, 3).join(",") + ` +${member.languages.length - 3}` : member.languages.join(",") : "All";
13885
- const joinedDate = new Date(member.joined_at).toLocaleDateString();
13922
+ const joinedDate = formatJoinedDate(member.joined_at);
13886
13923
  return {
13887
13924
  Email: emailDisplay,
13888
13925
  Name: member.name || "-",
@@ -14249,7 +14286,7 @@ contributorsCommand.command("remove <userId>").description("Remove a team member
14249
14286
 
14250
14287
  // src/index.tsx
14251
14288
  var program = new Command7();
14252
- program.name("intlpull").description("Intelligent i18n CLI for modern apps").version("0.1.5").option("--env-file <path>", "Path to custom env file (e.g., .env.production)").hook("preAction", (thisCommand) => {
14289
+ program.name("intlpull").description("Intelligent i18n CLI for modern apps").version("0.1.11").option("--env-file <path>", "Path to custom env file (e.g., .env.production)").hook("preAction", (thisCommand) => {
14253
14290
  const envFile = thisCommand.opts().envFile;
14254
14291
  if (envFile) {
14255
14292
  setCustomEnvFile(envFile);
@@ -14281,7 +14318,7 @@ program.command("logout").description("Clear stored credentials").action(async (
14281
14318
  });
14282
14319
  program.command("whoami").description("Show current authenticated user").action(async () => {
14283
14320
  const { getResolvedApiKey: getResolvedApiKey2, getAuthErrorMessage: getAuthErrorMessage2 } = await import("./config-F3O3XWYX.js");
14284
- const { createApiClient: createApiClient2 } = await import("./api-77ZWU4IB.js");
14321
+ const { createApiClient: createApiClient2 } = await import("./api-BTTALAAQ.js");
14285
14322
  const resolved = getResolvedApiKey2();
14286
14323
  if (!resolved) {
14287
14324
  console.log(getAuthErrorMessage2());
@@ -14474,7 +14511,7 @@ projects.command("list").description("List all projects").action(async () => {
14474
14511
  console.log("Not authenticated. Run `npx @intlpullhq/cli login` first.");
14475
14512
  return;
14476
14513
  }
14477
- const { createApiClient: createApiClient2 } = await import("./api-77ZWU4IB.js");
14514
+ const { createApiClient: createApiClient2 } = await import("./api-BTTALAAQ.js");
14478
14515
  try {
14479
14516
  const api = createApiClient2();
14480
14517
  const { projects: projects2 } = await api.listProjects();
@@ -14500,7 +14537,7 @@ projects.command("create <name>").description("Create a new project").option("--
14500
14537
  console.log("Not authenticated. Run `npx @intlpullhq/cli login` first.");
14501
14538
  return;
14502
14539
  }
14503
- const { createApiClient: createApiClient2 } = await import("./api-77ZWU4IB.js");
14540
+ const { createApiClient: createApiClient2 } = await import("./api-BTTALAAQ.js");
14504
14541
  try {
14505
14542
  const api = createApiClient2();
14506
14543
  const languages = options.languages.split(",").map((l) => l.trim());
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  KeysApi
3
- } from "./chunk-BULIQM4U.js";
4
- import "./chunk-KIDP7N6D.js";
3
+ } from "./chunk-DSTFGTTF.js";
4
+ import "./chunk-ZYZSONV6.js";
5
5
  import "./chunk-IWYURZV2.js";
6
6
  export {
7
7
  KeysApi
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ProjectsApi
3
- } from "./chunk-KCZQUMQP.js";
4
- import "./chunk-KIDP7N6D.js";
3
+ } from "./chunk-RQI7KQQ5.js";
4
+ import "./chunk-ZYZSONV6.js";
5
5
  import "./chunk-IWYURZV2.js";
6
6
  export {
7
7
  ProjectsApi
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  TranslationsApi
3
- } from "./chunk-WSY27J6N.js";
4
- import "./chunk-KIDP7N6D.js";
3
+ } from "./chunk-OMGFIATE.js";
4
+ import "./chunk-ZYZSONV6.js";
5
5
  import "./chunk-IWYURZV2.js";
6
6
  export {
7
7
  TranslationsApi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlpullhq/cli",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "The official CLI for IntlPull - intelligent i18n for modern apps. Manage translations, sync with cloud, and automate localization workflows.",
5
5
  "type": "module",
6
6
  "bin": {