@localess/cli 0.0.1-dev.20260220221945 → 0.0.1-dev.20260221224153

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/README.md CHANGED
@@ -13,8 +13,8 @@ A powerful CLI tool to interact with your Localess spaces.
13
13
  ## Features
14
14
 
15
15
  - 🔐 **Authentication** - Secure login system and CI environments.
16
- - 🛡️ **Type Safety** - Generate TypeScript type definitions for your Localess content schemas, ensuring type safety in your frontend applications.
17
16
  - 🌐 **Translations** - Sync and manage translations for your Localess space.
17
+ - 🛡️ **Type Safety** - Generate TypeScript type definitions for your Localess content schemas, ensuring type safety in your frontend applications.
18
18
 
19
19
  ## Setup
20
20
 
@@ -45,17 +45,43 @@ The CLI provides a `logout` command to clear your authentication token and log y
45
45
  localess logout
46
46
  ```
47
47
 
48
+ ## Translations Management
49
+
50
+ The CLI provides a `translations` command with `push` and `pull` subcommands to sync and manage translations for your Localess space.
51
+
52
+ ### Push Translations
53
+ Push local translation files to Localess.
54
+
55
+ ```bash
56
+ localess translations push <locale> --path <file> [--format <flat|nested>] [--type <add-missing|replace>]
57
+ ```
58
+ - `<locale>`: Locale code (e.g., `en`)
59
+ - `--path`: Path to the translations file to push (required)
60
+ - `--format`: File format (`flat` or `nested`, default: `flat`). **Note:** Only `flat` format is currently supported for push.
61
+ - `--type`: Push type (`add-missing`, `replace`, etc., default: `add-missing`)
62
+
63
+ ### Pull Translations
64
+ Pull translations from Localess and save locally.
65
+
66
+ ```bash
67
+ localess translations pull <locale> --path <file> [--format <flat|nested>]
68
+ ```
69
+ - `<locale>`: Locale code (e.g., `en`)
70
+ - `--path`: Path where the translations file will be saved (required)
71
+ - `--format`: File format (`flat` or `nested`, default: `flat`)
72
+
48
73
  ## Generate TypeScript Types
49
74
 
50
- The CLI provides a `types` command to generate TypeScript definitions for your Localess content schemas. This command fetches your space's OpenAPI schema and writes a `localess.d.ts` file to your project, allowing for strong typing in your codebase.
75
+ The CLI provides a `types generate` command to generate TypeScript definitions for your Localess content schemas. This command fetches your space's OpenAPI schema and writes a `localess.d.ts` file to your project, allowing for strong typing in your codebase.
51
76
 
52
77
  ### Usage
53
78
 
54
79
  ```bash
55
- localess types
80
+ localess types generate [--path <output_file>]
56
81
  ```
82
+ - `--path`: Path to the file where to save the generated types. Default is `.localess/localess.d.ts` in your current working directory.
57
83
 
58
84
  - You must be logged in (`localess login`) before running this command.
59
- - The generated types file will be saved as `./.localess/localess.d.ts` in your current working directory.
85
+ - The generated types file will be saved as `./.localess/localess.d.ts` by default.
60
86
 
61
87
  You can then import these types in your TypeScript project for improved type safety when working with Localess content.
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/program.ts
27
- var import_commander7 = require("commander");
27
+ var import_commander8 = require("commander");
28
28
 
29
29
  // src/commands/login/index.ts
30
30
  var import_commander = require("commander");
@@ -32,6 +32,24 @@ var import_commander = require("commander");
32
32
  // src/utils.ts
33
33
  var RESET = "\x1B[0m";
34
34
  var FG_BLUE = "\x1B[34m";
35
+ function dotToNestedObject(input) {
36
+ const result = {};
37
+ for (const [key, value] of Object.entries(input)) {
38
+ const parts = key.split(".");
39
+ let current = result;
40
+ for (let i = 0; i < parts.length; i++) {
41
+ if (i === parts.length - 1) {
42
+ current[parts[i]] = value;
43
+ } else {
44
+ if (!(parts[i] in current)) {
45
+ current[parts[i]] = {};
46
+ }
47
+ current = current[parts[i]];
48
+ }
49
+ }
50
+ }
51
+ return result;
52
+ }
35
53
 
36
54
  // src/cache.ts
37
55
  var NoCache = class {
@@ -509,7 +527,7 @@ var import_openapi_typescript = __toESM(require("openapi-typescript"));
509
527
  var import_node_path3 = require("path");
510
528
  var import_node_process = __toESM(require("process"));
511
529
  var TYPES_PATH = (0, import_node_path3.join)(import_node_process.default.cwd(), DEFAULT_CONFIG_DIR, "localess.d.ts");
512
- var typesGenerateCommand = new import_commander3.Command("generate").description("Generate types for your schemas").option("-f, --file <path>", "Path to the file where to save the generated types. Default is .localess/localess.d.ts", TYPES_PATH).action(async (options) => {
530
+ var typesGenerateCommand = new import_commander3.Command("generate").description("Generate types for your schemas").option("-p, --path <path>", "Path to the file where to save the generated types. Default is .localess/localess.d.ts", TYPES_PATH).action(async (options) => {
513
531
  console.log("Types in with options:", options);
514
532
  const session = await getSession();
515
533
  if (!session.isLoggedIn) {
@@ -533,8 +551,8 @@ var typesGenerateCommand = new import_commander3.Command("generate").description
533
551
  };
534
552
  const ast = await (0, import_openapi_typescript.default)(minimalSpec, { exportType: true, rootTypes: true, rootTypesNoSchemaPrefix: true });
535
553
  const contents = (0, import_openapi_typescript.astToString)(ast);
536
- await writeFile(options.file, contents);
537
- console.log(`Types generated successfully at ${options.file}`);
554
+ await writeFile(options.path, contents);
555
+ console.log(`Types generated successfully at ${options.path}`);
538
556
  } catch (e) {
539
557
  console.error(e);
540
558
  }
@@ -544,7 +562,7 @@ var typesGenerateCommand = new import_commander3.Command("generate").description
544
562
  var typesCommand = new import_commander4.Command("types").description("Generate types for your schemas").addCommand(typesGenerateCommand);
545
563
 
546
564
  // src/commands/translations/index.ts
547
- var import_commander6 = require("commander");
565
+ var import_commander7 = require("commander");
548
566
 
549
567
  // src/commands/translations/push/index.ts
550
568
  var import_commander5 = require("commander");
@@ -555,6 +573,11 @@ var TranslationUpdateType = /* @__PURE__ */ ((TranslationUpdateType2) => {
555
573
  TranslationUpdateType2["UPDATE_EXISTING"] = "update-existing";
556
574
  return TranslationUpdateType2;
557
575
  })(TranslationUpdateType || {});
576
+ var TranslationFileFormat = /* @__PURE__ */ ((TranslationFileFormat2) => {
577
+ TranslationFileFormat2["FLAT"] = "flat";
578
+ TranslationFileFormat2["NESTED"] = "nested";
579
+ return TranslationFileFormat2;
580
+ })(TranslationFileFormat || {});
558
581
 
559
582
  // src/models/translation.zod.ts
560
583
  var import_zod = require("zod");
@@ -566,7 +589,7 @@ var zTranslationUpdateSchema = import_zod.z.object({
566
589
  });
567
590
 
568
591
  // src/commands/translations/push/index.ts
569
- var translationsPushCommand = new import_commander5.Command("push").argument("<locale>", "Locale to push").description("Push locale translations to Localess").requiredOption("-f, --file <path>", "Path to the translations file to push").option("-t, --type <type>", `Push type. Possible values are : ${Object.values(TranslationUpdateType)}`, "add-missing" /* ADD_MISSING */).action(async (locale, options) => {
592
+ var translationsPushCommand = new import_commander5.Command("push").argument("<locale>", "Locale to push").description("Push locale translations to Localess").requiredOption("-p, --path <path>", "Path to the translations file to push").option("-f, --format <format>", `File format. Possible values are : ${Object.values(TranslationFileFormat)}`, "flat" /* FLAT */).option("-t, --type <type>", `Push type. Possible values are : ${Object.values(TranslationUpdateType)}`, "add-missing" /* ADD_MISSING */).action(async (locale, options) => {
570
593
  console.log("Pushing translations with arguments:", locale);
571
594
  console.log("Pushing translations with options:", options);
572
595
  if (!zTranslationUpdateTypeSchema.safeParse(options.type).success) {
@@ -584,8 +607,11 @@ var translationsPushCommand = new import_commander5.Command("push").argument("<l
584
607
  spaceId: session.space,
585
608
  token: session.token
586
609
  });
587
- console.log("Reading translations file from:", options.file);
588
- const fileContent = await readFile(options.file);
610
+ if (options.format === "nested" /* NESTED */) {
611
+ console.error("Nested format is not implemented yet. Please use flat format for now.");
612
+ }
613
+ console.log("Reading translations file from:", options.path);
614
+ const fileContent = await readFile(options.path);
589
615
  const translationValues = JSON.parse(fileContent);
590
616
  const pResult = zLocaleTranslationsSchema.safeParse(translationValues);
591
617
  if (!pResult.success) {
@@ -605,11 +631,43 @@ var translationsPushCommand = new import_commander5.Command("push").argument("<l
605
631
  }
606
632
  });
607
633
 
634
+ // src/commands/translations/pull/index.ts
635
+ var import_commander6 = require("commander");
636
+ var translationsPullCommand = new import_commander6.Command("pull").argument("<locale>", "Locale to pull").description("Pull locale translations from Localess").requiredOption("-p, --path <path>", "Path where the translations file will be saved").option("-f, --format <format>", `File format. Possible values are : ${Object.values(TranslationFileFormat)}`, "flat" /* FLAT */).action(async (locale, options) => {
637
+ console.log("Pulling translations with arguments:", locale);
638
+ console.log("Pulling translations with options:", options);
639
+ if (!Object.values(TranslationFileFormat).includes(options.format)) {
640
+ console.error("Invalid format provided. Possible values are :", Object.values(TranslationFileFormat));
641
+ return;
642
+ }
643
+ const session = await getSession();
644
+ if (!session.isLoggedIn) {
645
+ console.error("Not logged in");
646
+ console.error('Please log in first using "localess login" command');
647
+ return;
648
+ }
649
+ const client = localessClient({
650
+ origin: session.origin,
651
+ spaceId: session.space,
652
+ token: session.token
653
+ });
654
+ console.log("Pulling translations from Localess for locale:", locale);
655
+ const translations = await client.getTranslations(locale);
656
+ console.log("Saving translations in file:", options.path);
657
+ if (options.format === "flat" /* FLAT */) {
658
+ await writeFile(options.path, JSON.stringify(translations, null, 2));
659
+ } else if (options.format === "nested" /* NESTED */) {
660
+ const nestedTranslations = dotToNestedObject(translations);
661
+ await writeFile(options.path, JSON.stringify(nestedTranslations, null, 2));
662
+ }
663
+ console.log("Successfully saved translations from Localess");
664
+ });
665
+
608
666
  // src/commands/translations/index.ts
609
- var translationsCommand = new import_commander6.Command("translations").description("Manage translations").addCommand(translationsPushCommand);
667
+ var translationsCommand = new import_commander7.Command("translations").description("Manage translations").addCommand(translationsPushCommand).addCommand(translationsPullCommand);
610
668
 
611
669
  // src/program.ts
612
- var program = new import_commander7.Command();
670
+ var program = new import_commander8.Command();
613
671
  program.name("Localess CLI").description("CLI tool for Localess platform management").version("0.0.1");
614
672
  program.addCommand(loginCommand);
615
673
  program.addCommand(logoutCommand);
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/program.ts
4
- import { Command as Command7 } from "commander";
4
+ import { Command as Command8 } from "commander";
5
5
 
6
6
  // src/commands/login/index.ts
7
7
  import { Command } from "commander";
@@ -9,6 +9,24 @@ import { Command } from "commander";
9
9
  // src/utils.ts
10
10
  var RESET = "\x1B[0m";
11
11
  var FG_BLUE = "\x1B[34m";
12
+ function dotToNestedObject(input) {
13
+ const result = {};
14
+ for (const [key, value] of Object.entries(input)) {
15
+ const parts = key.split(".");
16
+ let current = result;
17
+ for (let i = 0; i < parts.length; i++) {
18
+ if (i === parts.length - 1) {
19
+ current[parts[i]] = value;
20
+ } else {
21
+ if (!(parts[i] in current)) {
22
+ current[parts[i]] = {};
23
+ }
24
+ current = current[parts[i]];
25
+ }
26
+ }
27
+ }
28
+ return result;
29
+ }
12
30
 
13
31
  // src/cache.ts
14
32
  var NoCache = class {
@@ -486,7 +504,7 @@ import openapiTS, { astToString } from "openapi-typescript";
486
504
  import { join as join2 } from "path";
487
505
  import process3 from "process";
488
506
  var TYPES_PATH = join2(process3.cwd(), DEFAULT_CONFIG_DIR, "localess.d.ts");
489
- var typesGenerateCommand = new Command3("generate").description("Generate types for your schemas").option("-f, --file <path>", "Path to the file where to save the generated types. Default is .localess/localess.d.ts", TYPES_PATH).action(async (options) => {
507
+ var typesGenerateCommand = new Command3("generate").description("Generate types for your schemas").option("-p, --path <path>", "Path to the file where to save the generated types. Default is .localess/localess.d.ts", TYPES_PATH).action(async (options) => {
490
508
  console.log("Types in with options:", options);
491
509
  const session = await getSession();
492
510
  if (!session.isLoggedIn) {
@@ -510,8 +528,8 @@ var typesGenerateCommand = new Command3("generate").description("Generate types
510
528
  };
511
529
  const ast = await openapiTS(minimalSpec, { exportType: true, rootTypes: true, rootTypesNoSchemaPrefix: true });
512
530
  const contents = astToString(ast);
513
- await writeFile(options.file, contents);
514
- console.log(`Types generated successfully at ${options.file}`);
531
+ await writeFile(options.path, contents);
532
+ console.log(`Types generated successfully at ${options.path}`);
515
533
  } catch (e) {
516
534
  console.error(e);
517
535
  }
@@ -521,7 +539,7 @@ var typesGenerateCommand = new Command3("generate").description("Generate types
521
539
  var typesCommand = new Command4("types").description("Generate types for your schemas").addCommand(typesGenerateCommand);
522
540
 
523
541
  // src/commands/translations/index.ts
524
- import { Command as Command6 } from "commander";
542
+ import { Command as Command7 } from "commander";
525
543
 
526
544
  // src/commands/translations/push/index.ts
527
545
  import { Command as Command5 } from "commander";
@@ -532,6 +550,11 @@ var TranslationUpdateType = /* @__PURE__ */ ((TranslationUpdateType2) => {
532
550
  TranslationUpdateType2["UPDATE_EXISTING"] = "update-existing";
533
551
  return TranslationUpdateType2;
534
552
  })(TranslationUpdateType || {});
553
+ var TranslationFileFormat = /* @__PURE__ */ ((TranslationFileFormat2) => {
554
+ TranslationFileFormat2["FLAT"] = "flat";
555
+ TranslationFileFormat2["NESTED"] = "nested";
556
+ return TranslationFileFormat2;
557
+ })(TranslationFileFormat || {});
535
558
 
536
559
  // src/models/translation.zod.ts
537
560
  import { z } from "zod";
@@ -543,7 +566,7 @@ var zTranslationUpdateSchema = z.object({
543
566
  });
544
567
 
545
568
  // src/commands/translations/push/index.ts
546
- var translationsPushCommand = new Command5("push").argument("<locale>", "Locale to push").description("Push locale translations to Localess").requiredOption("-f, --file <path>", "Path to the translations file to push").option("-t, --type <type>", `Push type. Possible values are : ${Object.values(TranslationUpdateType)}`, "add-missing" /* ADD_MISSING */).action(async (locale, options) => {
569
+ var translationsPushCommand = new Command5("push").argument("<locale>", "Locale to push").description("Push locale translations to Localess").requiredOption("-p, --path <path>", "Path to the translations file to push").option("-f, --format <format>", `File format. Possible values are : ${Object.values(TranslationFileFormat)}`, "flat" /* FLAT */).option("-t, --type <type>", `Push type. Possible values are : ${Object.values(TranslationUpdateType)}`, "add-missing" /* ADD_MISSING */).action(async (locale, options) => {
547
570
  console.log("Pushing translations with arguments:", locale);
548
571
  console.log("Pushing translations with options:", options);
549
572
  if (!zTranslationUpdateTypeSchema.safeParse(options.type).success) {
@@ -561,8 +584,11 @@ var translationsPushCommand = new Command5("push").argument("<locale>", "Locale
561
584
  spaceId: session.space,
562
585
  token: session.token
563
586
  });
564
- console.log("Reading translations file from:", options.file);
565
- const fileContent = await readFile(options.file);
587
+ if (options.format === "nested" /* NESTED */) {
588
+ console.error("Nested format is not implemented yet. Please use flat format for now.");
589
+ }
590
+ console.log("Reading translations file from:", options.path);
591
+ const fileContent = await readFile(options.path);
566
592
  const translationValues = JSON.parse(fileContent);
567
593
  const pResult = zLocaleTranslationsSchema.safeParse(translationValues);
568
594
  if (!pResult.success) {
@@ -582,11 +608,43 @@ var translationsPushCommand = new Command5("push").argument("<locale>", "Locale
582
608
  }
583
609
  });
584
610
 
611
+ // src/commands/translations/pull/index.ts
612
+ import { Command as Command6 } from "commander";
613
+ var translationsPullCommand = new Command6("pull").argument("<locale>", "Locale to pull").description("Pull locale translations from Localess").requiredOption("-p, --path <path>", "Path where the translations file will be saved").option("-f, --format <format>", `File format. Possible values are : ${Object.values(TranslationFileFormat)}`, "flat" /* FLAT */).action(async (locale, options) => {
614
+ console.log("Pulling translations with arguments:", locale);
615
+ console.log("Pulling translations with options:", options);
616
+ if (!Object.values(TranslationFileFormat).includes(options.format)) {
617
+ console.error("Invalid format provided. Possible values are :", Object.values(TranslationFileFormat));
618
+ return;
619
+ }
620
+ const session = await getSession();
621
+ if (!session.isLoggedIn) {
622
+ console.error("Not logged in");
623
+ console.error('Please log in first using "localess login" command');
624
+ return;
625
+ }
626
+ const client = localessClient({
627
+ origin: session.origin,
628
+ spaceId: session.space,
629
+ token: session.token
630
+ });
631
+ console.log("Pulling translations from Localess for locale:", locale);
632
+ const translations = await client.getTranslations(locale);
633
+ console.log("Saving translations in file:", options.path);
634
+ if (options.format === "flat" /* FLAT */) {
635
+ await writeFile(options.path, JSON.stringify(translations, null, 2));
636
+ } else if (options.format === "nested" /* NESTED */) {
637
+ const nestedTranslations = dotToNestedObject(translations);
638
+ await writeFile(options.path, JSON.stringify(nestedTranslations, null, 2));
639
+ }
640
+ console.log("Successfully saved translations from Localess");
641
+ });
642
+
585
643
  // src/commands/translations/index.ts
586
- var translationsCommand = new Command6("translations").description("Manage translations").addCommand(translationsPushCommand);
644
+ var translationsCommand = new Command7("translations").description("Manage translations").addCommand(translationsPushCommand).addCommand(translationsPullCommand);
587
645
 
588
646
  // src/program.ts
589
- var program = new Command7();
647
+ var program = new Command8();
590
648
  program.name("Localess CLI").description("CLI tool for Localess platform management").version("0.0.1");
591
649
  program.addCommand(loginCommand);
592
650
  program.addCommand(logoutCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localess/cli",
3
- "version": "0.0.1-dev.20260220221945",
3
+ "version": "0.0.1-dev.20260221224153",
4
4
  "description": "Localess Command Line.",
5
5
  "keywords": [
6
6
  "localess",