lezu 0.0.41 → 0.0.43

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.
@@ -1,321 +0,0 @@
1
- import {
2
- loadConfig,
3
- validateConfig
4
- } from "./chunk-EDQCBUBB.js";
5
- import {
6
- LezuApiClient
7
- } from "./chunk-HFRJAE6K.js";
8
-
9
- // src/commands/load.ts
10
- import { Command } from "commander";
11
- import chalk from "chalk";
12
- import ora from "ora";
13
- import { confirm, isCancel, text, select } from "@clack/prompts";
14
-
15
- // src/writer.ts
16
- import { writeFileSync, mkdirSync } from "fs";
17
- import { dirname, join } from "path";
18
- var TranslationWriter = class {
19
- config;
20
- constructor(config) {
21
- this.config = config;
22
- }
23
- write(translations) {
24
- mkdirSync(this.config.dest, { recursive: true });
25
- for (const [language, content] of Object.entries(translations)) {
26
- const processedContent = this.processContent(content);
27
- const filePath = this.getFilePath(language);
28
- mkdirSync(dirname(filePath), { recursive: true });
29
- const fileContent = this.formatContent(processedContent, language);
30
- writeFileSync(filePath, fileContent, "utf-8");
31
- console.log(`[Written] ${language} translations to ${filePath}`);
32
- }
33
- }
34
- processContent(content) {
35
- if (this.config.flatten) {
36
- return this.flattenObject(content);
37
- }
38
- if (!this.config.includeEmpty) {
39
- return this.removeEmptyValues(content);
40
- }
41
- return content;
42
- }
43
- flattenObject(obj, prefix = "") {
44
- const result = {};
45
- for (const [key, value] of Object.entries(obj)) {
46
- const newKey = prefix ? `${prefix}.${key}` : key;
47
- if (typeof value === "object" && value !== null && !Array.isArray(value)) {
48
- Object.assign(result, this.flattenObject(value, newKey));
49
- } else {
50
- result[newKey] = value;
51
- }
52
- }
53
- return result;
54
- }
55
- removeEmptyValues(obj) {
56
- if (typeof obj !== "object" || obj === null) {
57
- return obj;
58
- }
59
- const result = {};
60
- for (const [key, value] of Object.entries(obj)) {
61
- if (typeof value === "object" && value !== null) {
62
- const cleaned = this.removeEmptyValues(value);
63
- if (Object.keys(cleaned).length > 0) {
64
- result[key] = cleaned;
65
- }
66
- } else if (value !== "" && value !== null && value !== void 0) {
67
- result[key] = value;
68
- }
69
- }
70
- return result;
71
- }
72
- getFilePath(language) {
73
- const extension = this.getFileExtension();
74
- if (this.config.namespace) {
75
- return join(this.config.dest, "locales", `${language}.${extension}`);
76
- } else {
77
- return join(this.config.dest, `${language}.${extension}`);
78
- }
79
- }
80
- getFileExtension() {
81
- switch (this.config.format) {
82
- case "json":
83
- return "json";
84
- case "js":
85
- return "js";
86
- case "ts":
87
- return "ts";
88
- case "yaml":
89
- return "yaml";
90
- case "po":
91
- return "po";
92
- default:
93
- return "json";
94
- }
95
- }
96
- formatContent(content, language) {
97
- switch (this.config.format) {
98
- case "json":
99
- return JSON.stringify(content, null, 2);
100
- case "js":
101
- return `export default ${JSON.stringify(content, null, 2)}`;
102
- case "ts":
103
- return `const translations = ${JSON.stringify(content, null, 2)} as const
104
-
105
- export default translations`;
106
- case "yaml":
107
- return this.toYaml(content);
108
- case "po":
109
- return this.toPo(content, language);
110
- default:
111
- return JSON.stringify(content, null, 2);
112
- }
113
- }
114
- toYaml(obj, indent = 0) {
115
- let result = "";
116
- const spaces = " ".repeat(indent);
117
- for (const [key, value] of Object.entries(obj)) {
118
- if (typeof value === "object" && value !== null) {
119
- result += `${spaces}${key}:
120
- ${this.toYaml(value, indent + 2)}`;
121
- } else {
122
- const escapedValue = String(value).includes(":") || String(value).includes("#") ? `"${String(value).replace(/"/g, '\\"')}"` : value;
123
- result += `${spaces}${key}: ${escapedValue}
124
- `;
125
- }
126
- }
127
- return result;
128
- }
129
- toPo(obj, language) {
130
- const now = (/* @__PURE__ */ new Date()).toISOString();
131
- let result = `# Translation file for ${language}
132
- # Generated by Lezu CLI on ${now}
133
- msgid ""
134
- msgstr ""
135
- "Language: ${language}\\n"
136
- "MIME-Version: 1.0\\n"
137
- "Content-Type: text/plain; charset=UTF-8\\n"
138
- "Content-Transfer-Encoding: 8bit\\n"
139
- "Generated-By: Lezu CLI\\n"
140
-
141
- `;
142
- const flatEntries = this.flattenForPo(obj);
143
- for (const [key, value] of Object.entries(flatEntries)) {
144
- const escapedKey = this.escapePoString(key);
145
- const escapedValue = this.escapePoString(String(value));
146
- result += `msgid "${escapedKey}"
147
- `;
148
- result += `msgstr "${escapedValue}"
149
-
150
- `;
151
- }
152
- return result;
153
- }
154
- flattenForPo(obj, prefix = "") {
155
- const result = {};
156
- for (const [key, value] of Object.entries(obj)) {
157
- const fullKey = prefix ? `${prefix}.${key}` : key;
158
- if (typeof value === "object" && value !== null && !Array.isArray(value)) {
159
- Object.assign(result, this.flattenForPo(value, fullKey));
160
- } else {
161
- result[fullKey] = String(value);
162
- }
163
- }
164
- return result;
165
- }
166
- escapePoString(str) {
167
- return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
168
- }
169
- };
170
-
171
- // src/commands/load.ts
172
- function createLoadCommand() {
173
- const command = new Command("load").description("Download translation files from Lezu").option("-p, --project <id>", "Project ID").option("-k, --api-key <key>", "API key").option("-d, --dest <path>", "Destination folder", "./src/i18n").option("-f, --format <format>", "Output format (json, js, ts, yaml, po)", "json").option("-l, --languages <languages>", "Comma-separated list of languages to download").option("-r, --release <id>", "Specific release ID").option("-e, --environment <env>", "Environment", "production").option("--api-url <url>", "API URL", "https://api.lezu.app").option("--flatten", "Flatten nested keys").option("--namespace", "Use namespace folder structure").option("--include-empty", "Include empty translations").option("-w, --watch", "Watch for changes").option("--watch-interval <ms>", "Watch interval in milliseconds", "5000").action(async (options) => {
174
- try {
175
- if (options.languages) {
176
- options.languages = options.languages.split(",").map((l) => l.trim());
177
- }
178
- if (options.watchInterval) {
179
- options.watchInterval = parseInt(options.watchInterval, 10);
180
- }
181
- const config = loadConfig(options);
182
- const errors = validateConfig(config);
183
- if (errors.length > 0) {
184
- console.error(chalk.red("Configuration errors:"));
185
- errors.forEach((error) => console.error(chalk.red(` - ${error}`)));
186
- process.exit(1);
187
- }
188
- await syncTranslations(config);
189
- if (config.watch) {
190
- console.log(chalk.cyan(`
191
- [Watching] Monitoring for changes every ${config.watchInterval}ms...`));
192
- console.log(chalk.gray("Press Ctrl+C to stop"));
193
- setInterval(async () => {
194
- console.log(chalk.gray("\n[Checking] Looking for updates..."));
195
- await syncTranslations(config);
196
- }, config.watchInterval);
197
- }
198
- } catch (error) {
199
- console.error(chalk.red("\n[Error]"), error instanceof Error ? error.message : error);
200
- process.exit(1);
201
- }
202
- });
203
- return command;
204
- }
205
- async function syncTranslations(config) {
206
- const spinner = ora("Connecting to Lezu API...").start();
207
- try {
208
- const client = new LezuApiClient(config);
209
- if (!config.languages || config.languages.length === 0) {
210
- spinner.text = "Fetching project languages...";
211
- try {
212
- const projectData = await client.getProject();
213
- const projectLanguages = projectData.project.languages || ["en"];
214
- config.languages = Array.isArray(projectLanguages) ? projectLanguages.map((lang) => typeof lang === "string" ? lang : lang.code) : ["en"];
215
- spinner.info(`Using project languages: ${config.languages.join(", ")}`);
216
- spinner.start("Connecting to Lezu API...");
217
- } catch (error) {
218
- spinner.warn('Could not fetch project languages, defaulting to "en"');
219
- config.languages = ["en"];
220
- spinner.start("Connecting to Lezu API...");
221
- }
222
- }
223
- if (!config.release) {
224
- spinner.text = "Fetching environments...";
225
- const environmentsResponse = await client.getEnvironments();
226
- const environments = environmentsResponse.environments;
227
- let selectedEnvironment = config.environment || "production";
228
- if (environments.length > 1 && !config.environment) {
229
- spinner.stop();
230
- const environmentChoice = await select({
231
- message: "Select an environment:",
232
- options: environments.map((env) => ({
233
- value: env.name,
234
- label: `${env.name}${env.description ? ` - ${env.description}` : ""}`
235
- }))
236
- });
237
- if (isCancel(environmentChoice)) {
238
- console.log(chalk.yellow("\nOperation cancelled"));
239
- process.exit(0);
240
- }
241
- selectedEnvironment = environmentChoice;
242
- config.environment = selectedEnvironment;
243
- spinner.start("Fetching current release...");
244
- }
245
- spinner.text = `Fetching current release for ${selectedEnvironment}...`;
246
- const currentRelease = await client.getCurrentRelease(selectedEnvironment);
247
- if (currentRelease) {
248
- config.release = currentRelease;
249
- spinner.succeed(`Using current release for ${selectedEnvironment}: ${currentRelease}`);
250
- spinner.start("Fetching translations...");
251
- } else {
252
- spinner.fail(`No releases found for environment: ${selectedEnvironment}`);
253
- console.log(chalk.yellow("\n\u26A0\uFE0F Could not fetch releases. This might be due to no releases existing yet."));
254
- console.log(chalk.gray("Releases provide cached, versioned snapshots that are fast and efficient."));
255
- const shouldCreateRelease = await confirm({
256
- message: "Would you like to create a release now?",
257
- initialValue: true
258
- });
259
- if (isCancel(shouldCreateRelease) || !shouldCreateRelease) {
260
- console.log(chalk.red("\n\u2716 A release is required to download translations"));
261
- console.log(chalk.gray("\nOptions:"));
262
- console.log(chalk.gray(" 1. Create a release through the Lezu dashboard"));
263
- console.log(chalk.gray(" 2. Use: npx lezu release create"));
264
- process.exit(1);
265
- }
266
- const version = await text({
267
- message: "Version",
268
- placeholder: (/* @__PURE__ */ new Date()).toISOString().split("T")[0].replace(/-/g, "."),
269
- initialValue: (/* @__PURE__ */ new Date()).toISOString().split("T")[0].replace(/-/g, ".")
270
- });
271
- if (isCancel(version)) {
272
- console.log(chalk.yellow("\nOperation cancelled"));
273
- process.exit(0);
274
- }
275
- spinner.start("Creating release...");
276
- try {
277
- const release = await client.createRelease({
278
- version,
279
- name: "Initial Release",
280
- description: "Created by Lezu CLI"
281
- });
282
- config.release = release.release.id;
283
- spinner.succeed(`Created release v${release.release.version}`);
284
- spinner.start("Fetching translations...");
285
- } catch (error) {
286
- spinner.fail("Failed to create release");
287
- console.log(chalk.red("\n\u2716 Cannot continue without a release"));
288
- console.log(chalk.gray("Please check your permissions or try again later."));
289
- process.exit(1);
290
- }
291
- }
292
- }
293
- spinner.text = "Fetching translations...";
294
- const response = await client.getTranslations();
295
- if (!response.translations || Object.keys(response.translations).length === 0) {
296
- spinner.fail("No translations found");
297
- return;
298
- }
299
- spinner.succeed(`Fetched translations for ${Object.keys(response.translations).length} languages`);
300
- const writer = new TranslationWriter(config);
301
- writer.write(response.translations);
302
- console.log(chalk.green("\n[Success] Translations synced successfully!"));
303
- console.log(chalk.gray("\nSummary:"));
304
- console.log(chalk.gray(` - Project: ${config.projectId}`));
305
- console.log(chalk.gray(` - Languages: ${Object.keys(response.translations).join(", ")}`));
306
- console.log(chalk.gray(` - Destination: ${config.dest}`));
307
- console.log(chalk.gray(` - Format: ${config.format}`));
308
- if (response.meta?.version) {
309
- console.log(chalk.gray(` - Version: ${response.meta.version}`));
310
- }
311
- } catch (error) {
312
- spinner.fail("Failed to sync translations");
313
- throw error;
314
- }
315
- }
316
-
317
- export {
318
- createLoadCommand,
319
- syncTranslations
320
- };
321
- //# sourceMappingURL=chunk-4LVALDII.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/load.ts","../src/writer.ts"],"sourcesContent":["import { Command } from 'commander'\nimport chalk from 'chalk'\nimport ora from 'ora'\nimport { confirm, isCancel, text, select } from '@clack/prompts'\nimport { loadConfig, validateConfig } from '../config.js'\nimport { LezuApiClient } from '../api.js'\nimport { TranslationWriter } from '../writer.js'\nimport type { Config } from '../types.js'\n\nexport function createLoadCommand() {\n const command = new Command('load')\n .description('Download translation files from Lezu')\n .option('-p, --project <id>', 'Project ID')\n .option('-k, --api-key <key>', 'API key')\n .option('-d, --dest <path>', 'Destination folder', './src/i18n')\n .option('-f, --format <format>', 'Output format (json, js, ts, yaml, po)', 'json')\n .option('-l, --languages <languages>', 'Comma-separated list of languages to download')\n .option('-r, --release <id>', 'Specific release ID')\n .option('-e, --environment <env>', 'Environment', 'production')\n .option('--api-url <url>', 'API URL', 'https://api.lezu.app')\n .option('--flatten', 'Flatten nested keys')\n .option('--namespace', 'Use namespace folder structure')\n .option('--include-empty', 'Include empty translations')\n .option('-w, --watch', 'Watch for changes')\n .option('--watch-interval <ms>', 'Watch interval in milliseconds', '5000')\n .action(async (options) => {\n try {\n // Parse languages from comma-separated string\n if (options.languages) {\n options.languages = options.languages.split(',').map((l: string) => l.trim())\n }\n\n // Convert watch interval to number\n if (options.watchInterval) {\n options.watchInterval = parseInt(options.watchInterval, 10)\n }\n\n // Load configuration\n const config = loadConfig(options)\n\n // Validate configuration\n const errors = validateConfig(config)\n if (errors.length > 0) {\n console.error(chalk.red('Configuration errors:'))\n errors.forEach(error => console.error(chalk.red(` - ${error}`)))\n process.exit(1)\n }\n\n // Run the sync\n await syncTranslations(config)\n\n // Watch mode\n if (config.watch) {\n console.log(chalk.cyan(`\\n[Watching] Monitoring for changes every ${config.watchInterval}ms...`))\n console.log(chalk.gray('Press Ctrl+C to stop'))\n \n setInterval(async () => {\n console.log(chalk.gray('\\n[Checking] Looking for updates...'))\n await syncTranslations(config)\n }, config.watchInterval)\n }\n } catch (error) {\n console.error(chalk.red('\\n[Error]'), error instanceof Error ? error.message : error)\n process.exit(1)\n }\n })\n\n return command\n}\n\nexport async function syncTranslations(config: Config) {\n const spinner = ora('Connecting to Lezu API...').start()\n\n try {\n // Create API client\n const client = new LezuApiClient(config)\n \n // If no languages specified, fetch project languages\n if (!config.languages || config.languages.length === 0) {\n spinner.text = 'Fetching project languages...'\n try {\n const projectData = await client.getProject()\n \n // Extract language codes from project\n const projectLanguages = projectData.project.languages || ['en']\n config.languages = Array.isArray(projectLanguages) \n ? projectLanguages.map((lang: any) => typeof lang === 'string' ? lang : lang.code)\n : ['en']\n \n spinner.info(`Using project languages: ${config.languages.join(', ')}`)\n spinner.start('Connecting to Lezu API...')\n } catch (error) {\n spinner.warn('Could not fetch project languages, defaulting to \"en\"')\n config.languages = ['en']\n spinner.start('Connecting to Lezu API...')\n }\n }\n\n // Environment selection and release handling\n if (!config.release) {\n spinner.text = 'Fetching environments...'\n const environmentsResponse = await client.getEnvironments()\n const environments = environmentsResponse.environments\n \n let selectedEnvironment = config.environment || 'production'\n \n // If there are multiple environments and no environment specified, ask user to choose\n if (environments.length > 1 && !config.environment) {\n spinner.stop()\n \n const environmentChoice = await select({\n message: 'Select an environment:',\n options: environments.map((env: any) => ({\n value: env.name,\n label: `${env.name}${env.description ? ` - ${env.description}` : ''}`\n }))\n })\n \n if (isCancel(environmentChoice)) {\n console.log(chalk.yellow('\\nOperation cancelled'))\n process.exit(0)\n }\n \n selectedEnvironment = environmentChoice as string\n config.environment = selectedEnvironment\n spinner.start('Fetching current release...')\n }\n \n spinner.text = `Fetching current release for ${selectedEnvironment}...`\n const currentRelease = await client.getCurrentRelease(selectedEnvironment)\n \n if (currentRelease) {\n config.release = currentRelease\n spinner.succeed(`Using current release for ${selectedEnvironment}: ${currentRelease}`)\n spinner.start('Fetching translations...')\n } else {\n spinner.fail(`No releases found for environment: ${selectedEnvironment}`)\n console.log(chalk.yellow('\\n⚠️ Could not fetch releases. This might be due to no releases existing yet.'))\n console.log(chalk.gray('Releases provide cached, versioned snapshots that are fast and efficient.'))\n \n const shouldCreateRelease = await confirm({\n message: 'Would you like to create a release now?',\n initialValue: true\n })\n \n if (isCancel(shouldCreateRelease) || !shouldCreateRelease) {\n console.log(chalk.red('\\n✖ A release is required to download translations'))\n console.log(chalk.gray('\\nOptions:'))\n console.log(chalk.gray(' 1. Create a release through the Lezu dashboard'))\n console.log(chalk.gray(' 2. Use: npx lezu release create'))\n process.exit(1)\n }\n \n // Prompt for version\n const version = await text({\n message: 'Version',\n placeholder: new Date().toISOString().split('T')[0].replace(/-/g, '.'),\n initialValue: new Date().toISOString().split('T')[0].replace(/-/g, '.')\n })\n \n if (isCancel(version)) {\n console.log(chalk.yellow('\\nOperation cancelled'))\n process.exit(0)\n }\n \n spinner.start('Creating release...')\n \n try {\n const release = await client.createRelease({\n version: version as string,\n name: 'Initial Release',\n description: 'Created by Lezu CLI'\n })\n config.release = release.release.id\n spinner.succeed(`Created release v${release.release.version}`)\n spinner.start('Fetching translations...')\n } catch (error) {\n spinner.fail('Failed to create release')\n console.log(chalk.red('\\n✖ Cannot continue without a release'))\n console.log(chalk.gray('Please check your permissions or try again later.'))\n process.exit(1)\n }\n }\n }\n\n // Fetch translations\n spinner.text = 'Fetching translations...'\n const response = await client.getTranslations()\n\n if (!response.translations || Object.keys(response.translations).length === 0) {\n spinner.fail('No translations found')\n return\n }\n\n spinner.succeed(`Fetched translations for ${Object.keys(response.translations).length} languages`)\n\n // Write translations\n const writer = new TranslationWriter(config)\n writer.write(response.translations)\n\n console.log(chalk.green('\\n[Success] Translations synced successfully!'))\n\n // Show summary\n console.log(chalk.gray('\\nSummary:'))\n console.log(chalk.gray(` - Project: ${config.projectId}`))\n console.log(chalk.gray(` - Languages: ${Object.keys(response.translations).join(', ')}`))\n console.log(chalk.gray(` - Destination: ${config.dest}`))\n console.log(chalk.gray(` - Format: ${config.format}`))\n \n if (response.meta?.version) {\n console.log(chalk.gray(` - Version: ${response.meta.version}`))\n }\n\n } catch (error) {\n spinner.fail('Failed to sync translations')\n throw error\n }\n}","import { writeFileSync, mkdirSync } from 'fs'\nimport { resolve, dirname, join } from 'path'\nimport type { Config, TranslationBundle } from './types.js'\n\nexport class TranslationWriter {\n private config: Config\n\n constructor(config: Config) {\n this.config = config\n }\n\n write(translations: Record<string, any>): void {\n // Ensure destination directory exists\n mkdirSync(this.config.dest, { recursive: true })\n\n // Write each language to its own file\n for (const [language, content] of Object.entries(translations)) {\n const processedContent = this.processContent(content)\n const filePath = this.getFilePath(language)\n \n mkdirSync(dirname(filePath), { recursive: true })\n \n const fileContent = this.formatContent(processedContent, language)\n writeFileSync(filePath, fileContent, 'utf-8')\n \n console.log(`[Written] ${language} translations to ${filePath}`)\n }\n }\n\n private processContent(content: any): any {\n if (this.config.flatten) {\n return this.flattenObject(content)\n }\n \n if (!this.config.includeEmpty) {\n return this.removeEmptyValues(content)\n }\n \n return content\n }\n\n private flattenObject(obj: any, prefix = ''): Record<string, string> {\n const result: Record<string, string> = {}\n \n for (const [key, value] of Object.entries(obj)) {\n const newKey = prefix ? `${prefix}.${key}` : key\n \n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n Object.assign(result, this.flattenObject(value, newKey))\n } else {\n result[newKey] = value as string\n }\n }\n \n return result\n }\n\n private removeEmptyValues(obj: any): any {\n if (typeof obj !== 'object' || obj === null) {\n return obj\n }\n \n const result: any = {}\n \n for (const [key, value] of Object.entries(obj)) {\n if (typeof value === 'object' && value !== null) {\n const cleaned = this.removeEmptyValues(value)\n if (Object.keys(cleaned).length > 0) {\n result[key] = cleaned\n }\n } else if (value !== '' && value !== null && value !== undefined) {\n result[key] = value\n }\n }\n \n return result\n }\n\n private getFilePath(language: string): string {\n const extension = this.getFileExtension()\n \n if (this.config.namespace) {\n // Use namespace structure: dest/locales/en.json\n return join(this.config.dest, 'locales', `${language}.${extension}`)\n } else {\n // Use flat structure: dest/en.json\n return join(this.config.dest, `${language}.${extension}`)\n }\n }\n\n private getFileExtension(): string {\n switch (this.config.format) {\n case 'json':\n return 'json'\n case 'js':\n return 'js'\n case 'ts':\n return 'ts'\n case 'yaml':\n return 'yaml'\n case 'po':\n return 'po'\n default:\n return 'json'\n }\n }\n\n private formatContent(content: any, language: string): string {\n switch (this.config.format) {\n case 'json':\n return JSON.stringify(content, null, 2)\n \n case 'js':\n return `export default ${JSON.stringify(content, null, 2)}`\n \n case 'ts':\n return `const translations = ${JSON.stringify(content, null, 2)} as const\\n\\nexport default translations`\n \n case 'yaml':\n return this.toYaml(content)\n \n case 'po':\n return this.toPo(content, language)\n \n default:\n return JSON.stringify(content, null, 2)\n }\n }\n\n private toYaml(obj: any, indent = 0): string {\n let result = ''\n const spaces = ' '.repeat(indent)\n \n for (const [key, value] of Object.entries(obj)) {\n if (typeof value === 'object' && value !== null) {\n result += `${spaces}${key}:\\n${this.toYaml(value, indent + 2)}`\n } else {\n const escapedValue = String(value).includes(':') || String(value).includes('#') \n ? `\"${String(value).replace(/\"/g, '\\\\\"')}\"` \n : value\n result += `${spaces}${key}: ${escapedValue}\\n`\n }\n }\n \n return result\n }\n\n private toPo(obj: any, language: string): string {\n const now = new Date().toISOString()\n let result = `# Translation file for ${language}\n# Generated by Lezu CLI on ${now}\nmsgid \"\"\nmsgstr \"\"\n\"Language: ${language}\\\\n\"\n\"MIME-Version: 1.0\\\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\\\n\"\n\"Content-Transfer-Encoding: 8bit\\\\n\"\n\"Generated-By: Lezu CLI\\\\n\"\n\n`\n\n const flatEntries = this.flattenForPo(obj)\n \n for (const [key, value] of Object.entries(flatEntries)) {\n const escapedKey = this.escapePoString(key)\n const escapedValue = this.escapePoString(String(value))\n \n result += `msgid \"${escapedKey}\"\\n`\n result += `msgstr \"${escapedValue}\"\\n\\n`\n }\n \n return result\n }\n\n private flattenForPo(obj: any, prefix = ''): Record<string, string> {\n const result: Record<string, string> = {}\n \n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n \n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n Object.assign(result, this.flattenForPo(value, fullKey))\n } else {\n result[fullKey] = String(value)\n }\n }\n \n return result\n }\n\n private escapePoString(str: string): string {\n return str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t')\n }\n}"],"mappings":"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","names":[]}
@@ -1,96 +0,0 @@
1
- // src/config.ts
2
- import { readFileSync, existsSync } from "fs";
3
- import { resolve } from "path";
4
- import dotenv from "dotenv";
5
-
6
- // src/types.ts
7
- import { z } from "zod";
8
- var ConfigSchema = z.object({
9
- projectId: z.string().optional(),
10
- apiKey: z.string().optional(),
11
- apiUrl: z.string().default("https://api.lezu.app"),
12
- dest: z.string().default("./src/i18n"),
13
- format: z.enum(["json", "js", "ts", "yaml", "po"]).default("json"),
14
- languages: z.array(z.string()).optional(),
15
- release: z.string().optional(),
16
- environment: z.string().default("production"),
17
- flatten: z.boolean().default(false),
18
- namespace: z.boolean().default(false),
19
- includeEmpty: z.boolean().default(false),
20
- watch: z.boolean().default(false),
21
- watchInterval: z.number().default(5e3),
22
- debug: z.boolean().default(false)
23
- });
24
-
25
- // src/config.ts
26
- dotenv.config();
27
- function loadConfig(options = {}) {
28
- let config = {
29
- apiUrl: "https://api.lezu.app",
30
- dest: "./src/i18n",
31
- format: "json",
32
- environment: "production",
33
- flatten: false,
34
- namespace: false,
35
- includeEmpty: false,
36
- watch: false,
37
- watchInterval: 5e3
38
- };
39
- const configFiles = [".lezurc", ".lezurc.json", "lezu.config.json"];
40
- for (const file of configFiles) {
41
- const configPath = resolve(process.cwd(), file);
42
- if (existsSync(configPath)) {
43
- try {
44
- const content = readFileSync(configPath, "utf-8");
45
- const fileConfig = JSON.parse(content);
46
- config = { ...config, ...fileConfig };
47
- break;
48
- } catch (error) {
49
- console.warn(`[Warning] Failed to load config from ${file}:`, error);
50
- }
51
- }
52
- }
53
- if (process.env.LEZU_PROJECT_ID) {
54
- config.projectId = process.env.LEZU_PROJECT_ID;
55
- }
56
- if (process.env.LEZU_API_KEY) {
57
- config.apiKey = process.env.LEZU_API_KEY;
58
- }
59
- if (process.env.LEZU_API_URL) {
60
- config.apiUrl = process.env.LEZU_API_URL;
61
- }
62
- if (process.env.LEZU_DEST) {
63
- config.dest = process.env.LEZU_DEST;
64
- }
65
- if (process.env.LEZU_FORMAT) {
66
- config.format = process.env.LEZU_FORMAT;
67
- }
68
- if (process.env.LEZU_ENVIRONMENT) {
69
- config.environment = process.env.LEZU_ENVIRONMENT;
70
- }
71
- config = { ...config, ...options };
72
- try {
73
- return ConfigSchema.parse(config);
74
- } catch (error) {
75
- if (error instanceof Error) {
76
- throw new Error(`Invalid configuration: ${error.message}`);
77
- }
78
- throw error;
79
- }
80
- }
81
- function validateConfig(config) {
82
- const errors = [];
83
- if (!config.projectId) {
84
- errors.push("Project ID is required (use --project, LEZU_PROJECT_ID env var, or projectId in config file)");
85
- }
86
- if (!config.apiKey) {
87
- errors.push("API Key is required (use --api-key, LEZU_API_KEY env var, or apiKey in config file)");
88
- }
89
- return errors;
90
- }
91
-
92
- export {
93
- loadConfig,
94
- validateConfig
95
- };
96
- //# sourceMappingURL=chunk-EDQCBUBB.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config.ts","../src/types.ts"],"sourcesContent":["import { readFileSync, existsSync } from 'fs'\nimport { resolve } from 'path'\nimport dotenv from 'dotenv'\nimport { Config, ConfigSchema } from './types.js'\n\n// Load environment variables\ndotenv.config()\n\nexport function loadConfig(options: Partial<Config> = {}): Config {\n // 1. Start with defaults\n let config: Partial<Config> = {\n apiUrl: 'https://api.lezu.app',\n dest: './src/i18n',\n format: 'json',\n environment: 'production',\n flatten: false,\n namespace: false,\n includeEmpty: false,\n watch: false,\n watchInterval: 5000\n }\n\n // 2. Load from config file (only JSON files to avoid JS module complexity)\n const configFiles = ['.lezurc', '.lezurc.json', 'lezu.config.json']\n for (const file of configFiles) {\n const configPath = resolve(process.cwd(), file)\n if (existsSync(configPath)) {\n try {\n // JSON config files only\n const content = readFileSync(configPath, 'utf-8')\n const fileConfig = JSON.parse(content)\n config = { ...config, ...fileConfig }\n // Don't log in production to keep output clean\n break\n } catch (error) {\n console.warn(`[Warning] Failed to load config from ${file}:`, error)\n }\n }\n }\n\n // 3. Load from environment variables\n if (process.env.LEZU_PROJECT_ID) {\n config.projectId = process.env.LEZU_PROJECT_ID\n }\n if (process.env.LEZU_API_KEY) {\n config.apiKey = process.env.LEZU_API_KEY\n }\n if (process.env.LEZU_API_URL) {\n config.apiUrl = process.env.LEZU_API_URL\n }\n if (process.env.LEZU_DEST) {\n config.dest = process.env.LEZU_DEST\n }\n if (process.env.LEZU_FORMAT) {\n config.format = process.env.LEZU_FORMAT as any\n }\n if (process.env.LEZU_ENVIRONMENT) {\n config.environment = process.env.LEZU_ENVIRONMENT\n }\n\n // 4. Apply CLI options (highest priority)\n config = { ...config, ...options }\n\n // 5. Validate and return\n try {\n return ConfigSchema.parse(config)\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Invalid configuration: ${error.message}`)\n }\n throw error\n }\n}\n\nexport function validateConfig(config: Config): string[] {\n const errors: string[] = []\n\n if (!config.projectId) {\n errors.push('Project ID is required (use --project, LEZU_PROJECT_ID env var, or projectId in config file)')\n }\n\n if (!config.apiKey) {\n errors.push('API Key is required (use --api-key, LEZU_API_KEY env var, or apiKey in config file)')\n }\n\n return errors\n}","import { z } from 'zod'\n\nexport const ConfigSchema = z.object({\n projectId: z.string().optional(),\n apiKey: z.string().optional(),\n apiUrl: z.string().default('https://api.lezu.app'),\n dest: z.string().default('./src/i18n'),\n format: z.enum(['json', 'js', 'ts', 'yaml', 'po']).default('json'),\n languages: z.array(z.string()).optional(),\n release: z.string().optional(),\n environment: z.string().default('production'),\n flatten: z.boolean().default(false),\n namespace: z.boolean().default(false),\n includeEmpty: z.boolean().default(false),\n watch: z.boolean().default(false),\n watchInterval: z.number().default(5000),\n debug: z.boolean().default(false)\n})\n\nexport type Config = z.infer<typeof ConfigSchema>\n\nexport interface TranslationBundle {\n [key: string]: string | TranslationBundle\n}\n\nexport interface ApiResponse {\n translations: Record<string, any>\n meta?: {\n version?: string\n timestamp?: string\n languages?: string[]\n }\n}\n\nexport interface ReleaseResponse {\n releases: Array<{\n id: string\n version: string\n name?: string\n created_at: string\n }>\n}"],"mappings":"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","names":[]}