@fractary/codex-cli 0.10.26 → 0.10.28
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/dist/cli.cjs +44 -8
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +45 -9
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as path4 from 'path';
|
|
3
3
|
import { dirname, join } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
-
import { createConfigManager, resolveOrganization, validateNameFormat, formatBytes, createHealthChecker, readCodexConfig, formatDuration, createCodexClient, ValidationError, PermissionDeniedError, ConfigurationError, CodexError, CodexClient } from '@fractary/codex';
|
|
5
|
+
import { createConfigManager, resolveOrganization, validateNameFormat, formatBytes, createHealthChecker, readCodexConfig, calculateContentHash, formatDuration, createCodexClient, ValidationError, PermissionDeniedError, ConfigurationError, CodexError, CodexClient } from '@fractary/codex';
|
|
6
6
|
import * as os from 'os';
|
|
7
7
|
import * as fs2 from 'fs/promises';
|
|
8
8
|
import { spawn } from 'child_process';
|
|
@@ -118,10 +118,13 @@ async function isValidGitRepo(repoPath) {
|
|
|
118
118
|
return false;
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
-
function getCodexRepoUrl(config) {
|
|
121
|
+
function getCodexRepoUrl(config, token) {
|
|
122
122
|
const codexRepo = config.codex_repo || "codex";
|
|
123
123
|
validateGitHubName(config.organization, "organization");
|
|
124
124
|
validateGitHubName(codexRepo, "repository");
|
|
125
|
+
if (token) {
|
|
126
|
+
return `https://x-access-token:${encodeURIComponent(token)}@github.com/${config.organization}/${codexRepo}.git`;
|
|
127
|
+
}
|
|
125
128
|
return `https://github.com/${config.organization}/${codexRepo}.git`;
|
|
126
129
|
}
|
|
127
130
|
async function execGit(repoPath, args) {
|
|
@@ -185,6 +188,10 @@ async function ensureCodexCloned(config, options) {
|
|
|
185
188
|
const branch = options?.branch || "main";
|
|
186
189
|
if (await isValidGitRepo(tempPath) && !options?.force) {
|
|
187
190
|
try {
|
|
191
|
+
if (options?.token) {
|
|
192
|
+
const repoUrl2 = getCodexRepoUrl(config, options.token);
|
|
193
|
+
await execGit(tempPath, ["remote", "set-url", "origin", repoUrl2]);
|
|
194
|
+
}
|
|
188
195
|
await gitFetch(tempPath, branch);
|
|
189
196
|
await gitCheckout(tempPath, branch);
|
|
190
197
|
await gitPull(tempPath);
|
|
@@ -195,7 +202,7 @@ async function ensureCodexCloned(config, options) {
|
|
|
195
202
|
await fs2.rm(tempPath, { recursive: true, force: true });
|
|
196
203
|
}
|
|
197
204
|
}
|
|
198
|
-
const repoUrl = getCodexRepoUrl(config);
|
|
205
|
+
const repoUrl = getCodexRepoUrl(config, options?.token);
|
|
199
206
|
try {
|
|
200
207
|
await fs2.rm(tempPath, { recursive: true, force: true });
|
|
201
208
|
} catch (error) {
|
|
@@ -945,6 +952,23 @@ function syncCommand() {
|
|
|
945
952
|
const cmd = new Command("sync");
|
|
946
953
|
cmd.description("Sync single project with codex repository").argument("[name]", "Project name (auto-detected if not provided)").option("--env <env>", "Target environment (dev/test/staging/prod)", "prod").option("--dry-run", "Show what would sync without executing").option("--direction <dir>", "Sync direction (to-codex/from-codex/bidirectional)", "bidirectional").option("--include <pattern>", "Include files matching pattern (can be used multiple times)", (val, prev) => prev.concat([val]), []).option("--exclude <pattern>", "Exclude files matching pattern (can be used multiple times)", (val, prev) => prev.concat([val]), []).option("--force", "Force sync without checking timestamps").option("--json", "Output as JSON").option("--work-id <id>", "GitHub issue number or URL to scope sync to").action(async (name, options) => {
|
|
947
954
|
try {
|
|
955
|
+
const envFilePath = path4.join(process.cwd(), ".fractary", "env", ".env");
|
|
956
|
+
try {
|
|
957
|
+
const { readFile } = await import('fs/promises');
|
|
958
|
+
const envContent = await readFile(envFilePath, "utf-8");
|
|
959
|
+
for (const line of envContent.split("\n")) {
|
|
960
|
+
const trimmed = line.trim();
|
|
961
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
962
|
+
const eqIdx = trimmed.indexOf("=");
|
|
963
|
+
if (eqIdx === -1) continue;
|
|
964
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
965
|
+
const val = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
|
|
966
|
+
if (key && !process.env[key]) {
|
|
967
|
+
process.env[key] = val;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
} catch {
|
|
971
|
+
}
|
|
948
972
|
const configPath = path4.join(process.cwd(), ".fractary", "config.yaml");
|
|
949
973
|
let config;
|
|
950
974
|
try {
|
|
@@ -976,6 +1000,7 @@ function syncCommand() {
|
|
|
976
1000
|
}
|
|
977
1001
|
const direction = options.direction;
|
|
978
1002
|
const targetBranch = getEnvironmentBranch(config, options.env);
|
|
1003
|
+
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN || void 0;
|
|
979
1004
|
const localStorage = createLocalStorage({
|
|
980
1005
|
baseDir: process.cwd()
|
|
981
1006
|
});
|
|
@@ -1015,14 +1040,19 @@ function syncCommand() {
|
|
|
1015
1040
|
console.error(chalk10.yellow(`Warning: Invalid pattern "${pattern}": ${error.message}`));
|
|
1016
1041
|
}
|
|
1017
1042
|
}
|
|
1043
|
+
const fsModuleLocal = await import('fs/promises');
|
|
1018
1044
|
const targetFiles = await Promise.all(
|
|
1019
1045
|
Array.from(matchedFilePaths).map(async (filePath) => {
|
|
1020
1046
|
const fullPath = path4.join(sourceDir, filePath);
|
|
1021
|
-
const stats = await
|
|
1047
|
+
const [stats, content] = await Promise.all([
|
|
1048
|
+
fsModuleLocal.stat(fullPath),
|
|
1049
|
+
fsModuleLocal.readFile(fullPath)
|
|
1050
|
+
]);
|
|
1022
1051
|
return {
|
|
1023
1052
|
path: filePath,
|
|
1024
1053
|
size: stats.size,
|
|
1025
|
-
mtime: stats.mtimeMs
|
|
1054
|
+
mtime: stats.mtimeMs,
|
|
1055
|
+
hash: calculateContentHash(content)
|
|
1026
1056
|
};
|
|
1027
1057
|
})
|
|
1028
1058
|
);
|
|
@@ -1045,7 +1075,8 @@ function syncCommand() {
|
|
|
1045
1075
|
console.log(chalk10.blue("\u2139 Cloning/updating codex repository..."));
|
|
1046
1076
|
}
|
|
1047
1077
|
codexRepoPath = await ensureCodexCloned2(config, {
|
|
1048
|
-
branch: targetBranch
|
|
1078
|
+
branch: targetBranch,
|
|
1079
|
+
token
|
|
1049
1080
|
});
|
|
1050
1081
|
if (!options.json) {
|
|
1051
1082
|
console.log(chalk10.dim(` Codex cloned to: ${codexRepoPath}`));
|
|
@@ -1101,7 +1132,8 @@ function syncCommand() {
|
|
|
1101
1132
|
console.log(chalk10.blue("\u2139 Cloning/updating codex repository..."));
|
|
1102
1133
|
}
|
|
1103
1134
|
codexRepoPath = await ensureCodexCloned2(config, {
|
|
1104
|
-
branch: targetBranch
|
|
1135
|
+
branch: targetBranch,
|
|
1136
|
+
token
|
|
1105
1137
|
});
|
|
1106
1138
|
if (!options.json) {
|
|
1107
1139
|
console.log(chalk10.dim(` Codex cloned to: ${codexRepoPath}`));
|
|
@@ -1123,11 +1155,15 @@ function syncCommand() {
|
|
|
1123
1155
|
existingCodexFiles = await Promise.all(
|
|
1124
1156
|
codexGlobMatches.map(async (filePath) => {
|
|
1125
1157
|
const fullPath = path4.join(codexProjectDir, filePath);
|
|
1126
|
-
const stats = await
|
|
1158
|
+
const [stats, content] = await Promise.all([
|
|
1159
|
+
fsPromises.stat(fullPath),
|
|
1160
|
+
fsPromises.readFile(fullPath)
|
|
1161
|
+
]);
|
|
1127
1162
|
return {
|
|
1128
1163
|
path: filePath,
|
|
1129
1164
|
size: stats.size,
|
|
1130
|
-
mtime: stats.mtimeMs
|
|
1165
|
+
mtime: stats.mtimeMs,
|
|
1166
|
+
hash: calculateContentHash(content)
|
|
1131
1167
|
};
|
|
1132
1168
|
})
|
|
1133
1169
|
);
|