mirror of
https://github.com/di-sukharev/opencommit.git
synced 2026-01-14 16:18:02 -05:00
Compare commits
4 Commits
dev
...
390-add_co
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68dc9c36eb | ||
|
|
e063faa491 | ||
|
|
c7b1a5bcdc | ||
|
|
92943d3da8 |
120
out/cli.cjs
120
out/cli.cjs
@@ -25193,7 +25193,7 @@ function G3(t2, e3) {
|
|||||||
// package.json
|
// package.json
|
||||||
var package_default = {
|
var package_default = {
|
||||||
name: "opencommit",
|
name: "opencommit",
|
||||||
version: "3.0.20",
|
version: "3.1.0",
|
||||||
description: "Auto-generate impressive commits in 1 second. Killing lame commits with AI \u{1F92F}\u{1F52B}",
|
description: "Auto-generate impressive commits in 1 second. Killing lame commits with AI \u{1F92F}\u{1F52B}",
|
||||||
keywords: [
|
keywords: [
|
||||||
"git",
|
"git",
|
||||||
@@ -28029,28 +28029,7 @@ var configValidators = {
|
|||||||
};
|
};
|
||||||
var defaultConfigPath = (0, import_path.join)((0, import_os.homedir)(), ".opencommit");
|
var defaultConfigPath = (0, import_path.join)((0, import_os.homedir)(), ".opencommit");
|
||||||
var defaultEnvPath = (0, import_path.resolve)(process.cwd(), ".env");
|
var defaultEnvPath = (0, import_path.resolve)(process.cwd(), ".env");
|
||||||
var assertConfigsAreValid = (config7) => {
|
var DEFAULT_CONFIG = {
|
||||||
for (const [key, value] of Object.entries(config7)) {
|
|
||||||
if (!value)
|
|
||||||
continue;
|
|
||||||
if (typeof value === "string" && ["null", "undefined"].includes(value)) {
|
|
||||||
config7[key] = void 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const validate = configValidators[key];
|
|
||||||
validate(value, config7);
|
|
||||||
} catch (error) {
|
|
||||||
ce(`Unknown '${key}' config option or missing validator.`);
|
|
||||||
ce(
|
|
||||||
`Manually fix the '.env' file or global '~/.opencommit' config file.`
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var initGlobalConfig = () => {
|
|
||||||
const defaultConfig = {
|
|
||||||
OCO_TOKENS_MAX_INPUT: 40960 /* DEFAULT_MAX_TOKENS_INPUT */,
|
OCO_TOKENS_MAX_INPUT: 40960 /* DEFAULT_MAX_TOKENS_INPUT */,
|
||||||
OCO_TOKENS_MAX_OUTPUT: 4096 /* DEFAULT_MAX_TOKENS_OUTPUT */,
|
OCO_TOKENS_MAX_OUTPUT: 4096 /* DEFAULT_MAX_TOKENS_OUTPUT */,
|
||||||
OCO_DESCRIPTION: false,
|
OCO_DESCRIPTION: false,
|
||||||
@@ -28064,9 +28043,10 @@ var initGlobalConfig = () => {
|
|||||||
OCO_TEST_MOCK_TYPE: "commit-message",
|
OCO_TEST_MOCK_TYPE: "commit-message",
|
||||||
OCO_FLOWISE_ENDPOINT: ":",
|
OCO_FLOWISE_ENDPOINT: ":",
|
||||||
OCO_GITPUSH: true
|
OCO_GITPUSH: true
|
||||||
};
|
};
|
||||||
(0, import_fs.writeFileSync)(defaultConfigPath, (0, import_ini.stringify)(defaultConfig), "utf8");
|
var initGlobalConfig = (configPath = defaultConfigPath) => {
|
||||||
return defaultConfig;
|
(0, import_fs.writeFileSync)(configPath, (0, import_ini.stringify)(DEFAULT_CONFIG), "utf8");
|
||||||
|
return DEFAULT_CONFIG;
|
||||||
};
|
};
|
||||||
var parseEnvVarValue = (value) => {
|
var parseEnvVarValue = (value) => {
|
||||||
try {
|
try {
|
||||||
@@ -28075,12 +28055,9 @@ var parseEnvVarValue = (value) => {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var getConfig = ({
|
var getEnvConfig = (envPath) => {
|
||||||
configPath = defaultConfigPath,
|
|
||||||
envPath = defaultEnvPath
|
|
||||||
} = {}) => {
|
|
||||||
dotenv.config({ path: envPath });
|
dotenv.config({ path: envPath });
|
||||||
const envConfig = {
|
return {
|
||||||
OCO_MODEL: process.env.OCO_MODEL,
|
OCO_MODEL: process.env.OCO_MODEL,
|
||||||
OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY,
|
OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY,
|
||||||
OCO_ANTHROPIC_API_KEY: process.env.OCO_ANTHROPIC_API_KEY,
|
OCO_ANTHROPIC_API_KEY: process.env.OCO_ANTHROPIC_API_KEY,
|
||||||
@@ -28104,23 +28081,35 @@ var getConfig = ({
|
|||||||
OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE,
|
OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE,
|
||||||
OCO_GITPUSH: parseEnvVarValue(process.env.OCO_GITPUSH)
|
OCO_GITPUSH: parseEnvVarValue(process.env.OCO_GITPUSH)
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
var getGlobalConfig = (configPath) => {
|
||||||
let globalConfig;
|
let globalConfig;
|
||||||
const isGlobalConfigFileExist = (0, import_fs.existsSync)(configPath);
|
const isGlobalConfigFileExist = (0, import_fs.existsSync)(configPath);
|
||||||
if (!isGlobalConfigFileExist)
|
if (!isGlobalConfigFileExist)
|
||||||
globalConfig = initGlobalConfig();
|
globalConfig = initGlobalConfig(configPath);
|
||||||
else {
|
else {
|
||||||
const configFile = (0, import_fs.readFileSync)(configPath, "utf8");
|
const configFile = (0, import_fs.readFileSync)(configPath, "utf8");
|
||||||
globalConfig = (0, import_ini.parse)(configFile);
|
globalConfig = (0, import_ini.parse)(configFile);
|
||||||
}
|
}
|
||||||
const mergeObjects = (main, fallback) => Object.keys(CONFIG_KEYS).reduce((acc, key) => {
|
return globalConfig;
|
||||||
|
};
|
||||||
|
var mergeConfigs = (main, fallback) => Object.keys(CONFIG_KEYS).reduce((acc, key) => {
|
||||||
acc[key] = parseEnvVarValue(main[key] ?? fallback[key]);
|
acc[key] = parseEnvVarValue(main[key] ?? fallback[key]);
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
const config7 = mergeObjects(envConfig, globalConfig);
|
var getConfig = ({
|
||||||
|
envPath = defaultEnvPath,
|
||||||
|
globalPath = defaultConfigPath
|
||||||
|
} = {}) => {
|
||||||
|
const envConfig = getEnvConfig(envPath);
|
||||||
|
const globalConfig = getGlobalConfig(globalPath);
|
||||||
|
const config7 = mergeConfigs(envConfig, globalConfig);
|
||||||
return config7;
|
return config7;
|
||||||
};
|
};
|
||||||
var setConfig = (keyValues, configPath = defaultConfigPath) => {
|
var setConfig = (keyValues, globalConfigPath = defaultConfigPath) => {
|
||||||
const config7 = getConfig();
|
const config7 = getConfig({
|
||||||
|
globalPath: globalConfigPath
|
||||||
|
});
|
||||||
for (let [key, value] of keyValues) {
|
for (let [key, value] of keyValues) {
|
||||||
if (!configValidators.hasOwnProperty(key)) {
|
if (!configValidators.hasOwnProperty(key)) {
|
||||||
const supportedKeys = Object.keys(configValidators).join("\n");
|
const supportedKeys = Object.keys(configValidators).join("\n");
|
||||||
@@ -28144,8 +28133,7 @@ For more help refer to our docs: https://github.com/di-sukharev/opencommit`
|
|||||||
);
|
);
|
||||||
config7[key] = validValue;
|
config7[key] = validValue;
|
||||||
}
|
}
|
||||||
(0, import_fs.writeFileSync)(configPath, (0, import_ini.stringify)(config7), "utf8");
|
(0, import_fs.writeFileSync)(globalConfigPath, (0, import_ini.stringify)(config7), "utf8");
|
||||||
assertConfigsAreValid(config7);
|
|
||||||
ce(`${source_default.green("\u2714")} config successfully set`);
|
ce(`${source_default.green("\u2714")} config successfully set`);
|
||||||
};
|
};
|
||||||
var configCommand = G3(
|
var configCommand = G3(
|
||||||
@@ -42400,7 +42388,7 @@ var OpenAiEngine = class {
|
|||||||
function getEngine() {
|
function getEngine() {
|
||||||
const config7 = getConfig();
|
const config7 = getConfig();
|
||||||
const provider = config7.OCO_AI_PROVIDER;
|
const provider = config7.OCO_AI_PROVIDER;
|
||||||
const DEFAULT_CONFIG = {
|
const DEFAULT_CONFIG2 = {
|
||||||
model: config7.OCO_MODEL,
|
model: config7.OCO_MODEL,
|
||||||
maxTokensOutput: config7.OCO_TOKENS_MAX_OUTPUT,
|
maxTokensOutput: config7.OCO_TOKENS_MAX_OUTPUT,
|
||||||
maxTokensInput: config7.OCO_TOKENS_MAX_INPUT,
|
maxTokensInput: config7.OCO_TOKENS_MAX_INPUT,
|
||||||
@@ -42409,37 +42397,37 @@ function getEngine() {
|
|||||||
switch (provider) {
|
switch (provider) {
|
||||||
case "ollama" /* OLLAMA */:
|
case "ollama" /* OLLAMA */:
|
||||||
return new OllamaAi({
|
return new OllamaAi({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
apiKey: "",
|
apiKey: "",
|
||||||
baseURL: config7.OCO_OLLAMA_API_URL
|
baseURL: config7.OCO_OLLAMA_API_URL
|
||||||
});
|
});
|
||||||
case "anthropic" /* ANTHROPIC */:
|
case "anthropic" /* ANTHROPIC */:
|
||||||
return new AnthropicEngine({
|
return new AnthropicEngine({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
apiKey: config7.OCO_ANTHROPIC_API_KEY
|
apiKey: config7.OCO_ANTHROPIC_API_KEY
|
||||||
});
|
});
|
||||||
case "test" /* TEST */:
|
case "test" /* TEST */:
|
||||||
return new TestAi(config7.OCO_TEST_MOCK_TYPE);
|
return new TestAi(config7.OCO_TEST_MOCK_TYPE);
|
||||||
case "gemini" /* GEMINI */:
|
case "gemini" /* GEMINI */:
|
||||||
return new Gemini({
|
return new Gemini({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
apiKey: config7.OCO_GEMINI_API_KEY,
|
apiKey: config7.OCO_GEMINI_API_KEY,
|
||||||
baseURL: config7.OCO_GEMINI_BASE_PATH
|
baseURL: config7.OCO_GEMINI_BASE_PATH
|
||||||
});
|
});
|
||||||
case "azure" /* AZURE */:
|
case "azure" /* AZURE */:
|
||||||
return new AzureEngine({
|
return new AzureEngine({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
apiKey: config7.OCO_AZURE_API_KEY
|
apiKey: config7.OCO_AZURE_API_KEY
|
||||||
});
|
});
|
||||||
case "flowise" /* FLOWISE */:
|
case "flowise" /* FLOWISE */:
|
||||||
return new FlowiseAi({
|
return new FlowiseAi({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
baseURL: config7.OCO_FLOWISE_ENDPOINT || DEFAULT_CONFIG.baseURL,
|
baseURL: config7.OCO_FLOWISE_ENDPOINT || DEFAULT_CONFIG2.baseURL,
|
||||||
apiKey: config7.OCO_FLOWISE_API_KEY
|
apiKey: config7.OCO_FLOWISE_API_KEY
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
return new OpenAiEngine({
|
return new OpenAiEngine({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
apiKey: config7.OCO_OPENAI_API_KEY
|
apiKey: config7.OCO_OPENAI_API_KEY
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -43172,8 +43160,8 @@ var generateCommitMessageFromGitDiff = async ({
|
|||||||
skipCommitConfirmation = false
|
skipCommitConfirmation = false
|
||||||
}) => {
|
}) => {
|
||||||
await assertGitRepo();
|
await assertGitRepo();
|
||||||
const commitSpinner = le();
|
const commitGenerationSpinner = le();
|
||||||
commitSpinner.start("Generating the commit message");
|
commitGenerationSpinner.start("Generating the commit message");
|
||||||
try {
|
try {
|
||||||
let commitMessage = await generateCommitMessageByDiff(
|
let commitMessage = await generateCommitMessageByDiff(
|
||||||
diff,
|
diff,
|
||||||
@@ -43188,7 +43176,7 @@ var generateCommitMessageFromGitDiff = async ({
|
|||||||
commitMessage
|
commitMessage
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
commitSpinner.stop("\u{1F4DD} Commit message generated");
|
commitGenerationSpinner.stop("\u{1F4DD} Commit message generated");
|
||||||
ce(
|
ce(
|
||||||
`Generated commit message:
|
`Generated commit message:
|
||||||
${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014")}
|
${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014")}
|
||||||
@@ -43198,14 +43186,20 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2
|
|||||||
const isCommitConfirmedByUser = skipCommitConfirmation || await Q3({
|
const isCommitConfirmedByUser = skipCommitConfirmation || await Q3({
|
||||||
message: "Confirm the commit message?"
|
message: "Confirm the commit message?"
|
||||||
});
|
});
|
||||||
if (isCommitConfirmedByUser && !hD2(isCommitConfirmedByUser)) {
|
if (hD2(isCommitConfirmedByUser))
|
||||||
|
process.exit(1);
|
||||||
|
if (isCommitConfirmedByUser) {
|
||||||
|
const committingChangesSpinner = le();
|
||||||
|
committingChangesSpinner.start("Committing the changes");
|
||||||
const { stdout } = await execa("git", [
|
const { stdout } = await execa("git", [
|
||||||
"commit",
|
"commit",
|
||||||
"-m",
|
"-m",
|
||||||
commitMessage,
|
commitMessage,
|
||||||
...extraArgs2
|
...extraArgs2
|
||||||
]);
|
]);
|
||||||
ce(`${source_default.green("\u2714")} Successfully committed`);
|
committingChangesSpinner.stop(
|
||||||
|
`${source_default.green("\u2714")} Successfully committed`
|
||||||
|
);
|
||||||
ce(stdout);
|
ce(stdout);
|
||||||
const remotes = await getGitRemotes();
|
const remotes = await getGitRemotes();
|
||||||
if (!remotes.length) {
|
if (!remotes.length) {
|
||||||
@@ -43218,7 +43212,9 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2
|
|||||||
const isPushConfirmedByUser = await Q3({
|
const isPushConfirmedByUser = await Q3({
|
||||||
message: "Do you want to run `git push`?"
|
message: "Do you want to run `git push`?"
|
||||||
});
|
});
|
||||||
if (isPushConfirmedByUser && !hD2(isPushConfirmedByUser)) {
|
if (hD2(isPushConfirmedByUser))
|
||||||
|
process.exit(1);
|
||||||
|
if (isPushConfirmedByUser) {
|
||||||
const pushSpinner = le();
|
const pushSpinner = le();
|
||||||
pushSpinner.start(`Running 'git push ${remotes[0]}'`);
|
pushSpinner.start(`Running 'git push ${remotes[0]}'`);
|
||||||
const { stdout: stdout2 } = await execa("git", [
|
const { stdout: stdout2 } = await execa("git", [
|
||||||
@@ -43240,7 +43236,8 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2
|
|||||||
message: "Choose a remote to push to",
|
message: "Choose a remote to push to",
|
||||||
options: remotes.map((remote) => ({ value: remote, label: remote }))
|
options: remotes.map((remote) => ({ value: remote, label: remote }))
|
||||||
});
|
});
|
||||||
if (!hD2(selectedRemote)) {
|
if (hD2(selectedRemote))
|
||||||
|
process.exit(1);
|
||||||
const pushSpinner = le();
|
const pushSpinner = le();
|
||||||
pushSpinner.start(`Running 'git push ${selectedRemote}'`);
|
pushSpinner.start(`Running 'git push ${selectedRemote}'`);
|
||||||
const { stdout: stdout2 } = await execa("git", ["push", selectedRemote]);
|
const { stdout: stdout2 } = await execa("git", ["push", selectedRemote]);
|
||||||
@@ -43251,15 +43248,14 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2
|
|||||||
);
|
);
|
||||||
if (stdout2)
|
if (stdout2)
|
||||||
ce(stdout2);
|
ce(stdout2);
|
||||||
} else
|
|
||||||
ce(`${source_default.gray("\u2716")} process cancelled`);
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
if (!isCommitConfirmedByUser && !hD2(isCommitConfirmedByUser)) {
|
|
||||||
const regenerateMessage = await Q3({
|
const regenerateMessage = await Q3({
|
||||||
message: "Do you want to regenerate the message?"
|
message: "Do you want to regenerate the message?"
|
||||||
});
|
});
|
||||||
if (regenerateMessage && !hD2(isCommitConfirmedByUser)) {
|
if (hD2(regenerateMessage))
|
||||||
|
process.exit(1);
|
||||||
|
if (regenerateMessage) {
|
||||||
await generateCommitMessageFromGitDiff({
|
await generateCommitMessageFromGitDiff({
|
||||||
diff,
|
diff,
|
||||||
extraArgs: extraArgs2,
|
extraArgs: extraArgs2,
|
||||||
@@ -43268,7 +43264,7 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
commitSpinner.stop("\u{1F4DD} Commit message generated");
|
commitGenerationSpinner.stop("\u{1F4DD} Commit message generated");
|
||||||
const err = error;
|
const err = error;
|
||||||
ce(`${source_default.red("\u2716")} ${err?.message || err}`);
|
ce(`${source_default.red("\u2716")} ${err?.message || err}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@@ -43302,7 +43298,9 @@ async function commit(extraArgs2 = [], isStageAllFlag = false, fullGitMojiSpec =
|
|||||||
const isStageAllAndCommitConfirmedByUser = await Q3({
|
const isStageAllAndCommitConfirmedByUser = await Q3({
|
||||||
message: "Do you want to stage all files and generate commit message?"
|
message: "Do you want to stage all files and generate commit message?"
|
||||||
});
|
});
|
||||||
if (isStageAllAndCommitConfirmedByUser && !hD2(isStageAllAndCommitConfirmedByUser)) {
|
if (hD2(isStageAllAndCommitConfirmedByUser))
|
||||||
|
process.exit(1);
|
||||||
|
if (isStageAllAndCommitConfirmedByUser) {
|
||||||
await commit(extraArgs2, true, fullGitMojiSpec);
|
await commit(extraArgs2, true, fullGitMojiSpec);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46841,28 +46841,7 @@ var configValidators = {
|
|||||||
};
|
};
|
||||||
var defaultConfigPath = (0, import_path.join)((0, import_os.homedir)(), ".opencommit");
|
var defaultConfigPath = (0, import_path.join)((0, import_os.homedir)(), ".opencommit");
|
||||||
var defaultEnvPath = (0, import_path.resolve)(process.cwd(), ".env");
|
var defaultEnvPath = (0, import_path.resolve)(process.cwd(), ".env");
|
||||||
var assertConfigsAreValid = (config6) => {
|
var DEFAULT_CONFIG = {
|
||||||
for (const [key, value] of Object.entries(config6)) {
|
|
||||||
if (!value)
|
|
||||||
continue;
|
|
||||||
if (typeof value === "string" && ["null", "undefined"].includes(value)) {
|
|
||||||
config6[key] = void 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const validate = configValidators[key];
|
|
||||||
validate(value, config6);
|
|
||||||
} catch (error) {
|
|
||||||
ce(`Unknown '${key}' config option or missing validator.`);
|
|
||||||
ce(
|
|
||||||
`Manually fix the '.env' file or global '~/.opencommit' config file.`
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var initGlobalConfig = () => {
|
|
||||||
const defaultConfig = {
|
|
||||||
OCO_TOKENS_MAX_INPUT: 40960 /* DEFAULT_MAX_TOKENS_INPUT */,
|
OCO_TOKENS_MAX_INPUT: 40960 /* DEFAULT_MAX_TOKENS_INPUT */,
|
||||||
OCO_TOKENS_MAX_OUTPUT: 4096 /* DEFAULT_MAX_TOKENS_OUTPUT */,
|
OCO_TOKENS_MAX_OUTPUT: 4096 /* DEFAULT_MAX_TOKENS_OUTPUT */,
|
||||||
OCO_DESCRIPTION: false,
|
OCO_DESCRIPTION: false,
|
||||||
@@ -46876,9 +46855,10 @@ var initGlobalConfig = () => {
|
|||||||
OCO_TEST_MOCK_TYPE: "commit-message",
|
OCO_TEST_MOCK_TYPE: "commit-message",
|
||||||
OCO_FLOWISE_ENDPOINT: ":",
|
OCO_FLOWISE_ENDPOINT: ":",
|
||||||
OCO_GITPUSH: true
|
OCO_GITPUSH: true
|
||||||
};
|
};
|
||||||
(0, import_fs.writeFileSync)(defaultConfigPath, (0, import_ini.stringify)(defaultConfig), "utf8");
|
var initGlobalConfig = (configPath = defaultConfigPath) => {
|
||||||
return defaultConfig;
|
(0, import_fs.writeFileSync)(configPath, (0, import_ini.stringify)(DEFAULT_CONFIG), "utf8");
|
||||||
|
return DEFAULT_CONFIG;
|
||||||
};
|
};
|
||||||
var parseEnvVarValue = (value) => {
|
var parseEnvVarValue = (value) => {
|
||||||
try {
|
try {
|
||||||
@@ -46887,12 +46867,9 @@ var parseEnvVarValue = (value) => {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var getConfig = ({
|
var getEnvConfig = (envPath) => {
|
||||||
configPath = defaultConfigPath,
|
|
||||||
envPath = defaultEnvPath
|
|
||||||
} = {}) => {
|
|
||||||
dotenv.config({ path: envPath });
|
dotenv.config({ path: envPath });
|
||||||
const envConfig = {
|
return {
|
||||||
OCO_MODEL: process.env.OCO_MODEL,
|
OCO_MODEL: process.env.OCO_MODEL,
|
||||||
OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY,
|
OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY,
|
||||||
OCO_ANTHROPIC_API_KEY: process.env.OCO_ANTHROPIC_API_KEY,
|
OCO_ANTHROPIC_API_KEY: process.env.OCO_ANTHROPIC_API_KEY,
|
||||||
@@ -46916,23 +46893,35 @@ var getConfig = ({
|
|||||||
OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE,
|
OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE,
|
||||||
OCO_GITPUSH: parseEnvVarValue(process.env.OCO_GITPUSH)
|
OCO_GITPUSH: parseEnvVarValue(process.env.OCO_GITPUSH)
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
var getGlobalConfig = (configPath) => {
|
||||||
let globalConfig;
|
let globalConfig;
|
||||||
const isGlobalConfigFileExist = (0, import_fs.existsSync)(configPath);
|
const isGlobalConfigFileExist = (0, import_fs.existsSync)(configPath);
|
||||||
if (!isGlobalConfigFileExist)
|
if (!isGlobalConfigFileExist)
|
||||||
globalConfig = initGlobalConfig();
|
globalConfig = initGlobalConfig(configPath);
|
||||||
else {
|
else {
|
||||||
const configFile = (0, import_fs.readFileSync)(configPath, "utf8");
|
const configFile = (0, import_fs.readFileSync)(configPath, "utf8");
|
||||||
globalConfig = (0, import_ini.parse)(configFile);
|
globalConfig = (0, import_ini.parse)(configFile);
|
||||||
}
|
}
|
||||||
const mergeObjects = (main, fallback) => Object.keys(CONFIG_KEYS).reduce((acc, key) => {
|
return globalConfig;
|
||||||
|
};
|
||||||
|
var mergeConfigs = (main, fallback) => Object.keys(CONFIG_KEYS).reduce((acc, key) => {
|
||||||
acc[key] = parseEnvVarValue(main[key] ?? fallback[key]);
|
acc[key] = parseEnvVarValue(main[key] ?? fallback[key]);
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
const config6 = mergeObjects(envConfig, globalConfig);
|
var getConfig = ({
|
||||||
|
envPath = defaultEnvPath,
|
||||||
|
globalPath = defaultConfigPath
|
||||||
|
} = {}) => {
|
||||||
|
const envConfig = getEnvConfig(envPath);
|
||||||
|
const globalConfig = getGlobalConfig(globalPath);
|
||||||
|
const config6 = mergeConfigs(envConfig, globalConfig);
|
||||||
return config6;
|
return config6;
|
||||||
};
|
};
|
||||||
var setConfig = (keyValues, configPath = defaultConfigPath) => {
|
var setConfig = (keyValues, globalConfigPath = defaultConfigPath) => {
|
||||||
const config6 = getConfig();
|
const config6 = getConfig({
|
||||||
|
globalPath: globalConfigPath
|
||||||
|
});
|
||||||
for (let [key, value] of keyValues) {
|
for (let [key, value] of keyValues) {
|
||||||
if (!configValidators.hasOwnProperty(key)) {
|
if (!configValidators.hasOwnProperty(key)) {
|
||||||
const supportedKeys = Object.keys(configValidators).join("\n");
|
const supportedKeys = Object.keys(configValidators).join("\n");
|
||||||
@@ -46956,8 +46945,7 @@ For more help refer to our docs: https://github.com/di-sukharev/opencommit`
|
|||||||
);
|
);
|
||||||
config6[key] = validValue;
|
config6[key] = validValue;
|
||||||
}
|
}
|
||||||
(0, import_fs.writeFileSync)(configPath, (0, import_ini.stringify)(config6), "utf8");
|
(0, import_fs.writeFileSync)(globalConfigPath, (0, import_ini.stringify)(config6), "utf8");
|
||||||
assertConfigsAreValid(config6);
|
|
||||||
ce(`${source_default.green("\u2714")} config successfully set`);
|
ce(`${source_default.green("\u2714")} config successfully set`);
|
||||||
};
|
};
|
||||||
var configCommand = G2(
|
var configCommand = G2(
|
||||||
@@ -61212,7 +61200,7 @@ var OpenAiEngine = class {
|
|||||||
function getEngine() {
|
function getEngine() {
|
||||||
const config6 = getConfig();
|
const config6 = getConfig();
|
||||||
const provider = config6.OCO_AI_PROVIDER;
|
const provider = config6.OCO_AI_PROVIDER;
|
||||||
const DEFAULT_CONFIG = {
|
const DEFAULT_CONFIG2 = {
|
||||||
model: config6.OCO_MODEL,
|
model: config6.OCO_MODEL,
|
||||||
maxTokensOutput: config6.OCO_TOKENS_MAX_OUTPUT,
|
maxTokensOutput: config6.OCO_TOKENS_MAX_OUTPUT,
|
||||||
maxTokensInput: config6.OCO_TOKENS_MAX_INPUT,
|
maxTokensInput: config6.OCO_TOKENS_MAX_INPUT,
|
||||||
@@ -61221,37 +61209,37 @@ function getEngine() {
|
|||||||
switch (provider) {
|
switch (provider) {
|
||||||
case "ollama" /* OLLAMA */:
|
case "ollama" /* OLLAMA */:
|
||||||
return new OllamaAi({
|
return new OllamaAi({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
apiKey: "",
|
apiKey: "",
|
||||||
baseURL: config6.OCO_OLLAMA_API_URL
|
baseURL: config6.OCO_OLLAMA_API_URL
|
||||||
});
|
});
|
||||||
case "anthropic" /* ANTHROPIC */:
|
case "anthropic" /* ANTHROPIC */:
|
||||||
return new AnthropicEngine({
|
return new AnthropicEngine({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
apiKey: config6.OCO_ANTHROPIC_API_KEY
|
apiKey: config6.OCO_ANTHROPIC_API_KEY
|
||||||
});
|
});
|
||||||
case "test" /* TEST */:
|
case "test" /* TEST */:
|
||||||
return new TestAi(config6.OCO_TEST_MOCK_TYPE);
|
return new TestAi(config6.OCO_TEST_MOCK_TYPE);
|
||||||
case "gemini" /* GEMINI */:
|
case "gemini" /* GEMINI */:
|
||||||
return new Gemini({
|
return new Gemini({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
apiKey: config6.OCO_GEMINI_API_KEY,
|
apiKey: config6.OCO_GEMINI_API_KEY,
|
||||||
baseURL: config6.OCO_GEMINI_BASE_PATH
|
baseURL: config6.OCO_GEMINI_BASE_PATH
|
||||||
});
|
});
|
||||||
case "azure" /* AZURE */:
|
case "azure" /* AZURE */:
|
||||||
return new AzureEngine({
|
return new AzureEngine({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
apiKey: config6.OCO_AZURE_API_KEY
|
apiKey: config6.OCO_AZURE_API_KEY
|
||||||
});
|
});
|
||||||
case "flowise" /* FLOWISE */:
|
case "flowise" /* FLOWISE */:
|
||||||
return new FlowiseAi({
|
return new FlowiseAi({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
baseURL: config6.OCO_FLOWISE_ENDPOINT || DEFAULT_CONFIG.baseURL,
|
baseURL: config6.OCO_FLOWISE_ENDPOINT || DEFAULT_CONFIG2.baseURL,
|
||||||
apiKey: config6.OCO_FLOWISE_API_KEY
|
apiKey: config6.OCO_FLOWISE_API_KEY
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
return new OpenAiEngine({
|
return new OpenAiEngine({
|
||||||
...DEFAULT_CONFIG,
|
...DEFAULT_CONFIG2,
|
||||||
apiKey: config6.OCO_OPENAI_API_KEY
|
apiKey: config6.OCO_OPENAI_API_KEY
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ const generateCommitMessageFromGitDiff = async ({
|
|||||||
skipCommitConfirmation = false
|
skipCommitConfirmation = false
|
||||||
}: GenerateCommitMessageFromGitDiffParams): Promise<void> => {
|
}: GenerateCommitMessageFromGitDiffParams): Promise<void> => {
|
||||||
await assertGitRepo();
|
await assertGitRepo();
|
||||||
const commitSpinner = spinner();
|
const commitGenerationSpinner = spinner();
|
||||||
commitSpinner.start('Generating the commit message');
|
commitGenerationSpinner.start('Generating the commit message');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let commitMessage = await generateCommitMessageByDiff(
|
let commitMessage = await generateCommitMessageByDiff(
|
||||||
@@ -73,7 +73,7 @@ const generateCommitMessageFromGitDiff = async ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
commitSpinner.stop('📝 Commit message generated');
|
commitGenerationSpinner.stop('📝 Commit message generated');
|
||||||
|
|
||||||
outro(
|
outro(
|
||||||
`Generated commit message:
|
`Generated commit message:
|
||||||
@@ -88,15 +88,20 @@ ${chalk.grey('——————————————————')}`
|
|||||||
message: 'Confirm the commit message?'
|
message: 'Confirm the commit message?'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (isCommitConfirmedByUser && !isCancel(isCommitConfirmedByUser)) {
|
if (isCancel(isCommitConfirmedByUser)) process.exit(1);
|
||||||
|
|
||||||
|
if (isCommitConfirmedByUser) {
|
||||||
|
const committingChangesSpinner = spinner();
|
||||||
|
committingChangesSpinner.start('Committing the changes');
|
||||||
const { stdout } = await execa('git', [
|
const { stdout } = await execa('git', [
|
||||||
'commit',
|
'commit',
|
||||||
'-m',
|
'-m',
|
||||||
commitMessage,
|
commitMessage,
|
||||||
...extraArgs
|
...extraArgs
|
||||||
]);
|
]);
|
||||||
|
committingChangesSpinner.stop(
|
||||||
outro(`${chalk.green('✔')} Successfully committed`);
|
`${chalk.green('✔')} Successfully committed`
|
||||||
|
);
|
||||||
|
|
||||||
outro(stdout);
|
outro(stdout);
|
||||||
|
|
||||||
@@ -113,7 +118,9 @@ ${chalk.grey('——————————————————')}`
|
|||||||
message: 'Do you want to run `git push`?'
|
message: 'Do you want to run `git push`?'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isPushConfirmedByUser && !isCancel(isPushConfirmedByUser)) {
|
if (isCancel(isPushConfirmedByUser)) process.exit(1);
|
||||||
|
|
||||||
|
if (isPushConfirmedByUser) {
|
||||||
const pushSpinner = spinner();
|
const pushSpinner = spinner();
|
||||||
|
|
||||||
pushSpinner.start(`Running 'git push ${remotes[0]}'`);
|
pushSpinner.start(`Running 'git push ${remotes[0]}'`);
|
||||||
@@ -141,7 +148,8 @@ ${chalk.grey('——————————————————')}`
|
|||||||
options: remotes.map((remote) => ({ value: remote, label: remote }))
|
options: remotes.map((remote) => ({ value: remote, label: remote }))
|
||||||
})) as string;
|
})) as string;
|
||||||
|
|
||||||
if (!isCancel(selectedRemote)) {
|
if (isCancel(selectedRemote)) process.exit(1);
|
||||||
|
|
||||||
const pushSpinner = spinner();
|
const pushSpinner = spinner();
|
||||||
|
|
||||||
pushSpinner.start(`Running 'git push ${selectedRemote}'`);
|
pushSpinner.start(`Running 'git push ${selectedRemote}'`);
|
||||||
@@ -155,14 +163,15 @@ ${chalk.grey('——————————————————')}`
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (stdout) outro(stdout);
|
if (stdout) outro(stdout);
|
||||||
} else outro(`${chalk.gray('✖')} process cancelled`);
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
if (!isCommitConfirmedByUser && !isCancel(isCommitConfirmedByUser)) {
|
|
||||||
const regenerateMessage = await confirm({
|
const regenerateMessage = await confirm({
|
||||||
message: 'Do you want to regenerate the message?'
|
message: 'Do you want to regenerate the message?'
|
||||||
});
|
});
|
||||||
if (regenerateMessage && !isCancel(isCommitConfirmedByUser)) {
|
|
||||||
|
if (isCancel(regenerateMessage)) process.exit(1);
|
||||||
|
|
||||||
|
if (regenerateMessage) {
|
||||||
await generateCommitMessageFromGitDiff({
|
await generateCommitMessageFromGitDiff({
|
||||||
diff,
|
diff,
|
||||||
extraArgs,
|
extraArgs,
|
||||||
@@ -171,7 +180,7 @@ ${chalk.grey('——————————————————')}`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
commitSpinner.stop('📝 Commit message generated');
|
commitGenerationSpinner.stop('📝 Commit message generated');
|
||||||
|
|
||||||
const err = error as Error;
|
const err = error as Error;
|
||||||
outro(`${chalk.red('✖')} ${err?.message || err}`);
|
outro(`${chalk.red('✖')} ${err?.message || err}`);
|
||||||
@@ -219,10 +228,9 @@ export async function commit(
|
|||||||
message: 'Do you want to stage all files and generate commit message?'
|
message: 'Do you want to stage all files and generate commit message?'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (isCancel(isStageAllAndCommitConfirmedByUser)) process.exit(1);
|
||||||
isStageAllAndCommitConfirmedByUser &&
|
|
||||||
!isCancel(isStageAllAndCommitConfirmedByUser)
|
if (isStageAllAndCommitConfirmedByUser) {
|
||||||
) {
|
|
||||||
await commit(extraArgs, true, fullGitMojiSpec);
|
await commit(extraArgs, true, fullGitMojiSpec);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -422,8 +422,7 @@ enum OCO_PROMPT_MODULE_ENUM {
|
|||||||
COMMITLINT = '@commitlint'
|
COMMITLINT = '@commitlint'
|
||||||
}
|
}
|
||||||
|
|
||||||
const initGlobalConfig = () => {
|
export const DEFAULT_CONFIG = {
|
||||||
const defaultConfig = {
|
|
||||||
OCO_TOKENS_MAX_INPUT: DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_INPUT,
|
OCO_TOKENS_MAX_INPUT: DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_INPUT,
|
||||||
OCO_TOKENS_MAX_OUTPUT: DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_OUTPUT,
|
OCO_TOKENS_MAX_OUTPUT: DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_OUTPUT,
|
||||||
OCO_DESCRIPTION: false,
|
OCO_DESCRIPTION: false,
|
||||||
@@ -437,10 +436,11 @@ const initGlobalConfig = () => {
|
|||||||
OCO_TEST_MOCK_TYPE: 'commit-message',
|
OCO_TEST_MOCK_TYPE: 'commit-message',
|
||||||
OCO_FLOWISE_ENDPOINT: ':',
|
OCO_FLOWISE_ENDPOINT: ':',
|
||||||
OCO_GITPUSH: true // todo: deprecate
|
OCO_GITPUSH: true // todo: deprecate
|
||||||
};
|
};
|
||||||
|
|
||||||
writeFileSync(defaultConfigPath, iniStringify(defaultConfig), 'utf8');
|
const initGlobalConfig = (configPath: string = defaultConfigPath) => {
|
||||||
return defaultConfig;
|
writeFileSync(configPath, iniStringify(DEFAULT_CONFIG), 'utf8');
|
||||||
|
return DEFAULT_CONFIG;
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseEnvVarValue = (value?: any) => {
|
const parseEnvVarValue = (value?: any) => {
|
||||||
@@ -451,16 +451,10 @@ const parseEnvVarValue = (value?: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getConfig = ({
|
const getEnvConfig = (envPath: string) => {
|
||||||
configPath = defaultConfigPath,
|
|
||||||
envPath = defaultEnvPath
|
|
||||||
}: {
|
|
||||||
configPath?: string;
|
|
||||||
envPath?: string;
|
|
||||||
} = {}): ConfigType => {
|
|
||||||
dotenv.config({ path: envPath });
|
dotenv.config({ path: envPath });
|
||||||
|
|
||||||
const envConfig = {
|
return {
|
||||||
OCO_MODEL: process.env.OCO_MODEL,
|
OCO_MODEL: process.env.OCO_MODEL,
|
||||||
|
|
||||||
OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY,
|
OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY,
|
||||||
@@ -491,33 +485,59 @@ export const getConfig = ({
|
|||||||
|
|
||||||
OCO_GITPUSH: parseEnvVarValue(process.env.OCO_GITPUSH) // todo: deprecate
|
OCO_GITPUSH: parseEnvVarValue(process.env.OCO_GITPUSH) // todo: deprecate
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getGlobalConfig = (configPath: string) => {
|
||||||
let globalConfig: ConfigType;
|
let globalConfig: ConfigType;
|
||||||
|
|
||||||
const isGlobalConfigFileExist = existsSync(configPath);
|
const isGlobalConfigFileExist = existsSync(configPath);
|
||||||
if (!isGlobalConfigFileExist) globalConfig = initGlobalConfig();
|
if (!isGlobalConfigFileExist) globalConfig = initGlobalConfig(configPath);
|
||||||
else {
|
else {
|
||||||
const configFile = readFileSync(configPath, 'utf8');
|
const configFile = readFileSync(configPath, 'utf8');
|
||||||
globalConfig = iniParse(configFile) as ConfigType;
|
globalConfig = iniParse(configFile) as ConfigType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mergeObjects = (main: Partial<ConfigType>, fallback: ConfigType) =>
|
return globalConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges two configs.
|
||||||
|
* Env config takes precedence over global ~/.opencommit config file
|
||||||
|
* @param main - env config
|
||||||
|
* @param fallback - global ~/.opencommit config file
|
||||||
|
* @returns merged config
|
||||||
|
*/
|
||||||
|
const mergeConfigs = (main: Partial<ConfigType>, fallback: ConfigType) =>
|
||||||
Object.keys(CONFIG_KEYS).reduce((acc, key) => {
|
Object.keys(CONFIG_KEYS).reduce((acc, key) => {
|
||||||
acc[key] = parseEnvVarValue(main[key] ?? fallback[key]);
|
acc[key] = parseEnvVarValue(main[key] ?? fallback[key]);
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as ConfigType);
|
}, {} as ConfigType);
|
||||||
|
|
||||||
// env config takes precedence over global ~/.opencommit config file
|
interface GetConfigOptions {
|
||||||
const config = mergeObjects(envConfig, globalConfig);
|
globalPath?: string;
|
||||||
|
envPath?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getConfig = ({
|
||||||
|
envPath = defaultEnvPath,
|
||||||
|
globalPath = defaultConfigPath
|
||||||
|
}: GetConfigOptions = {}): ConfigType => {
|
||||||
|
const envConfig = getEnvConfig(envPath);
|
||||||
|
const globalConfig = getGlobalConfig(globalPath);
|
||||||
|
|
||||||
|
const config = mergeConfigs(envConfig, globalConfig);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setConfig = (
|
export const setConfig = (
|
||||||
keyValues: [key: string, value: string][],
|
keyValues: [key: string, value: string][],
|
||||||
configPath: string = defaultConfigPath
|
globalConfigPath: string = defaultConfigPath
|
||||||
) => {
|
) => {
|
||||||
const config = getConfig();
|
const config = getConfig({
|
||||||
|
globalPath: globalConfigPath
|
||||||
|
});
|
||||||
|
|
||||||
for (let [key, value] of keyValues) {
|
for (let [key, value] of keyValues) {
|
||||||
if (!configValidators.hasOwnProperty(key)) {
|
if (!configValidators.hasOwnProperty(key)) {
|
||||||
@@ -543,9 +563,7 @@ export const setConfig = (
|
|||||||
config[key] = validValue;
|
config[key] = validValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeFileSync(configPath, iniStringify(config), 'utf8');
|
writeFileSync(globalConfigPath, iniStringify(config), 'utf8');
|
||||||
|
|
||||||
assertConfigsAreValid(config);
|
|
||||||
|
|
||||||
outro(`${chalk.green('✔')} config successfully set`);
|
outro(`${chalk.green('✔')} config successfully set`);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
import { getConfig } from '../../src/commands/config';
|
import { existsSync, readFileSync, rmSync } from 'fs';
|
||||||
|
import {
|
||||||
|
DEFAULT_CONFIG,
|
||||||
|
getConfig,
|
||||||
|
setConfig
|
||||||
|
} from '../../src/commands/config';
|
||||||
import { prepareFile } from './utils';
|
import { prepareFile } from './utils';
|
||||||
|
import { dirname } from 'path';
|
||||||
|
|
||||||
describe('getConfig', () => {
|
describe('config', () => {
|
||||||
const originalEnv = { ...process.env };
|
const originalEnv = { ...process.env };
|
||||||
let globalConfigFile: { filePath: string; cleanup: () => Promise<void> };
|
let globalConfigFile: { filePath: string; cleanup: () => Promise<void> };
|
||||||
let localEnvFile: { filePath: string; cleanup: () => Promise<void> };
|
let envConfigFile: { filePath: string; cleanup: () => Promise<void> };
|
||||||
|
|
||||||
function resetEnv(env: NodeJS.ProcessEnv) {
|
function resetEnv(env: NodeJS.ProcessEnv) {
|
||||||
Object.keys(process.env).forEach((key) => {
|
Object.keys(process.env).forEach((key) => {
|
||||||
@@ -19,7 +25,12 @@ describe('getConfig', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
resetEnv(originalEnv);
|
resetEnv(originalEnv);
|
||||||
if (globalConfigFile) await globalConfigFile.cleanup();
|
if (globalConfigFile) await globalConfigFile.cleanup();
|
||||||
if (localEnvFile) await localEnvFile.cleanup();
|
if (envConfigFile) await envConfigFile.cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
if (globalConfigFile) await globalConfigFile.cleanup();
|
||||||
|
if (envConfigFile) await envConfigFile.cleanup();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
@@ -36,6 +47,7 @@ describe('getConfig', () => {
|
|||||||
return await prepareFile(fileName, fileContent);
|
return await prepareFile(fileName, fileContent);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
describe('getConfig', () => {
|
||||||
it('should prioritize local .env over global .opencommit config', async () => {
|
it('should prioritize local .env over global .opencommit config', async () => {
|
||||||
globalConfigFile = await generateConfig('.opencommit', {
|
globalConfigFile = await generateConfig('.opencommit', {
|
||||||
OCO_OPENAI_API_KEY: 'global-key',
|
OCO_OPENAI_API_KEY: 'global-key',
|
||||||
@@ -43,15 +55,15 @@ describe('getConfig', () => {
|
|||||||
OCO_LANGUAGE: 'en'
|
OCO_LANGUAGE: 'en'
|
||||||
});
|
});
|
||||||
|
|
||||||
localEnvFile = await generateConfig('.env', {
|
envConfigFile = await generateConfig('.env', {
|
||||||
OCO_OPENAI_API_KEY: 'local-key',
|
OCO_OPENAI_API_KEY: 'local-key',
|
||||||
OCO_ANTHROPIC_API_KEY: 'local-anthropic-key',
|
OCO_ANTHROPIC_API_KEY: 'local-anthropic-key',
|
||||||
OCO_LANGUAGE: 'fr'
|
OCO_LANGUAGE: 'fr'
|
||||||
});
|
});
|
||||||
|
|
||||||
const config = getConfig({
|
const config = getConfig({
|
||||||
configPath: globalConfigFile.filePath,
|
globalPath: globalConfigFile.filePath,
|
||||||
envPath: localEnvFile.filePath
|
envPath: envConfigFile.filePath
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(config).not.toEqual(null);
|
expect(config).not.toEqual(null);
|
||||||
@@ -69,13 +81,13 @@ describe('getConfig', () => {
|
|||||||
OCO_DESCRIPTION: 'true'
|
OCO_DESCRIPTION: 'true'
|
||||||
});
|
});
|
||||||
|
|
||||||
localEnvFile = await generateConfig('.env', {
|
envConfigFile = await generateConfig('.env', {
|
||||||
OCO_ANTHROPIC_API_KEY: 'local-anthropic-key'
|
OCO_ANTHROPIC_API_KEY: 'local-anthropic-key'
|
||||||
});
|
});
|
||||||
|
|
||||||
const config = getConfig({
|
const config = getConfig({
|
||||||
configPath: globalConfigFile.filePath,
|
globalPath: globalConfigFile.filePath,
|
||||||
envPath: localEnvFile.filePath
|
envPath: envConfigFile.filePath
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(config).not.toEqual(null);
|
expect(config).not.toEqual(null);
|
||||||
@@ -93,14 +105,14 @@ describe('getConfig', () => {
|
|||||||
OCO_GITPUSH: 'true'
|
OCO_GITPUSH: 'true'
|
||||||
});
|
});
|
||||||
|
|
||||||
localEnvFile = await generateConfig('.env', {
|
envConfigFile = await generateConfig('.env', {
|
||||||
OCO_TOKENS_MAX_INPUT: '8192',
|
OCO_TOKENS_MAX_INPUT: '8192',
|
||||||
OCO_ONE_LINE_COMMIT: 'false'
|
OCO_ONE_LINE_COMMIT: 'false'
|
||||||
});
|
});
|
||||||
|
|
||||||
const config = getConfig({
|
const config = getConfig({
|
||||||
configPath: globalConfigFile.filePath,
|
globalPath: globalConfigFile.filePath,
|
||||||
envPath: localEnvFile.filePath
|
envPath: envConfigFile.filePath
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(config).not.toEqual(null);
|
expect(config).not.toEqual(null);
|
||||||
@@ -117,11 +129,11 @@ describe('getConfig', () => {
|
|||||||
OCO_LANGUAGE: 'es'
|
OCO_LANGUAGE: 'es'
|
||||||
});
|
});
|
||||||
|
|
||||||
localEnvFile = await generateConfig('.env', {});
|
envConfigFile = await generateConfig('.env', {});
|
||||||
|
|
||||||
const config = getConfig({
|
const config = getConfig({
|
||||||
configPath: globalConfigFile.filePath,
|
globalPath: globalConfigFile.filePath,
|
||||||
envPath: localEnvFile.filePath
|
envPath: envConfigFile.filePath
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(config).not.toEqual(null);
|
expect(config).not.toEqual(null);
|
||||||
@@ -137,14 +149,147 @@ describe('getConfig', () => {
|
|||||||
OCO_LANGUAGE: 'es'
|
OCO_LANGUAGE: 'es'
|
||||||
});
|
});
|
||||||
|
|
||||||
localEnvFile = await generateConfig('.env', { OCO_OPENAI_API_KEY: 'null' });
|
envConfigFile = await generateConfig('.env', {
|
||||||
|
OCO_OPENAI_API_KEY: 'null'
|
||||||
|
});
|
||||||
|
|
||||||
const config = getConfig({
|
const config = getConfig({
|
||||||
configPath: globalConfigFile.filePath,
|
globalPath: globalConfigFile.filePath,
|
||||||
envPath: localEnvFile.filePath
|
envPath: envConfigFile.filePath
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(config).not.toEqual(null);
|
expect(config).not.toEqual(null);
|
||||||
expect(config.OCO_OPENAI_API_KEY).toEqual(null);
|
expect(config.OCO_OPENAI_API_KEY).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle empty global config', async () => {
|
||||||
|
globalConfigFile = await generateConfig('.opencommit', {});
|
||||||
|
envConfigFile = await generateConfig('.env', {});
|
||||||
|
|
||||||
|
const config = getConfig({
|
||||||
|
globalPath: globalConfigFile.filePath,
|
||||||
|
envPath: envConfigFile.filePath
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(config).not.toEqual(null);
|
||||||
|
expect(config.OCO_OPENAI_API_KEY).toEqual(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setConfig', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
// we create and delete the file to have the parent directory, but not the file, to test the creation of the file
|
||||||
|
globalConfigFile = await generateConfig('.opencommit', {});
|
||||||
|
rmSync(globalConfigFile.filePath);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create .opencommit file with DEFAULT CONFIG if it does not exist on first setConfig run', async () => {
|
||||||
|
const isGlobalConfigFileExist = existsSync(globalConfigFile.filePath);
|
||||||
|
expect(isGlobalConfigFileExist).toBe(false);
|
||||||
|
|
||||||
|
await setConfig(
|
||||||
|
[['OCO_OPENAI_API_KEY', 'persisted-key_1']],
|
||||||
|
globalConfigFile.filePath
|
||||||
|
);
|
||||||
|
|
||||||
|
const fileContent = readFileSync(globalConfigFile.filePath, 'utf8');
|
||||||
|
expect(fileContent).toContain('OCO_OPENAI_API_KEY=persisted-key_1');
|
||||||
|
Object.entries(DEFAULT_CONFIG).forEach(([key, value]) => {
|
||||||
|
expect(fileContent).toContain(`${key}=${value}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set new config values', async () => {
|
||||||
|
globalConfigFile = await generateConfig('.opencommit', {});
|
||||||
|
await setConfig(
|
||||||
|
[
|
||||||
|
['OCO_OPENAI_API_KEY', 'new-key'],
|
||||||
|
['OCO_MODEL', 'gpt-4']
|
||||||
|
],
|
||||||
|
globalConfigFile.filePath
|
||||||
|
);
|
||||||
|
|
||||||
|
const config = getConfig({ globalPath: globalConfigFile.filePath });
|
||||||
|
expect(config.OCO_OPENAI_API_KEY).toEqual('new-key');
|
||||||
|
expect(config.OCO_MODEL).toEqual('gpt-4');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update existing config values', async () => {
|
||||||
|
globalConfigFile = await generateConfig('.opencommit', {
|
||||||
|
OCO_OPENAI_API_KEY: 'initial-key'
|
||||||
|
});
|
||||||
|
await setConfig(
|
||||||
|
[['OCO_OPENAI_API_KEY', 'updated-key']],
|
||||||
|
globalConfigFile.filePath
|
||||||
|
);
|
||||||
|
|
||||||
|
const config = getConfig({ globalPath: globalConfigFile.filePath });
|
||||||
|
expect(config.OCO_OPENAI_API_KEY).toEqual('updated-key');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle boolean and numeric values correctly', async () => {
|
||||||
|
globalConfigFile = await generateConfig('.opencommit', {});
|
||||||
|
await setConfig(
|
||||||
|
[
|
||||||
|
['OCO_TOKENS_MAX_INPUT', '8192'],
|
||||||
|
['OCO_DESCRIPTION', 'true'],
|
||||||
|
['OCO_ONE_LINE_COMMIT', 'false']
|
||||||
|
],
|
||||||
|
globalConfigFile.filePath
|
||||||
|
);
|
||||||
|
|
||||||
|
const config = getConfig({ globalPath: globalConfigFile.filePath });
|
||||||
|
expect(config.OCO_TOKENS_MAX_INPUT).toEqual(8192);
|
||||||
|
expect(config.OCO_DESCRIPTION).toEqual(true);
|
||||||
|
expect(config.OCO_ONE_LINE_COMMIT).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error for unsupported config keys', async () => {
|
||||||
|
globalConfigFile = await generateConfig('.opencommit', {});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await setConfig(
|
||||||
|
[['UNSUPPORTED_KEY', 'value']],
|
||||||
|
globalConfigFile.filePath
|
||||||
|
);
|
||||||
|
throw new Error('NEVER_REACHED');
|
||||||
|
} catch (error) {
|
||||||
|
expect(error.message).toContain(
|
||||||
|
'Unsupported config key: UNSUPPORTED_KEY'
|
||||||
|
);
|
||||||
|
expect(error.message).not.toContain('NEVER_REACHED');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should persist changes to the config file', async () => {
|
||||||
|
const isGlobalConfigFileExist = existsSync(globalConfigFile.filePath);
|
||||||
|
expect(isGlobalConfigFileExist).toBe(false);
|
||||||
|
|
||||||
|
await setConfig(
|
||||||
|
[['OCO_OPENAI_API_KEY', 'persisted-key']],
|
||||||
|
globalConfigFile.filePath
|
||||||
|
);
|
||||||
|
|
||||||
|
const fileContent = readFileSync(globalConfigFile.filePath, 'utf8');
|
||||||
|
expect(fileContent).toContain('OCO_OPENAI_API_KEY=persisted-key');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set multiple configs in a row and keep the changes', async () => {
|
||||||
|
const isGlobalConfigFileExist = existsSync(globalConfigFile.filePath);
|
||||||
|
expect(isGlobalConfigFileExist).toBe(false);
|
||||||
|
|
||||||
|
await setConfig(
|
||||||
|
[['OCO_OPENAI_API_KEY', 'persisted-key']],
|
||||||
|
globalConfigFile.filePath
|
||||||
|
);
|
||||||
|
|
||||||
|
const fileContent1 = readFileSync(globalConfigFile.filePath, 'utf8');
|
||||||
|
expect(fileContent1).toContain('OCO_OPENAI_API_KEY=persisted-key');
|
||||||
|
|
||||||
|
await setConfig([['OCO_MODEL', 'gpt-4']], globalConfigFile.filePath);
|
||||||
|
|
||||||
|
const fileContent2 = readFileSync(globalConfigFile.filePath, 'utf8');
|
||||||
|
expect(fileContent2).toContain('OCO_MODEL=gpt-4');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import path from 'path';
|
import { existsSync, mkdtemp, rm, writeFile } from 'fs';
|
||||||
import { mkdtemp, rm, writeFile } from 'fs';
|
|
||||||
import { promisify } from 'util';
|
|
||||||
import { tmpdir } from 'os';
|
import { tmpdir } from 'os';
|
||||||
|
import path from 'path';
|
||||||
|
import { promisify } from 'util';
|
||||||
const fsMakeTempDir = promisify(mkdtemp);
|
const fsMakeTempDir = promisify(mkdtemp);
|
||||||
const fsRemove = promisify(rm);
|
const fsRemove = promisify(rm);
|
||||||
const fsWriteFile = promisify(writeFile);
|
const fsWriteFile = promisify(writeFile);
|
||||||
@@ -20,7 +20,9 @@ export async function prepareFile(
|
|||||||
const filePath = path.resolve(tempDir, fileName);
|
const filePath = path.resolve(tempDir, fileName);
|
||||||
await fsWriteFile(filePath, content);
|
await fsWriteFile(filePath, content);
|
||||||
const cleanup = async () => {
|
const cleanup = async () => {
|
||||||
return fsRemove(tempDir, { recursive: true });
|
if (existsSync(tempDir)) {
|
||||||
|
await fsRemove(tempDir, { recursive: true });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -21,9 +21,7 @@
|
|||||||
|
|
||||||
"skipLibCheck": true
|
"skipLibCheck": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["test/jest-setup.ts"],
|
||||||
"test/jest-setup.ts"
|
|
||||||
],
|
|
||||||
"exclude": ["node_modules"],
|
"exclude": ["node_modules"],
|
||||||
"ts-node": {
|
"ts-node": {
|
||||||
"esm": true,
|
"esm": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user