@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 +30 -4
- package/dist/index.js +68 -10
- package/dist/index.mjs +68 -10
- package/package.json +1 -1
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`
|
|
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
|
|
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("-
|
|
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.
|
|
537
|
-
console.log(`Types generated successfully at ${options.
|
|
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
|
|
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("-
|
|
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
|
-
|
|
588
|
-
|
|
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
|
|
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
|
|
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
|
|
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("-
|
|
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.
|
|
514
|
-
console.log(`Types generated successfully at ${options.
|
|
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
|
|
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("-
|
|
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
|
-
|
|
565
|
-
|
|
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
|
|
644
|
+
var translationsCommand = new Command7("translations").description("Manage translations").addCommand(translationsPushCommand).addCommand(translationsPullCommand);
|
|
587
645
|
|
|
588
646
|
// src/program.ts
|
|
589
|
-
var program = new
|
|
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);
|