@lingo.dev/compiler 0.1.12 → 0.2.0
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/build/react/server/ServerLingoProvider.d.cts +2 -2
- package/build/react/server/ServerLingoProvider.d.mts +2 -2
- package/build/react/shared/LingoProvider.d.mts +2 -2
- package/build/react/shared/LocaleSwitcher.d.cts +2 -2
- package/build/react/shared/LocaleSwitcher.d.mts +2 -2
- package/build/translators/lingo/model-factory.cjs +13 -2
- package/build/translators/lingo/model-factory.mjs +13 -2
- package/build/translators/lingo/model-factory.mjs.map +1 -1
- package/build/utils/observability.cjs +9 -9
- package/build/utils/observability.mjs +9 -9
- package/build/utils/observability.mjs.map +1 -1
- package/build/utils/org-id.cjs +72 -0
- package/build/utils/org-id.mjs +72 -0
- package/build/utils/org-id.mjs.map +1 -0
- package/package.json +3 -2
- package/build/utils/repository-id.cjs +0 -64
- package/build/utils/repository-id.mjs +0 -64
- package/build/utils/repository-id.mjs.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { LingoProviderProps } from "../shared/LingoProvider.cjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime2 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/react/server/ServerLingoProvider.d.ts
|
|
5
5
|
declare function LingoProvider({
|
|
6
6
|
initialLocale,
|
|
7
7
|
initialTranslations,
|
|
8
8
|
...rest
|
|
9
|
-
}: LingoProviderProps): Promise<
|
|
9
|
+
}: LingoProviderProps): Promise<react_jsx_runtime2.JSX.Element>;
|
|
10
10
|
//#endregion
|
|
11
11
|
export { LingoProvider };
|
|
12
12
|
//# sourceMappingURL=ServerLingoProvider.d.cts.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { LingoProviderProps } from "../shared/LingoProvider.mjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime1 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/react/server/ServerLingoProvider.d.ts
|
|
5
5
|
declare function LingoProvider({
|
|
6
6
|
initialLocale,
|
|
7
7
|
initialTranslations,
|
|
8
8
|
...rest
|
|
9
|
-
}: LingoProviderProps): Promise<
|
|
9
|
+
}: LingoProviderProps): Promise<react_jsx_runtime1.JSX.Element>;
|
|
10
10
|
//#endregion
|
|
11
11
|
export { LingoProvider };
|
|
12
12
|
//# sourceMappingURL=ServerLingoProvider.d.mts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PropsWithChildren } from "react";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime3 from "react/jsx-runtime";
|
|
3
3
|
import { LocaleCode } from "lingo.dev/spec";
|
|
4
4
|
|
|
5
5
|
//#region src/react/shared/LingoProvider.d.ts
|
|
@@ -70,7 +70,7 @@ declare function LingoProvider__Dev({
|
|
|
70
70
|
router,
|
|
71
71
|
devWidget,
|
|
72
72
|
children
|
|
73
|
-
}: LingoProviderProps):
|
|
73
|
+
}: LingoProviderProps): react_jsx_runtime3.JSX.Element;
|
|
74
74
|
//#endregion
|
|
75
75
|
export { LingoProvider, LingoProviderProps };
|
|
76
76
|
//# sourceMappingURL=LingoProvider.d.mts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LocaleCode } from "lingo.dev/spec";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime3 from "react/jsx-runtime";
|
|
3
3
|
import { CSSProperties } from "react";
|
|
4
4
|
|
|
5
5
|
//#region src/react/shared/LocaleSwitcher.d.ts
|
|
@@ -65,7 +65,7 @@ declare function LocaleSwitcher({
|
|
|
65
65
|
style,
|
|
66
66
|
className,
|
|
67
67
|
showLoadingState
|
|
68
|
-
}: LocaleSwitcherProps):
|
|
68
|
+
}: LocaleSwitcherProps): react_jsx_runtime3.JSX.Element;
|
|
69
69
|
//#endregion
|
|
70
70
|
export { LocaleSwitcher };
|
|
71
71
|
//# sourceMappingURL=LocaleSwitcher.d.cts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CSSProperties } from "react";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime2 from "react/jsx-runtime";
|
|
3
3
|
import { LocaleCode } from "lingo.dev/spec";
|
|
4
4
|
|
|
5
5
|
//#region src/react/shared/LocaleSwitcher.d.ts
|
|
@@ -65,7 +65,7 @@ declare function LocaleSwitcher({
|
|
|
65
65
|
style,
|
|
66
66
|
className,
|
|
67
67
|
showLoadingState
|
|
68
|
-
}: LocaleSwitcherProps):
|
|
68
|
+
}: LocaleSwitcherProps): react_jsx_runtime2.JSX.Element;
|
|
69
69
|
//#endregion
|
|
70
70
|
export { LocaleSwitcher };
|
|
71
71
|
//# sourceMappingURL=LocaleSwitcher.d.mts.map
|
|
@@ -7,6 +7,7 @@ let _ai_sdk_google = require("@ai-sdk/google");
|
|
|
7
7
|
let _openrouter_ai_sdk_provider = require("@openrouter/ai-sdk-provider");
|
|
8
8
|
let ai_sdk_ollama = require("ai-sdk-ollama");
|
|
9
9
|
let _ai_sdk_mistral = require("@ai-sdk/mistral");
|
|
10
|
+
let _ai_sdk_openai = require("@ai-sdk/openai");
|
|
10
11
|
let dotenv = require("dotenv");
|
|
11
12
|
dotenv = require_rolldown_runtime.__toESM(dotenv);
|
|
12
13
|
|
|
@@ -105,7 +106,10 @@ function getLocaleModel(localeModels, sourceLocale, targetLocale) {
|
|
|
105
106
|
* @throws Error if format is invalid
|
|
106
107
|
*/
|
|
107
108
|
function parseModelString(modelString) {
|
|
108
|
-
const
|
|
109
|
+
const colonIndex = modelString.indexOf(":");
|
|
110
|
+
if (colonIndex === -1) return;
|
|
111
|
+
const provider = modelString.substring(0, colonIndex);
|
|
112
|
+
const name = modelString.substring(colonIndex + 1);
|
|
109
113
|
if (!provider || !name) return;
|
|
110
114
|
return {
|
|
111
115
|
provider,
|
|
@@ -156,10 +160,17 @@ function createAiModel(model, validatedKeys) {
|
|
|
156
160
|
const providerConfig = providerDetails[model.provider];
|
|
157
161
|
if (!providerConfig) throw new Error(`⚠️ Provider "${model.provider}" is not supported. Supported providers: ${Object.keys(providerDetails).join(", ")}`);
|
|
158
162
|
const apiKey = providerConfig.apiKeyEnvVar ? validatedKeys[model.provider] : void 0;
|
|
159
|
-
if (providerConfig.apiKeyEnvVar && !apiKey) throw new Error(`⚠️ ${providerConfig.name} API key not found. Please set ${providerConfig.apiKeyEnvVar} environment variable.\n\nThis should not happen if
|
|
163
|
+
if (providerConfig.apiKeyEnvVar && !apiKey) throw new Error(`⚠️ ${providerConfig.name} API key not found. Please set ${providerConfig.apiKeyEnvVar} environment variable.\n\nThis should not happen if validateAndGetApiKeys() was called. Please restart the service.`);
|
|
160
164
|
switch (model.provider) {
|
|
161
165
|
case "groq": return (0, _ai_sdk_groq.createGroq)({ apiKey })(model.name);
|
|
162
166
|
case "google": return (0, _ai_sdk_google.createGoogleGenerativeAI)({ apiKey })(model.name);
|
|
167
|
+
case "openai": {
|
|
168
|
+
const baseURL = getKeyFromEnv("OPENAI_BASE_URL");
|
|
169
|
+
return (0, _ai_sdk_openai.createOpenAI)({
|
|
170
|
+
apiKey,
|
|
171
|
+
...baseURL && { baseURL }
|
|
172
|
+
}).chat(model.name);
|
|
173
|
+
}
|
|
163
174
|
case "openrouter": return (0, _openrouter_ai_sdk_provider.createOpenRouter)({ apiKey })(model.name);
|
|
164
175
|
case "ollama": return (0, ai_sdk_ollama.ollama)(model.name);
|
|
165
176
|
case "mistral": return (0, _ai_sdk_mistral.createMistral)({ apiKey })(model.name);
|
|
@@ -5,6 +5,7 @@ import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
|
5
5
|
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
|
|
6
6
|
import { ollama } from "ai-sdk-ollama";
|
|
7
7
|
import { createMistral } from "@ai-sdk/mistral";
|
|
8
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
8
9
|
import * as dotenv from "dotenv";
|
|
9
10
|
|
|
10
11
|
//#region src/translators/lingo/model-factory.ts
|
|
@@ -102,7 +103,10 @@ function getLocaleModel(localeModels, sourceLocale, targetLocale) {
|
|
|
102
103
|
* @throws Error if format is invalid
|
|
103
104
|
*/
|
|
104
105
|
function parseModelString(modelString) {
|
|
105
|
-
const
|
|
106
|
+
const colonIndex = modelString.indexOf(":");
|
|
107
|
+
if (colonIndex === -1) return;
|
|
108
|
+
const provider = modelString.substring(0, colonIndex);
|
|
109
|
+
const name = modelString.substring(colonIndex + 1);
|
|
106
110
|
if (!provider || !name) return;
|
|
107
111
|
return {
|
|
108
112
|
provider,
|
|
@@ -153,10 +157,17 @@ function createAiModel(model, validatedKeys) {
|
|
|
153
157
|
const providerConfig = providerDetails[model.provider];
|
|
154
158
|
if (!providerConfig) throw new Error(`⚠️ Provider "${model.provider}" is not supported. Supported providers: ${Object.keys(providerDetails).join(", ")}`);
|
|
155
159
|
const apiKey = providerConfig.apiKeyEnvVar ? validatedKeys[model.provider] : void 0;
|
|
156
|
-
if (providerConfig.apiKeyEnvVar && !apiKey) throw new Error(`⚠️ ${providerConfig.name} API key not found. Please set ${providerConfig.apiKeyEnvVar} environment variable.\n\nThis should not happen if
|
|
160
|
+
if (providerConfig.apiKeyEnvVar && !apiKey) throw new Error(`⚠️ ${providerConfig.name} API key not found. Please set ${providerConfig.apiKeyEnvVar} environment variable.\n\nThis should not happen if validateAndGetApiKeys() was called. Please restart the service.`);
|
|
157
161
|
switch (model.provider) {
|
|
158
162
|
case "groq": return createGroq({ apiKey })(model.name);
|
|
159
163
|
case "google": return createGoogleGenerativeAI({ apiKey })(model.name);
|
|
164
|
+
case "openai": {
|
|
165
|
+
const baseURL = getKeyFromEnv("OPENAI_BASE_URL");
|
|
166
|
+
return createOpenAI({
|
|
167
|
+
apiKey,
|
|
168
|
+
...baseURL && { baseURL }
|
|
169
|
+
}).chat(model.name);
|
|
170
|
+
}
|
|
160
171
|
case "openrouter": return createOpenRouter({ apiKey })(model.name);
|
|
161
172
|
case "ollama": return ollama(model.name);
|
|
162
173
|
case "mistral": return createMistral({ apiKey })(model.name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-factory.mjs","names":["path","providerDetails: Record<string, ProviderConfig>","keys: ValidatedApiKeys","missingProviders: string[]","providersToValidate: string[]"],"sources":["../../../src/translators/lingo/model-factory.ts"],"sourcesContent":["/**\n * Shared utilities for creating AI model instances\n */\n\nimport { createGroq } from \"@ai-sdk/groq\";\nimport { createGoogleGenerativeAI } from \"@ai-sdk/google\";\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\nimport { ollama } from \"ai-sdk-ollama\";\nimport { createMistral } from \"@ai-sdk/mistral\";\nimport type { LanguageModel } from \"ai\";\nimport * as dotenv from \"dotenv\";\nimport * as path from \"path\";\nimport { formatNoApiKeysError } from \"./provider-details\";\n\nexport type LocaleModel = {\n provider: string;\n name: string;\n};\n\nexport function getKeyFromEnv(envVarName: string): string | undefined {\n if (process.env[envVarName]) {\n return process.env[envVarName];\n }\n\n const projectRoot = process.cwd();\n\n const result = dotenv.config({\n path: [\n path.resolve(projectRoot, \".env\"),\n path.resolve(projectRoot, \".env.local\"),\n path.resolve(projectRoot, \".env.development\"),\n ],\n });\n\n return result?.parsed?.[envVarName];\n}\n\n/**\n * Pre-validated API keys for all providers\n * Keys are fetched and validated once at initialization\n */\nexport type ValidatedApiKeys = Record<string, string>;\n\n/**\n * Provider configuration including env var names and requirements\n */\ntype ProviderConfig = {\n name: string; // Display name (e.g., \"Groq\", \"Google\")\n apiKeyEnvVar?: string; // Environment variable name (e.g., \"GROQ_API_KEY\")\n apiKeyConfigKey?: string; // Config key if applicable (e.g., \"llm.groqApiKey\")\n getKeyLink: string; // Link to get API key\n docsLink: string; // Link to API docs for troubleshooting\n};\n\nexport const providerDetails: Record<string, ProviderConfig> = {\n groq: {\n name: \"Groq\",\n apiKeyEnvVar: \"GROQ_API_KEY\",\n apiKeyConfigKey: \"llm.groqApiKey\",\n getKeyLink: \"https://groq.com\",\n docsLink: \"https://console.groq.com/docs/errors\",\n },\n google: {\n name: \"Google\",\n apiKeyEnvVar: \"GOOGLE_API_KEY\",\n apiKeyConfigKey: \"llm.googleApiKey\",\n getKeyLink: \"https://ai.google.dev/\",\n docsLink: \"https://ai.google.dev/gemini-api/docs/troubleshooting\",\n },\n openai: {\n name: \"OpenAI\",\n apiKeyEnvVar: \"OPENAI_API_KEY\",\n apiKeyConfigKey: \"llm.openaiApiKey\",\n getKeyLink: \"https://platform.openai.com/account/api-keys\",\n docsLink: \"https://platform.openai.com/docs\",\n },\n anthropic: {\n name: \"Anthropic\",\n apiKeyEnvVar: \"ANTHROPIC_API_KEY\",\n apiKeyConfigKey: \"llm.anthropicApiKey\",\n getKeyLink: \"https://console.anthropic.com/get-api-key\",\n docsLink: \"https://console.anthropic.com/docs\",\n },\n openrouter: {\n name: \"OpenRouter\",\n apiKeyEnvVar: \"OPENROUTER_API_KEY\",\n apiKeyConfigKey: \"llm.openrouterApiKey\",\n getKeyLink: \"https://openrouter.ai\",\n docsLink: \"https://openrouter.ai/docs\",\n },\n ollama: {\n name: \"Ollama\",\n apiKeyEnvVar: undefined, // Ollama doesn't require an API key\n apiKeyConfigKey: undefined, // Ollama doesn't require an API key\n getKeyLink: \"https://ollama.com/download\",\n docsLink: \"https://github.com/ollama/ollama/tree/main/docs\",\n },\n mistral: {\n name: \"Mistral\",\n apiKeyEnvVar: \"MISTRAL_API_KEY\",\n apiKeyConfigKey: \"llm.mistralApiKey\",\n getKeyLink: \"https://console.mistral.ai\",\n docsLink: \"https://docs.mistral.ai\",\n },\n \"lingo.dev\": {\n name: \"Lingo.dev\",\n apiKeyEnvVar: \"LINGODOTDEV_API_KEY\",\n apiKeyConfigKey: \"auth.apiKey\",\n getKeyLink: \"https://lingo.dev\",\n docsLink: \"https://lingo.dev/docs\",\n },\n};\n\n/**\n * Get provider and model for a specific locale pair\n */\nexport function getLocaleModel(\n localeModels: Record<string, string>,\n sourceLocale: string,\n targetLocale: string,\n): LocaleModel | undefined {\n const localeKeys = [\n `${sourceLocale}:${targetLocale}`,\n `*:${targetLocale}`,\n `${sourceLocale}:*`,\n \"*:*\",\n ];\n\n const modelKey = localeKeys.find((key) => key in localeModels);\n if (!modelKey) {\n return undefined;\n }\n\n const value = localeModels[modelKey];\n if (!value) {\n return undefined;\n }\n\n return parseModelString(value);\n}\n\n/**\n * Parse provider and model from model string\n * Format: \"provider:model\" (e.g., \"groq:llama3-8b-8192\")\n *\n * @param modelString Model string to parse\n * @returns Object with provider and model\n * @throws Error if format is invalid\n */\nexport function parseModelString(modelString: string): LocaleModel | undefined {\n // Split on first colon only\n const [provider, name] = modelString.split(\":\", 2);\n\n if (!provider || !name) {\n return undefined;\n }\n\n return { provider, name };\n}\n\n/**\n * Validate and fetch all necessary API keys for the given configuration\n * This should be called once at initialization time\n *\n * @param config Model configuration (\"lingo.dev\" or locale-pair mapping)\n * @returns Validated API keys (provider ID -> API key)\n * @throws Error if required keys are missing\n */\nexport function validateAndGetApiKeys(\n config: \"lingo.dev\" | Record<string, string>,\n): ValidatedApiKeys {\n const keys: ValidatedApiKeys = {};\n const missingProviders: string[] = [];\n\n // Determine which providers are configured\n let providersToValidate: string[];\n\n if (config === \"lingo.dev\") {\n // Only need lingo.dev provider\n providersToValidate = [\"lingo.dev\"];\n } else {\n // Extract unique providers from model strings\n const providerSet = new Set<string>();\n Object.values(config).forEach((modelString) => {\n const model = parseModelString(modelString);\n if (model) {\n providerSet.add(model.provider);\n }\n });\n providersToValidate = Array.from(providerSet);\n }\n\n // Validate and fetch keys for each provider\n for (const provider of providersToValidate) {\n const providerConfig = providerDetails[provider];\n\n if (!providerConfig) {\n throw new Error(\n `⚠️ Unknown provider \"${provider}\". Supported providers: ${Object.keys(providerDetails).join(\", \")}`,\n );\n }\n\n // Skip providers that don't require keys (like Ollama)\n if (!providerConfig.apiKeyEnvVar) {\n continue;\n }\n\n const key = getKeyFromEnv(providerConfig.apiKeyEnvVar);\n if (key) {\n keys[provider] = key;\n } else {\n missingProviders.push(provider);\n }\n }\n\n // If any keys are missing, throw with detailed error\n if (missingProviders.length > 0) {\n throw new Error(formatNoApiKeysError(missingProviders));\n }\n\n return keys;\n}\n\n/**\n * Create AI model instance from provider and model ID\n *\n * @param model Provider name (groq, google, openrouter, ollama, mistral) and model identifier\n * @param validatedKeys Pre-validated API keys from validateAndFetchApiKeys()\n * @returns LanguageModel instance\n * @throws Error if provider is not supported or API key is missing\n */\nexport function createAiModel(\n model: LocaleModel,\n validatedKeys: ValidatedApiKeys,\n): LanguageModel {\n const providerConfig = providerDetails[model.provider];\n\n if (!providerConfig) {\n throw new Error(\n `⚠️ Provider \"${model.provider}\" is not supported. Supported providers: ${Object.keys(providerDetails).join(\", \")}`,\n );\n }\n\n // Get API key if required\n const apiKey = providerConfig.apiKeyEnvVar\n ? validatedKeys[model.provider]\n : undefined;\n\n // TODO (AleksandrSl 25/12/2025): Do we really need to make a second check? Maybe creation should be combined with validation.\n // Verify key is present for providers that require it\n if (providerConfig.apiKeyEnvVar && !apiKey) {\n throw new Error(\n `⚠️ ${providerConfig.name} API key not found. Please set ${providerConfig.apiKeyEnvVar} environment variable.\\n\\n` +\n `This should not happen if validateAndFetchApiKeys() was called. Please restart the service.`,\n );\n }\n\n // Create the appropriate model instance\n switch (model.provider) {\n case \"groq\":\n return createGroq({ apiKey: apiKey! })(model.name);\n\n case \"google\":\n return createGoogleGenerativeAI({ apiKey: apiKey! })(model.name);\n\n case \"openrouter\":\n return createOpenRouter({ apiKey: apiKey! })(model.name);\n\n case \"ollama\":\n return ollama(model.name);\n\n case \"mistral\":\n return createMistral({ apiKey: apiKey! })(model.name);\n\n default:\n // This should be unreachable due to check above\n throw new Error(`⚠️ Provider \"${model.provider}\" is not implemented`);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"model-factory.mjs","names":["path","providerDetails: Record<string, ProviderConfig>","keys: ValidatedApiKeys","missingProviders: string[]","providersToValidate: string[]"],"sources":["../../../src/translators/lingo/model-factory.ts"],"sourcesContent":["/**\n * Shared utilities for creating AI model instances\n */\n\nimport { createGroq } from \"@ai-sdk/groq\";\nimport { createGoogleGenerativeAI } from \"@ai-sdk/google\";\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\nimport { ollama } from \"ai-sdk-ollama\";\nimport { createMistral } from \"@ai-sdk/mistral\";\nimport { createOpenAI } from \"@ai-sdk/openai\";\nimport type { LanguageModel } from \"ai\";\nimport * as dotenv from \"dotenv\";\nimport * as path from \"path\";\nimport { formatNoApiKeysError } from \"./provider-details\";\n\nexport type LocaleModel = {\n provider: string;\n name: string;\n};\n\nexport function getKeyFromEnv(envVarName: string): string | undefined {\n if (process.env[envVarName]) {\n return process.env[envVarName];\n }\n\n const projectRoot = process.cwd();\n\n const result = dotenv.config({\n path: [\n path.resolve(projectRoot, \".env\"),\n path.resolve(projectRoot, \".env.local\"),\n path.resolve(projectRoot, \".env.development\"),\n ],\n });\n\n return result?.parsed?.[envVarName];\n}\n\n/**\n * Pre-validated API keys for all providers\n * Keys are fetched and validated once at initialization\n */\nexport type ValidatedApiKeys = Record<string, string>;\n\n/**\n * Provider configuration including env var names and requirements\n */\ntype ProviderConfig = {\n name: string; // Display name (e.g., \"Groq\", \"Google\")\n apiKeyEnvVar?: string; // Environment variable name (e.g., \"GROQ_API_KEY\")\n apiKeyConfigKey?: string; // Config key if applicable (e.g., \"llm.groqApiKey\")\n getKeyLink: string; // Link to get API key\n docsLink: string; // Link to API docs for troubleshooting\n};\n\nexport const providerDetails: Record<string, ProviderConfig> = {\n groq: {\n name: \"Groq\",\n apiKeyEnvVar: \"GROQ_API_KEY\",\n apiKeyConfigKey: \"llm.groqApiKey\",\n getKeyLink: \"https://groq.com\",\n docsLink: \"https://console.groq.com/docs/errors\",\n },\n google: {\n name: \"Google\",\n apiKeyEnvVar: \"GOOGLE_API_KEY\",\n apiKeyConfigKey: \"llm.googleApiKey\",\n getKeyLink: \"https://ai.google.dev/\",\n docsLink: \"https://ai.google.dev/gemini-api/docs/troubleshooting\",\n },\n openai: {\n name: \"OpenAI\",\n apiKeyEnvVar: \"OPENAI_API_KEY\",\n apiKeyConfigKey: \"llm.openaiApiKey\",\n getKeyLink: \"https://platform.openai.com/account/api-keys\",\n docsLink: \"https://platform.openai.com/docs\",\n },\n anthropic: {\n name: \"Anthropic\",\n apiKeyEnvVar: \"ANTHROPIC_API_KEY\",\n apiKeyConfigKey: \"llm.anthropicApiKey\",\n getKeyLink: \"https://console.anthropic.com/get-api-key\",\n docsLink: \"https://console.anthropic.com/docs\",\n },\n openrouter: {\n name: \"OpenRouter\",\n apiKeyEnvVar: \"OPENROUTER_API_KEY\",\n apiKeyConfigKey: \"llm.openrouterApiKey\",\n getKeyLink: \"https://openrouter.ai\",\n docsLink: \"https://openrouter.ai/docs\",\n },\n ollama: {\n name: \"Ollama\",\n apiKeyEnvVar: undefined, // Ollama doesn't require an API key\n apiKeyConfigKey: undefined, // Ollama doesn't require an API key\n getKeyLink: \"https://ollama.com/download\",\n docsLink: \"https://github.com/ollama/ollama/tree/main/docs\",\n },\n mistral: {\n name: \"Mistral\",\n apiKeyEnvVar: \"MISTRAL_API_KEY\",\n apiKeyConfigKey: \"llm.mistralApiKey\",\n getKeyLink: \"https://console.mistral.ai\",\n docsLink: \"https://docs.mistral.ai\",\n },\n \"lingo.dev\": {\n name: \"Lingo.dev\",\n apiKeyEnvVar: \"LINGODOTDEV_API_KEY\",\n apiKeyConfigKey: \"auth.apiKey\",\n getKeyLink: \"https://lingo.dev\",\n docsLink: \"https://lingo.dev/docs\",\n },\n};\n\n/**\n * Get provider and model for a specific locale pair\n */\nexport function getLocaleModel(\n localeModels: Record<string, string>,\n sourceLocale: string,\n targetLocale: string,\n): LocaleModel | undefined {\n const localeKeys = [\n `${sourceLocale}:${targetLocale}`,\n `*:${targetLocale}`,\n `${sourceLocale}:*`,\n \"*:*\",\n ];\n\n const modelKey = localeKeys.find((key) => key in localeModels);\n if (!modelKey) {\n return undefined;\n }\n\n const value = localeModels[modelKey];\n if (!value) {\n return undefined;\n }\n\n return parseModelString(value);\n}\n\n/**\n * Parse provider and model from model string\n * Format: \"provider:model\" (e.g., \"groq:llama3-8b-8192\")\n *\n * @param modelString Model string to parse\n * @returns Object with provider and model\n * @throws Error if format is invalid\n */\nexport function parseModelString(modelString: string): LocaleModel | undefined {\n // Split on first colon only to allow colons in model names\n const colonIndex = modelString.indexOf(\":\");\n if (colonIndex === -1) {\n return undefined;\n }\n\n const provider = modelString.substring(0, colonIndex);\n const name = modelString.substring(colonIndex + 1);\n\n if (!provider || !name) {\n return undefined;\n }\n\n return { provider, name };\n}\n\n/**\n * Validate and fetch all necessary API keys for the given configuration\n * This should be called once at initialization time\n *\n * @param config Model configuration (\"lingo.dev\" or locale-pair mapping)\n * @returns Validated API keys (provider ID -> API key)\n * @throws Error if required keys are missing\n */\nexport function validateAndGetApiKeys(\n config: \"lingo.dev\" | Record<string, string>,\n): ValidatedApiKeys {\n const keys: ValidatedApiKeys = {};\n const missingProviders: string[] = [];\n\n // Determine which providers are configured\n let providersToValidate: string[];\n\n if (config === \"lingo.dev\") {\n // Only need lingo.dev provider\n providersToValidate = [\"lingo.dev\"];\n } else {\n // Extract unique providers from model strings\n const providerSet = new Set<string>();\n Object.values(config).forEach((modelString) => {\n const model = parseModelString(modelString);\n if (model) {\n providerSet.add(model.provider);\n }\n });\n providersToValidate = Array.from(providerSet);\n }\n\n // Validate and fetch keys for each provider\n for (const provider of providersToValidate) {\n const providerConfig = providerDetails[provider];\n\n if (!providerConfig) {\n throw new Error(\n `⚠️ Unknown provider \"${provider}\". Supported providers: ${Object.keys(providerDetails).join(\", \")}`,\n );\n }\n\n // Skip providers that don't require keys (like Ollama)\n if (!providerConfig.apiKeyEnvVar) {\n continue;\n }\n\n const key = getKeyFromEnv(providerConfig.apiKeyEnvVar);\n if (key) {\n keys[provider] = key;\n } else {\n missingProviders.push(provider);\n }\n }\n\n // If any keys are missing, throw with detailed error\n if (missingProviders.length > 0) {\n throw new Error(formatNoApiKeysError(missingProviders));\n }\n\n return keys;\n}\n\n/**\n * Create AI model instance from provider and model ID\n *\n * @param model Provider name (groq, google, openrouter, ollama, mistral) and model identifier\n * @param validatedKeys Pre-validated API keys from validateAndFetchApiKeys()\n * @returns LanguageModel instance\n * @throws Error if provider is not supported or API key is missing\n */\nexport function createAiModel(\n model: LocaleModel,\n validatedKeys: ValidatedApiKeys,\n): LanguageModel {\n const providerConfig = providerDetails[model.provider];\n\n if (!providerConfig) {\n throw new Error(\n `⚠️ Provider \"${model.provider}\" is not supported. Supported providers: ${Object.keys(providerDetails).join(\", \")}`,\n );\n }\n\n // Get API key if required\n const apiKey = providerConfig.apiKeyEnvVar\n ? validatedKeys[model.provider]\n : undefined;\n\n // TODO (AleksandrSl 25/12/2025): Do we really need to make a second check? Maybe creation should be combined with validation.\n // Verify key is present for providers that require it\n if (providerConfig.apiKeyEnvVar && !apiKey) {\n throw new Error(\n `⚠️ ${providerConfig.name} API key not found. Please set ${providerConfig.apiKeyEnvVar} environment variable.\\n\\n` +\n `This should not happen if validateAndGetApiKeys() was called. Please restart the service.`,\n );\n }\n\n // Create the appropriate model instance\n switch (model.provider) {\n case \"groq\":\n return createGroq({ apiKey: apiKey! })(model.name);\n\n case \"google\":\n return createGoogleGenerativeAI({ apiKey: apiKey! })(model.name);\n\n case \"openai\": {\n // Support custom base URL for OpenAI-compatible providers (e.g., Nebius)\n const baseURL = getKeyFromEnv(\"OPENAI_BASE_URL\");\n\n const provider = createOpenAI({\n apiKey: apiKey!,\n ...(baseURL && { baseURL }),\n });\n\n return provider.chat(model.name);\n }\n\n case \"openrouter\":\n return createOpenRouter({ apiKey: apiKey! })(model.name);\n\n case \"ollama\":\n return ollama(model.name);\n\n case \"mistral\":\n return createMistral({ apiKey: apiKey! })(model.name);\n\n default:\n // This should be unreachable due to check above\n throw new Error(`⚠️ Provider \"${model.provider}\" is not implemented`);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
2
|
const require_rc = require('./rc.cjs');
|
|
3
|
-
const
|
|
3
|
+
const require_org_id = require('./org-id.cjs');
|
|
4
4
|
const require_tracking_events = require('./tracking-events.cjs');
|
|
5
5
|
let node_machine_id = require("node-machine-id");
|
|
6
6
|
node_machine_id = require_rolldown_runtime.__toESM(node_machine_id);
|
|
@@ -26,7 +26,7 @@ async function trackEvent(event, properties) {
|
|
|
26
26
|
tracking_version: require_tracking_events.TRACKING_VERSION,
|
|
27
27
|
compiler_package: require_tracking_events.COMPILER_PACKAGE,
|
|
28
28
|
distinct_id_source: identityInfo.distinct_id_source,
|
|
29
|
-
|
|
29
|
+
org_id: identityInfo.org_id,
|
|
30
30
|
meta: {
|
|
31
31
|
version: process.env.npm_package_version,
|
|
32
32
|
isCi: process.env.CI === "true"
|
|
@@ -39,24 +39,24 @@ async function trackEvent(event, properties) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
async function getDistinctId() {
|
|
42
|
+
const orgId = require_org_id.getOrgId();
|
|
42
43
|
const email = await tryGetEmail();
|
|
43
44
|
if (email) return {
|
|
44
45
|
distinct_id: email,
|
|
45
46
|
distinct_id_source: "email",
|
|
46
|
-
|
|
47
|
+
org_id: orgId
|
|
47
48
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
project_id: repoId
|
|
49
|
+
if (orgId) return {
|
|
50
|
+
distinct_id: orgId,
|
|
51
|
+
distinct_id_source: "git_org",
|
|
52
|
+
org_id: orgId
|
|
53
53
|
};
|
|
54
54
|
const deviceId = `device-${await node_machine_id.machineId()}`;
|
|
55
55
|
if (process.env.DEBUG === "true") console.warn("[Tracking] Using device ID fallback. Consider using git repository for consistent tracking.");
|
|
56
56
|
return {
|
|
57
57
|
distinct_id: deviceId,
|
|
58
58
|
distinct_id_source: "device",
|
|
59
|
-
|
|
59
|
+
org_id: null
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
async function tryGetEmail() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getRc } from "./rc.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { getOrgId } from "./org-id.mjs";
|
|
3
3
|
import { COMPILER_PACKAGE, TRACKING_VERSION } from "./tracking-events.mjs";
|
|
4
4
|
import * as machineIdLib from "node-machine-id";
|
|
5
5
|
|
|
@@ -24,7 +24,7 @@ async function trackEvent(event, properties) {
|
|
|
24
24
|
tracking_version: TRACKING_VERSION,
|
|
25
25
|
compiler_package: COMPILER_PACKAGE,
|
|
26
26
|
distinct_id_source: identityInfo.distinct_id_source,
|
|
27
|
-
|
|
27
|
+
org_id: identityInfo.org_id,
|
|
28
28
|
meta: {
|
|
29
29
|
version: process.env.npm_package_version,
|
|
30
30
|
isCi: process.env.CI === "true"
|
|
@@ -37,24 +37,24 @@ async function trackEvent(event, properties) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
async function getDistinctId() {
|
|
40
|
+
const orgId = getOrgId();
|
|
40
41
|
const email = await tryGetEmail();
|
|
41
42
|
if (email) return {
|
|
42
43
|
distinct_id: email,
|
|
43
44
|
distinct_id_source: "email",
|
|
44
|
-
|
|
45
|
+
org_id: orgId
|
|
45
46
|
};
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
project_id: repoId
|
|
47
|
+
if (orgId) return {
|
|
48
|
+
distinct_id: orgId,
|
|
49
|
+
distinct_id_source: "git_org",
|
|
50
|
+
org_id: orgId
|
|
51
51
|
};
|
|
52
52
|
const deviceId = `device-${await machineIdLib.machineId()}`;
|
|
53
53
|
if (process.env.DEBUG === "true") console.warn("[Tracking] Using device ID fallback. Consider using git repository for consistent tracking.");
|
|
54
54
|
return {
|
|
55
55
|
distinct_id: deviceId,
|
|
56
56
|
distinct_id_source: "device",
|
|
57
|
-
|
|
57
|
+
org_id: null
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
async function tryGetEmail() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observability.mjs","names":[],"sources":["../../src/utils/observability.ts"],"sourcesContent":["import * as machineIdLib from \"node-machine-id\";\nimport { getRc } from \"./rc\";\nimport {
|
|
1
|
+
{"version":3,"file":"observability.mjs","names":[],"sources":["../../src/utils/observability.ts"],"sourcesContent":["import * as machineIdLib from \"node-machine-id\";\nimport { getRc } from \"./rc\";\nimport { getOrgId } from \"./org-id\";\nimport { TRACKING_VERSION, COMPILER_PACKAGE } from \"./tracking-events\";\n\nexport default async function trackEvent(\n event: string,\n properties?: Record<string, any>,\n) {\n if (process.env.DO_NOT_TRACK === \"1\") {\n return;\n }\n\n try {\n const identityInfo = await getDistinctId();\n\n if (process.env.DEBUG === \"true\") {\n console.log(\n `[Tracking] Event: ${event}, ID: ${identityInfo.distinct_id}, Source: ${identityInfo.distinct_id_source}`,\n );\n }\n\n const { PostHog } = await import(\"posthog-node\");\n const posthog = new PostHog(\n \"phc_eR0iSoQufBxNY36k0f0T15UvHJdTfHlh8rJcxsfhfXk\",\n {\n host: \"https://eu.i.posthog.com\",\n flushAt: 1,\n flushInterval: 0,\n },\n );\n\n await posthog.capture({\n distinctId: identityInfo.distinct_id,\n event,\n properties: {\n ...properties,\n isByokMode: properties?.models !== \"lingo.dev\",\n tracking_version: TRACKING_VERSION,\n compiler_package: COMPILER_PACKAGE,\n distinct_id_source: identityInfo.distinct_id_source,\n org_id: identityInfo.org_id,\n meta: {\n version: process.env.npm_package_version,\n isCi: process.env.CI === \"true\",\n },\n },\n });\n\n await posthog.shutdown();\n } catch (error) {\n if (process.env.DEBUG === \"true\") {\n console.error(\"[Tracking] Error:\", error);\n }\n }\n}\n\nasync function getDistinctId(): Promise<{\n distinct_id: string;\n distinct_id_source: string;\n org_id: string | null;\n}> {\n const orgId = getOrgId();\n const email = await tryGetEmail();\n\n if (email) {\n return {\n distinct_id: email,\n distinct_id_source: \"email\",\n org_id: orgId,\n };\n }\n\n if (orgId) {\n return {\n distinct_id: orgId,\n distinct_id_source: \"git_org\",\n org_id: orgId,\n };\n }\n\n const deviceId = `device-${await machineIdLib.machineId()}`;\n if (process.env.DEBUG === \"true\") {\n console.warn(\n \"[Tracking] Using device ID fallback. Consider using git repository for consistent tracking.\",\n );\n }\n return {\n distinct_id: deviceId,\n distinct_id_source: \"device\",\n org_id: null,\n };\n}\n\nasync function tryGetEmail(): Promise<string | null> {\n const rc = getRc();\n const apiKey = process.env.LINGODOTDEV_API_KEY || rc?.auth?.apiKey;\n const apiUrl =\n process.env.LINGODOTDEV_API_URL ||\n rc?.auth?.apiUrl ||\n \"https://engine.lingo.dev\";\n\n if (!apiKey) {\n return null;\n }\n\n try {\n const res = await fetch(`${apiUrl}/whoami`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiKey}`,\n ContentType: \"application/json\",\n },\n });\n if (res.ok) {\n const payload = await res.json();\n if (payload?.email) {\n return payload.email;\n }\n }\n } catch (err) {\n // ignore\n }\n\n return null;\n}\n"],"mappings":";;;;;;AAKA,eAA8B,WAC5B,OACA,YACA;AACA,KAAI,QAAQ,IAAI,iBAAiB,IAC/B;AAGF,KAAI;EACF,MAAM,eAAe,MAAM,eAAe;AAE1C,MAAI,QAAQ,IAAI,UAAU,OACxB,SAAQ,IACN,qBAAqB,MAAM,QAAQ,aAAa,YAAY,YAAY,aAAa,qBACtF;EAGH,MAAM,EAAE,YAAY,MAAM,OAAO;EACjC,MAAM,UAAU,IAAI,QAClB,mDACA;GACE,MAAM;GACN,SAAS;GACT,eAAe;GAChB,CACF;AAED,QAAM,QAAQ,QAAQ;GACpB,YAAY,aAAa;GACzB;GACA,YAAY;IACV,GAAG;IACH,YAAY,YAAY,WAAW;IACnC,kBAAkB;IAClB,kBAAkB;IAClB,oBAAoB,aAAa;IACjC,QAAQ,aAAa;IACrB,MAAM;KACJ,SAAS,QAAQ,IAAI;KACrB,MAAM,QAAQ,IAAI,OAAO;KAC1B;IACF;GACF,CAAC;AAEF,QAAM,QAAQ,UAAU;UACjB,OAAO;AACd,MAAI,QAAQ,IAAI,UAAU,OACxB,SAAQ,MAAM,qBAAqB,MAAM;;;AAK/C,eAAe,gBAIZ;CACD,MAAM,QAAQ,UAAU;CACxB,MAAM,QAAQ,MAAM,aAAa;AAEjC,KAAI,MACF,QAAO;EACL,aAAa;EACb,oBAAoB;EACpB,QAAQ;EACT;AAGH,KAAI,MACF,QAAO;EACL,aAAa;EACb,oBAAoB;EACpB,QAAQ;EACT;CAGH,MAAM,WAAW,UAAU,MAAM,aAAa,WAAW;AACzD,KAAI,QAAQ,IAAI,UAAU,OACxB,SAAQ,KACN,8FACD;AAEH,QAAO;EACL,aAAa;EACb,oBAAoB;EACpB,QAAQ;EACT;;AAGH,eAAe,cAAsC;CACnD,MAAM,KAAK,OAAO;CAClB,MAAM,SAAS,QAAQ,IAAI,uBAAuB,IAAI,MAAM;CAC5D,MAAM,SACJ,QAAQ,IAAI,uBACZ,IAAI,MAAM,UACV;AAEF,KAAI,CAAC,OACH,QAAO;AAGT,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,GAAG,OAAO,UAAU;GAC1C,QAAQ;GACR,SAAS;IACP,eAAe,UAAU;IACzB,aAAa;IACd;GACF,CAAC;AACF,MAAI,IAAI,IAAI;GACV,MAAM,UAAU,MAAM,IAAI,MAAM;AAChC,OAAI,SAAS,MACX,QAAO,QAAQ;;UAGZ,KAAK;AAId,QAAO"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let child_process = require("child_process");
|
|
3
|
+
|
|
4
|
+
//#region src/utils/org-id.ts
|
|
5
|
+
let cachedGitOrgId = void 0;
|
|
6
|
+
function extractOrg(fullPath) {
|
|
7
|
+
const parts = fullPath.split("/");
|
|
8
|
+
if (parts.length < 1) return null;
|
|
9
|
+
return parts[0];
|
|
10
|
+
}
|
|
11
|
+
function getOrgId() {
|
|
12
|
+
const ciOrgId = getCIOrgId();
|
|
13
|
+
if (ciOrgId) return ciOrgId;
|
|
14
|
+
const gitOrgId = getGitOrgId();
|
|
15
|
+
if (gitOrgId) return gitOrgId;
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
function getCIOrgId() {
|
|
19
|
+
if (process.env.GITHUB_REPOSITORY) {
|
|
20
|
+
const org = extractOrg(process.env.GITHUB_REPOSITORY);
|
|
21
|
+
if (org) return `github:${org}`;
|
|
22
|
+
}
|
|
23
|
+
if (process.env.CI_PROJECT_PATH) {
|
|
24
|
+
const org = extractOrg(process.env.CI_PROJECT_PATH);
|
|
25
|
+
if (org) return `gitlab:${org}`;
|
|
26
|
+
}
|
|
27
|
+
if (process.env.BITBUCKET_REPO_FULL_NAME) {
|
|
28
|
+
const org = extractOrg(process.env.BITBUCKET_REPO_FULL_NAME);
|
|
29
|
+
if (org) return `bitbucket:${org}`;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function getGitOrgId() {
|
|
34
|
+
if (cachedGitOrgId !== void 0) return cachedGitOrgId;
|
|
35
|
+
try {
|
|
36
|
+
const remoteUrl = (0, child_process.execSync)("git config --get remote.origin.url", {
|
|
37
|
+
encoding: "utf8",
|
|
38
|
+
stdio: [
|
|
39
|
+
"pipe",
|
|
40
|
+
"pipe",
|
|
41
|
+
"ignore"
|
|
42
|
+
]
|
|
43
|
+
}).trim();
|
|
44
|
+
if (!remoteUrl) {
|
|
45
|
+
cachedGitOrgId = null;
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
cachedGitOrgId = parseGitUrl(remoteUrl);
|
|
49
|
+
return cachedGitOrgId;
|
|
50
|
+
} catch {
|
|
51
|
+
cachedGitOrgId = null;
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function parseGitUrl(url) {
|
|
56
|
+
const cleanUrl = url.replace(/\.git$/, "");
|
|
57
|
+
let platform = null;
|
|
58
|
+
if (cleanUrl.includes("github.com")) platform = "github";
|
|
59
|
+
else if (cleanUrl.includes("gitlab.com")) platform = "gitlab";
|
|
60
|
+
else if (cleanUrl.includes("bitbucket.org")) platform = "bitbucket";
|
|
61
|
+
const sshMatch = cleanUrl.match(/[@:]([^:/@]+\/[^:/@]+)$/);
|
|
62
|
+
const httpsMatch = cleanUrl.match(/\/([^/]+\/[^/]+)$/);
|
|
63
|
+
const repoPath = sshMatch?.[1] || httpsMatch?.[1];
|
|
64
|
+
if (!repoPath) return null;
|
|
65
|
+
const org = extractOrg(repoPath);
|
|
66
|
+
if (!org) return null;
|
|
67
|
+
if (platform) return `${platform}:${org}`;
|
|
68
|
+
return `git:${org}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
exports.getOrgId = getOrgId;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/org-id.ts
|
|
4
|
+
let cachedGitOrgId = void 0;
|
|
5
|
+
function extractOrg(fullPath) {
|
|
6
|
+
const parts = fullPath.split("/");
|
|
7
|
+
if (parts.length < 1) return null;
|
|
8
|
+
return parts[0];
|
|
9
|
+
}
|
|
10
|
+
function getOrgId() {
|
|
11
|
+
const ciOrgId = getCIOrgId();
|
|
12
|
+
if (ciOrgId) return ciOrgId;
|
|
13
|
+
const gitOrgId = getGitOrgId();
|
|
14
|
+
if (gitOrgId) return gitOrgId;
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
function getCIOrgId() {
|
|
18
|
+
if (process.env.GITHUB_REPOSITORY) {
|
|
19
|
+
const org = extractOrg(process.env.GITHUB_REPOSITORY);
|
|
20
|
+
if (org) return `github:${org}`;
|
|
21
|
+
}
|
|
22
|
+
if (process.env.CI_PROJECT_PATH) {
|
|
23
|
+
const org = extractOrg(process.env.CI_PROJECT_PATH);
|
|
24
|
+
if (org) return `gitlab:${org}`;
|
|
25
|
+
}
|
|
26
|
+
if (process.env.BITBUCKET_REPO_FULL_NAME) {
|
|
27
|
+
const org = extractOrg(process.env.BITBUCKET_REPO_FULL_NAME);
|
|
28
|
+
if (org) return `bitbucket:${org}`;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function getGitOrgId() {
|
|
33
|
+
if (cachedGitOrgId !== void 0) return cachedGitOrgId;
|
|
34
|
+
try {
|
|
35
|
+
const remoteUrl = execSync("git config --get remote.origin.url", {
|
|
36
|
+
encoding: "utf8",
|
|
37
|
+
stdio: [
|
|
38
|
+
"pipe",
|
|
39
|
+
"pipe",
|
|
40
|
+
"ignore"
|
|
41
|
+
]
|
|
42
|
+
}).trim();
|
|
43
|
+
if (!remoteUrl) {
|
|
44
|
+
cachedGitOrgId = null;
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
cachedGitOrgId = parseGitUrl(remoteUrl);
|
|
48
|
+
return cachedGitOrgId;
|
|
49
|
+
} catch {
|
|
50
|
+
cachedGitOrgId = null;
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function parseGitUrl(url) {
|
|
55
|
+
const cleanUrl = url.replace(/\.git$/, "");
|
|
56
|
+
let platform = null;
|
|
57
|
+
if (cleanUrl.includes("github.com")) platform = "github";
|
|
58
|
+
else if (cleanUrl.includes("gitlab.com")) platform = "gitlab";
|
|
59
|
+
else if (cleanUrl.includes("bitbucket.org")) platform = "bitbucket";
|
|
60
|
+
const sshMatch = cleanUrl.match(/[@:]([^:/@]+\/[^:/@]+)$/);
|
|
61
|
+
const httpsMatch = cleanUrl.match(/\/([^/]+\/[^/]+)$/);
|
|
62
|
+
const repoPath = sshMatch?.[1] || httpsMatch?.[1];
|
|
63
|
+
if (!repoPath) return null;
|
|
64
|
+
const org = extractOrg(repoPath);
|
|
65
|
+
if (!org) return null;
|
|
66
|
+
if (platform) return `${platform}:${org}`;
|
|
67
|
+
return `git:${org}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//#endregion
|
|
71
|
+
export { getOrgId };
|
|
72
|
+
//# sourceMappingURL=org-id.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-id.mjs","names":["cachedGitOrgId: string | null | undefined","platform: string | null"],"sources":["../../src/utils/org-id.ts"],"sourcesContent":["import { execSync } from \"child_process\";\n\nlet cachedGitOrgId: string | null | undefined = undefined;\n\nfunction extractOrg(fullPath: string): string | null {\n const parts = fullPath.split(\"/\");\n if (parts.length < 1) {\n return null;\n }\n return parts[0];\n}\n\nexport function getOrgId(): string | null {\n const ciOrgId = getCIOrgId();\n if (ciOrgId) return ciOrgId;\n\n const gitOrgId = getGitOrgId();\n if (gitOrgId) return gitOrgId;\n\n return null;\n}\n\nfunction getCIOrgId(): string | null {\n if (process.env.GITHUB_REPOSITORY) {\n const org = extractOrg(process.env.GITHUB_REPOSITORY);\n if (org) return `github:${org}`;\n }\n\n if (process.env.CI_PROJECT_PATH) {\n const org = extractOrg(process.env.CI_PROJECT_PATH);\n if (org) return `gitlab:${org}`;\n }\n\n if (process.env.BITBUCKET_REPO_FULL_NAME) {\n const org = extractOrg(process.env.BITBUCKET_REPO_FULL_NAME);\n if (org) return `bitbucket:${org}`;\n }\n\n return null;\n}\n\nfunction getGitOrgId(): string | null {\n if (cachedGitOrgId !== undefined) {\n return cachedGitOrgId;\n }\n\n try {\n const remoteUrl = execSync(\"git config --get remote.origin.url\", {\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n }).trim();\n\n if (!remoteUrl) {\n cachedGitOrgId = null;\n return null;\n }\n\n cachedGitOrgId = parseGitUrl(remoteUrl);\n return cachedGitOrgId;\n } catch {\n cachedGitOrgId = null;\n return null;\n }\n}\n\nfunction parseGitUrl(url: string): string | null {\n const cleanUrl = url.replace(/\\.git$/, \"\");\n\n let platform: string | null = null;\n if (cleanUrl.includes(\"github.com\")) {\n platform = \"github\";\n } else if (cleanUrl.includes(\"gitlab.com\")) {\n platform = \"gitlab\";\n } else if (cleanUrl.includes(\"bitbucket.org\")) {\n platform = \"bitbucket\";\n }\n\n const sshMatch = cleanUrl.match(/[@:]([^:/@]+\\/[^:/@]+)$/);\n const httpsMatch = cleanUrl.match(/\\/([^/]+\\/[^/]+)$/);\n\n const repoPath = sshMatch?.[1] || httpsMatch?.[1];\n\n if (!repoPath) return null;\n\n const org = extractOrg(repoPath);\n if (!org) return null;\n\n if (platform) {\n return `${platform}:${org}`;\n }\n\n return `git:${org}`;\n}\n"],"mappings":";;;AAEA,IAAIA,iBAA4C;AAEhD,SAAS,WAAW,UAAiC;CACnD,MAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,KAAI,MAAM,SAAS,EACjB,QAAO;AAET,QAAO,MAAM;;AAGf,SAAgB,WAA0B;CACxC,MAAM,UAAU,YAAY;AAC5B,KAAI,QAAS,QAAO;CAEpB,MAAM,WAAW,aAAa;AAC9B,KAAI,SAAU,QAAO;AAErB,QAAO;;AAGT,SAAS,aAA4B;AACnC,KAAI,QAAQ,IAAI,mBAAmB;EACjC,MAAM,MAAM,WAAW,QAAQ,IAAI,kBAAkB;AACrD,MAAI,IAAK,QAAO,UAAU;;AAG5B,KAAI,QAAQ,IAAI,iBAAiB;EAC/B,MAAM,MAAM,WAAW,QAAQ,IAAI,gBAAgB;AACnD,MAAI,IAAK,QAAO,UAAU;;AAG5B,KAAI,QAAQ,IAAI,0BAA0B;EACxC,MAAM,MAAM,WAAW,QAAQ,IAAI,yBAAyB;AAC5D,MAAI,IAAK,QAAO,aAAa;;AAG/B,QAAO;;AAGT,SAAS,cAA6B;AACpC,KAAI,mBAAmB,OACrB,QAAO;AAGT,KAAI;EACF,MAAM,YAAY,SAAS,sCAAsC;GAC/D,UAAU;GACV,OAAO;IAAC;IAAQ;IAAQ;IAAS;GAClC,CAAC,CAAC,MAAM;AAET,MAAI,CAAC,WAAW;AACd,oBAAiB;AACjB,UAAO;;AAGT,mBAAiB,YAAY,UAAU;AACvC,SAAO;SACD;AACN,mBAAiB;AACjB,SAAO;;;AAIX,SAAS,YAAY,KAA4B;CAC/C,MAAM,WAAW,IAAI,QAAQ,UAAU,GAAG;CAE1C,IAAIC,WAA0B;AAC9B,KAAI,SAAS,SAAS,aAAa,CACjC,YAAW;UACF,SAAS,SAAS,aAAa,CACxC,YAAW;UACF,SAAS,SAAS,gBAAgB,CAC3C,YAAW;CAGb,MAAM,WAAW,SAAS,MAAM,0BAA0B;CAC1D,MAAM,aAAa,SAAS,MAAM,oBAAoB;CAEtD,MAAM,WAAW,WAAW,MAAM,aAAa;AAE/C,KAAI,CAAC,SAAU,QAAO;CAEtB,MAAM,MAAM,WAAW,SAAS;AAChC,KAAI,CAAC,IAAK,QAAO;AAEjB,KAAI,SACF,QAAO,GAAG,SAAS,GAAG;AAGxB,QAAO,OAAO"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lingo.dev/compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Lingo.dev Compiler",
|
|
5
5
|
"private": false,
|
|
6
6
|
"repository": {
|
|
@@ -141,6 +141,7 @@
|
|
|
141
141
|
"@ai-sdk/google": "3.0.1",
|
|
142
142
|
"@ai-sdk/groq": "3.0.1",
|
|
143
143
|
"@ai-sdk/mistral": "3.0.1",
|
|
144
|
+
"@ai-sdk/openai": "3.0.1",
|
|
144
145
|
"@babel/core": "7.26.0",
|
|
145
146
|
"@babel/generator": "7.28.5",
|
|
146
147
|
"@babel/parser": "7.28.5",
|
|
@@ -161,7 +162,7 @@
|
|
|
161
162
|
"posthog-node": "5.14.0",
|
|
162
163
|
"proper-lockfile": "4.1.2",
|
|
163
164
|
"ws": "8.18.3",
|
|
164
|
-
"lingo.dev": "^0.125.
|
|
165
|
+
"lingo.dev": "^0.125.4"
|
|
165
166
|
},
|
|
166
167
|
"peerDependencies": {
|
|
167
168
|
"next": "^15.0.0 || ^16.0.4",
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
-
let crypto = require("crypto");
|
|
3
|
-
let child_process = require("child_process");
|
|
4
|
-
|
|
5
|
-
//#region src/utils/repository-id.ts
|
|
6
|
-
let cachedGitRepoId = void 0;
|
|
7
|
-
function hashProjectName(fullPath) {
|
|
8
|
-
const parts = fullPath.split("/");
|
|
9
|
-
if (parts.length !== 2) return (0, crypto.createHash)("sha256").update(fullPath).digest("hex").slice(0, 8);
|
|
10
|
-
const [org, project] = parts;
|
|
11
|
-
return `${org}/${(0, crypto.createHash)("sha256").update(project).digest("hex").slice(0, 8)}`;
|
|
12
|
-
}
|
|
13
|
-
function getRepositoryId() {
|
|
14
|
-
const ciRepoId = getCIRepositoryId();
|
|
15
|
-
if (ciRepoId) return ciRepoId;
|
|
16
|
-
const gitRepoId = getGitRepositoryId();
|
|
17
|
-
if (gitRepoId) return gitRepoId;
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
function getCIRepositoryId() {
|
|
21
|
-
if (process.env.GITHUB_REPOSITORY) return `github:${hashProjectName(process.env.GITHUB_REPOSITORY)}`;
|
|
22
|
-
if (process.env.CI_PROJECT_PATH) return `gitlab:${hashProjectName(process.env.CI_PROJECT_PATH)}`;
|
|
23
|
-
if (process.env.BITBUCKET_REPO_FULL_NAME) return `bitbucket:${hashProjectName(process.env.BITBUCKET_REPO_FULL_NAME)}`;
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
function getGitRepositoryId() {
|
|
27
|
-
if (cachedGitRepoId !== void 0) return cachedGitRepoId;
|
|
28
|
-
try {
|
|
29
|
-
const remoteUrl = (0, child_process.execSync)("git config --get remote.origin.url", {
|
|
30
|
-
encoding: "utf8",
|
|
31
|
-
stdio: [
|
|
32
|
-
"pipe",
|
|
33
|
-
"pipe",
|
|
34
|
-
"ignore"
|
|
35
|
-
]
|
|
36
|
-
}).trim();
|
|
37
|
-
if (!remoteUrl) {
|
|
38
|
-
cachedGitRepoId = null;
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
cachedGitRepoId = parseGitUrl(remoteUrl);
|
|
42
|
-
return cachedGitRepoId;
|
|
43
|
-
} catch {
|
|
44
|
-
cachedGitRepoId = null;
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function parseGitUrl(url) {
|
|
49
|
-
const cleanUrl = url.replace(/\.git$/, "");
|
|
50
|
-
let platform = null;
|
|
51
|
-
if (cleanUrl.includes("github.com")) platform = "github";
|
|
52
|
-
else if (cleanUrl.includes("gitlab.com")) platform = "gitlab";
|
|
53
|
-
else if (cleanUrl.includes("bitbucket.org")) platform = "bitbucket";
|
|
54
|
-
const sshMatch = cleanUrl.match(/[@:]([^:/@]+\/[^:/@]+)$/);
|
|
55
|
-
const httpsMatch = cleanUrl.match(/\/([^/]+\/[^/]+)$/);
|
|
56
|
-
const repoPath = sshMatch?.[1] || httpsMatch?.[1];
|
|
57
|
-
if (!repoPath) return null;
|
|
58
|
-
const hashedPath = hashProjectName(repoPath);
|
|
59
|
-
if (platform) return `${platform}:${hashedPath}`;
|
|
60
|
-
return `git:${hashedPath}`;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
//#endregion
|
|
64
|
-
exports.getRepositoryId = getRepositoryId;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { createHash } from "crypto";
|
|
2
|
-
import { execSync } from "child_process";
|
|
3
|
-
|
|
4
|
-
//#region src/utils/repository-id.ts
|
|
5
|
-
let cachedGitRepoId = void 0;
|
|
6
|
-
function hashProjectName(fullPath) {
|
|
7
|
-
const parts = fullPath.split("/");
|
|
8
|
-
if (parts.length !== 2) return createHash("sha256").update(fullPath).digest("hex").slice(0, 8);
|
|
9
|
-
const [org, project] = parts;
|
|
10
|
-
return `${org}/${createHash("sha256").update(project).digest("hex").slice(0, 8)}`;
|
|
11
|
-
}
|
|
12
|
-
function getRepositoryId() {
|
|
13
|
-
const ciRepoId = getCIRepositoryId();
|
|
14
|
-
if (ciRepoId) return ciRepoId;
|
|
15
|
-
const gitRepoId = getGitRepositoryId();
|
|
16
|
-
if (gitRepoId) return gitRepoId;
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
function getCIRepositoryId() {
|
|
20
|
-
if (process.env.GITHUB_REPOSITORY) return `github:${hashProjectName(process.env.GITHUB_REPOSITORY)}`;
|
|
21
|
-
if (process.env.CI_PROJECT_PATH) return `gitlab:${hashProjectName(process.env.CI_PROJECT_PATH)}`;
|
|
22
|
-
if (process.env.BITBUCKET_REPO_FULL_NAME) return `bitbucket:${hashProjectName(process.env.BITBUCKET_REPO_FULL_NAME)}`;
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
function getGitRepositoryId() {
|
|
26
|
-
if (cachedGitRepoId !== void 0) return cachedGitRepoId;
|
|
27
|
-
try {
|
|
28
|
-
const remoteUrl = execSync("git config --get remote.origin.url", {
|
|
29
|
-
encoding: "utf8",
|
|
30
|
-
stdio: [
|
|
31
|
-
"pipe",
|
|
32
|
-
"pipe",
|
|
33
|
-
"ignore"
|
|
34
|
-
]
|
|
35
|
-
}).trim();
|
|
36
|
-
if (!remoteUrl) {
|
|
37
|
-
cachedGitRepoId = null;
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
cachedGitRepoId = parseGitUrl(remoteUrl);
|
|
41
|
-
return cachedGitRepoId;
|
|
42
|
-
} catch {
|
|
43
|
-
cachedGitRepoId = null;
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
function parseGitUrl(url) {
|
|
48
|
-
const cleanUrl = url.replace(/\.git$/, "");
|
|
49
|
-
let platform = null;
|
|
50
|
-
if (cleanUrl.includes("github.com")) platform = "github";
|
|
51
|
-
else if (cleanUrl.includes("gitlab.com")) platform = "gitlab";
|
|
52
|
-
else if (cleanUrl.includes("bitbucket.org")) platform = "bitbucket";
|
|
53
|
-
const sshMatch = cleanUrl.match(/[@:]([^:/@]+\/[^:/@]+)$/);
|
|
54
|
-
const httpsMatch = cleanUrl.match(/\/([^/]+\/[^/]+)$/);
|
|
55
|
-
const repoPath = sshMatch?.[1] || httpsMatch?.[1];
|
|
56
|
-
if (!repoPath) return null;
|
|
57
|
-
const hashedPath = hashProjectName(repoPath);
|
|
58
|
-
if (platform) return `${platform}:${hashedPath}`;
|
|
59
|
-
return `git:${hashedPath}`;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
//#endregion
|
|
63
|
-
export { getRepositoryId };
|
|
64
|
-
//# sourceMappingURL=repository-id.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"repository-id.mjs","names":["cachedGitRepoId: string | null | undefined","platform: string | null"],"sources":["../../src/utils/repository-id.ts"],"sourcesContent":["import { execSync } from \"child_process\";\nimport { createHash } from \"crypto\";\n\nlet cachedGitRepoId: string | null | undefined = undefined;\n\nfunction hashProjectName(fullPath: string): string {\n const parts = fullPath.split(\"/\");\n if (parts.length !== 2) {\n return createHash(\"sha256\").update(fullPath).digest(\"hex\").slice(0, 8);\n }\n\n const [org, project] = parts;\n const hashedProject = createHash(\"sha256\")\n .update(project)\n .digest(\"hex\")\n .slice(0, 8);\n\n return `${org}/${hashedProject}`;\n}\n\nexport function getRepositoryId(): string | null {\n const ciRepoId = getCIRepositoryId();\n if (ciRepoId) return ciRepoId;\n\n const gitRepoId = getGitRepositoryId();\n if (gitRepoId) return gitRepoId;\n\n return null;\n}\n\nfunction getCIRepositoryId(): string | null {\n if (process.env.GITHUB_REPOSITORY) {\n const hashed = hashProjectName(process.env.GITHUB_REPOSITORY);\n return `github:${hashed}`;\n }\n\n if (process.env.CI_PROJECT_PATH) {\n const hashed = hashProjectName(process.env.CI_PROJECT_PATH);\n return `gitlab:${hashed}`;\n }\n\n if (process.env.BITBUCKET_REPO_FULL_NAME) {\n const hashed = hashProjectName(process.env.BITBUCKET_REPO_FULL_NAME);\n return `bitbucket:${hashed}`;\n }\n\n return null;\n}\n\nfunction getGitRepositoryId(): string | null {\n if (cachedGitRepoId !== undefined) {\n return cachedGitRepoId;\n }\n\n try {\n const remoteUrl = execSync(\"git config --get remote.origin.url\", {\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n }).trim();\n\n if (!remoteUrl) {\n cachedGitRepoId = null;\n return null;\n }\n\n cachedGitRepoId = parseGitUrl(remoteUrl);\n return cachedGitRepoId;\n } catch {\n cachedGitRepoId = null;\n return null;\n }\n}\n\nfunction parseGitUrl(url: string): string | null {\n const cleanUrl = url.replace(/\\.git$/, \"\");\n\n let platform: string | null = null;\n if (cleanUrl.includes(\"github.com\")) {\n platform = \"github\";\n } else if (cleanUrl.includes(\"gitlab.com\")) {\n platform = \"gitlab\";\n } else if (cleanUrl.includes(\"bitbucket.org\")) {\n platform = \"bitbucket\";\n }\n\n const sshMatch = cleanUrl.match(/[@:]([^:/@]+\\/[^:/@]+)$/);\n const httpsMatch = cleanUrl.match(/\\/([^/]+\\/[^/]+)$/);\n\n const repoPath = sshMatch?.[1] || httpsMatch?.[1];\n\n if (!repoPath) return null;\n\n const hashedPath = hashProjectName(repoPath);\n\n if (platform) {\n return `${platform}:${hashedPath}`;\n }\n\n return `git:${hashedPath}`;\n}\n"],"mappings":";;;;AAGA,IAAIA,kBAA6C;AAEjD,SAAS,gBAAgB,UAA0B;CACjD,MAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,KAAI,MAAM,WAAW,EACnB,QAAO,WAAW,SAAS,CAAC,OAAO,SAAS,CAAC,OAAO,MAAM,CAAC,MAAM,GAAG,EAAE;CAGxE,MAAM,CAAC,KAAK,WAAW;AAMvB,QAAO,GAAG,IAAI,GALQ,WAAW,SAAS,CACvC,OAAO,QAAQ,CACf,OAAO,MAAM,CACb,MAAM,GAAG,EAAE;;AAKhB,SAAgB,kBAAiC;CAC/C,MAAM,WAAW,mBAAmB;AACpC,KAAI,SAAU,QAAO;CAErB,MAAM,YAAY,oBAAoB;AACtC,KAAI,UAAW,QAAO;AAEtB,QAAO;;AAGT,SAAS,oBAAmC;AAC1C,KAAI,QAAQ,IAAI,kBAEd,QAAO,UADQ,gBAAgB,QAAQ,IAAI,kBAAkB;AAI/D,KAAI,QAAQ,IAAI,gBAEd,QAAO,UADQ,gBAAgB,QAAQ,IAAI,gBAAgB;AAI7D,KAAI,QAAQ,IAAI,yBAEd,QAAO,aADQ,gBAAgB,QAAQ,IAAI,yBAAyB;AAItE,QAAO;;AAGT,SAAS,qBAAoC;AAC3C,KAAI,oBAAoB,OACtB,QAAO;AAGT,KAAI;EACF,MAAM,YAAY,SAAS,sCAAsC;GAC/D,UAAU;GACV,OAAO;IAAC;IAAQ;IAAQ;IAAS;GAClC,CAAC,CAAC,MAAM;AAET,MAAI,CAAC,WAAW;AACd,qBAAkB;AAClB,UAAO;;AAGT,oBAAkB,YAAY,UAAU;AACxC,SAAO;SACD;AACN,oBAAkB;AAClB,SAAO;;;AAIX,SAAS,YAAY,KAA4B;CAC/C,MAAM,WAAW,IAAI,QAAQ,UAAU,GAAG;CAE1C,IAAIC,WAA0B;AAC9B,KAAI,SAAS,SAAS,aAAa,CACjC,YAAW;UACF,SAAS,SAAS,aAAa,CACxC,YAAW;UACF,SAAS,SAAS,gBAAgB,CAC3C,YAAW;CAGb,MAAM,WAAW,SAAS,MAAM,0BAA0B;CAC1D,MAAM,aAAa,SAAS,MAAM,oBAAoB;CAEtD,MAAM,WAAW,WAAW,MAAM,aAAa;AAE/C,KAAI,CAAC,SAAU,QAAO;CAEtB,MAAM,aAAa,gBAAgB,SAAS;AAE5C,KAAI,SACF,QAAO,GAAG,SAAS,GAAG;AAGxB,QAAO,OAAO"}
|