Skip to content

Commit

Permalink
Support mjs and ts config
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusab committed Dec 27, 2024
1 parent 96de9c3 commit 118d514
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { defineConfig } from "languine";

export default defineConfig({
version: "0.6.7",
export default {
version: "0.6.8",
locale: {
source: "en",
targets: ["es"],
Expand All @@ -15,4 +13,4 @@ export default defineConfig({
provider: "openai",
model: "gpt-4-turbo",
},
});
};
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "languine",
"version": "0.6.7",
"version": "0.6.8",
"type": "module",
"bin": "dist/index.js",
"main": "dist/config.js",
Expand Down
49 changes: 26 additions & 23 deletions packages/cli/src/commands/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import chalk from "chalk";
import { installDependencies } from "../install.js";
import { providers } from "../providers.js";
import type { PresetOptions, Provider } from "../types.js";
import { configPath } from "../utils.js";
import { configFile, generateConfig } from "../utils.js";

async function createDirectoryOrFile(filePath: string, isDirectory = false) {
try {
Expand Down Expand Up @@ -78,6 +78,19 @@ export async function init(preset?: string) {

intro("Let's set up your i18n configuration");

const configType = (await select({
message: "What type of config file would you like to use?",
options: [
{ value: "ts", label: "TypeScript", hint: "recommended" },
{ value: "mjs", label: "JavaScript" },
],
})) as "ts" | "mjs";

// Install dependencies only if we're using TypeScript for types in config
if (configType === "ts") {
await installDependencies();
}

const sourceLanguage = (await select({
message: "What is your source language?",
options: [
Expand Down Expand Up @@ -169,27 +182,16 @@ export async function init(preset?: string) {
message: "Which model should be used for translations?",
options: models,
})) as string;
const configContent = `import { defineConfig } from "languine";
export default defineConfig({
version: "${require("../../package.json").version}",
locale: {
source: "${sourceLanguage}",
targets: ${JSON.stringify(targetLanguages.split(",").map((l) => l.trim()))},
},
files: {
${fileFormat.includes("-") ? `"${fileFormat}"` : fileFormat}: {
include: ${JSON.stringify(filesPatterns)},
},
},
llm: {
provider: "${provider}",
model: "${model}",
},
})`;

// Install dependencies
await installDependencies();
const configContent = generateConfig({
version: require("../../package.json").version,
sourceLanguage,
targetLanguages: targetLanguages.split(",").map((l) => l.trim()),
fileFormat,
filesPatterns,
provider,
model,
configType,
});

try {
const targetLangs = [
Expand Down Expand Up @@ -217,7 +219,8 @@ export default defineConfig({
}

// Write config file
await fs.writeFile(configPath, configContent);
const { path: configPath } = await configFile(configType);
await fs.writeFile(configPath, configContent, "utf-8");
outro(
"Configuration file and language files/directories created successfully!",
);
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/src/commands/instructions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from "node:fs/promises";
import { intro, outro, text } from "@clack/prompts";
import chalk from "chalk";
import { configPath, getConfig } from "../utils.js";
import { configFile, getConfig } from "../utils.js";

export async function instructions() {
intro("Let's customize your translation prompt");
Expand All @@ -22,6 +22,7 @@ export async function instructions() {
config.instructions = customInstructions as string;

// Write updated config
const { path: configPath } = await configFile();
await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");

outro(chalk.green("Translation prompt updated successfully!"));
Expand Down
16 changes: 10 additions & 6 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node

import "./envs.js";
import { select } from "@clack/prompts";
import { isCancel, select } from "@clack/prompts";
import chalk from "chalk";
import dedent from "dedent";
import { clean } from "./commands/clean.js";
Expand Down Expand Up @@ -46,22 +46,26 @@ const command =
],
}));

if (isCancel(command)) {
process.exit(0);
}

const targetLocale = process.argv[3];
const preset = process.argv.includes("--preset")
? process.argv[process.argv.indexOf("--preset") + 1]
: undefined;
const force = process.argv.includes("--force") || process.argv.includes("-f");

if (command === "init") {
init(preset);
await init(preset);
} else if (command === "translate") {
translate(targetLocale, force);
await translate(targetLocale, force);
} else if (command === "instructions") {
instructions();
await instructions();
} else if (command === "diff") {
diff();
await diff();
} else if (command === "clean") {
clean();
await clean();
} else if (command === "available") {
console.log(dedent`
${chalk.cyan("init")} Initialize a new Languine configuration
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ export async function installDependencies() {
const s = spinner();

try {
s.start("Installing dependencies...");
s.start("Installing Languine as a dev dependency...");

const pm = await findPreferredPM();

await execAsync(`${pm?.name} install languine -D`);

s.stop("Dependencies installed successfully");
s.stop("Languine installed successfully");
} catch (error) {
s.stop("Failed to install dependencies");
s.stop("Failed to install Languine");
throw error;
}
}
91 changes: 75 additions & 16 deletions packages/cli/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import type { Jiti } from "jiti";
import preferredPM from "preferred-pm";
import type { Config } from "./types.js";

const CONFIG_NAME = "languine.config";

export async function getApiKey(name: string, key: string) {
if (key in process.env) {
return process.env[key];
Expand Down Expand Up @@ -62,35 +64,92 @@ export async function getApiKey(name: string, key: string) {
})();
}

export const configPath = path.join(process.cwd(), "languine.config.ts");
const name = "languine.config";
export function generateConfig({
version,
sourceLanguage,
targetLanguages,
fileFormat,
filesPatterns,
provider,
model,
configType,
}: {
version: string;
sourceLanguage: string;
targetLanguages: string[];
fileFormat: string;
filesPatterns: string[];
provider: string;
model: string;
configType: "ts" | "mjs";
}) {
const formatKey = fileFormat.includes("-") ? `"${fileFormat}"` : fileFormat;

const configBody = `{
version: "${version}",
locale: {
source: "${sourceLanguage}",
targets: [${targetLanguages.map((l) => `"${l}"`).join(", ")}],
},
files: {
${formatKey}: {
include: [${filesPatterns.map((p) => `"${p}"`).join(", ")}],
}
},
llm: {
provider: "${provider}",
model: "${model}",
}
}`;

let jiti: Jiti | undefined;
if (configType === "mjs") {
return `export default ${configBody}`;
}

export async function getConfig(): Promise<Config> {
let config: Config;
let target: string | undefined;
return `import { defineConfig } from "languine";
export default defineConfig(${configBody})`;
}

export async function configFile(configType?: "ts" | "mjs") {
const files = await fs.readdir(process.cwd());
const configFile = files.find(
(file: string) =>
file.startsWith(`${CONFIG_NAME}.`) &&
(file.endsWith(".ts") || file.endsWith(".mjs")),
);

// If configType is specified, use that
// Otherwise try to detect from existing file, falling back to ts
const format = configType || (configFile?.endsWith(".mjs") ? "mjs" : "ts");
const filePath = path.join(
process.cwd(),
configFile || `${CONFIG_NAME}.${format}`,
);

return {
path: filePath,
format,
};
}

for (const file of files) {
if (file.startsWith(`${name}.`)) {
target = path.resolve(file);
break;
}
}
let jiti: Jiti | undefined;

export async function getConfig(): Promise<Config> {
const { path: filePath, format } = await configFile();

if (!target) {
if (!filePath) {
outro(
chalk.red(
"Could not find languine.config.ts. Run 'languine init' first.",
`Could not find ${CONFIG_NAME}.${format}. Run 'languine init' first.`,
),
);

process.exit(1);
}

try {
const configModule = await import(pathToFileURL(target).href);
const configModule = await import(pathToFileURL(filePath).href);
return configModule.default;
} catch (error) {
const { createJiti } = await import("jiti");
Expand All @@ -105,7 +164,7 @@ export async function getConfig(): Promise<Config> {
});

return await jiti
.import(target)
.import(filePath)
.then((mod) => (mod as unknown as { default: Config }).default);
}
}
Expand Down

0 comments on commit 118d514

Please sign in to comment.