codiedev 0.7.7 → 0.7.9
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.js +0 -0
- package/dist/commands/doctor.js +7 -1
- package/dist/commands/shared.js +2 -0
- package/dist/connect.js +4 -0
- package/dist/hook.js +2 -0
- package/dist/mcp.js +0 -0
- package/dist/upgradeNudge.d.ts +7 -0
- package/dist/upgradeNudge.js +123 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +67 -0
- package/dist/versionCheck.d.ts +28 -0
- package/dist/versionCheck.js +49 -0
- package/package.json +3 -3
- package/dist/__tests__/connectFlow.test.d.ts +0 -1
- package/dist/__tests__/connectFlow.test.js +0 -33
- package/dist/__tests__/detection.test.d.ts +0 -1
- package/dist/__tests__/detection.test.js +0 -18
- package/dist/__tests__/prUrl.test.d.ts +0 -1
- package/dist/__tests__/prUrl.test.js +0 -50
- package/dist/__tests__/repoResolver.test.d.ts +0 -1
- package/dist/__tests__/repoResolver.test.js +0 -72
- package/dist/__tests__/scope.test.d.ts +0 -1
- package/dist/__tests__/scope.test.js +0 -24
package/dist/cli.js
CHANGED
|
File without changes
|
package/dist/commands/doctor.js
CHANGED
|
@@ -40,6 +40,8 @@ const os = __importStar(require("os"));
|
|
|
40
40
|
const child_process_1 = require("child_process");
|
|
41
41
|
const shared_1 = require("./shared");
|
|
42
42
|
const utils_1 = require("../utils");
|
|
43
|
+
const version_1 = require("../version");
|
|
44
|
+
const upgradeNudge_1 = require("../upgradeNudge");
|
|
43
45
|
const CLAUDE_SETTINGS_PATH = path.join(os.homedir(), ".claude", "settings.json");
|
|
44
46
|
const CLAUDE_INSTRUCTIONS_PATH = path.join(os.homedir(), ".claude", "CLAUDE.md");
|
|
45
47
|
const CODEX_HOOKS_PATH = path.join(os.homedir(), ".codex", "hooks.json");
|
|
@@ -151,6 +153,7 @@ function hasGlabCli() {
|
|
|
151
153
|
async function runDoctor(_args) {
|
|
152
154
|
const checks = [];
|
|
153
155
|
console.log("\nCodieDev doctor — checking your setup…\n");
|
|
156
|
+
await (0, upgradeNudge_1.maybePrintUpgradeNudge)();
|
|
154
157
|
// 1. Config file
|
|
155
158
|
const config = (0, utils_1.readConfig)();
|
|
156
159
|
if (!config) {
|
|
@@ -171,7 +174,10 @@ async function runDoctor(_args) {
|
|
|
171
174
|
try {
|
|
172
175
|
const res = await fetch(`${config.backendUrl}/api/cli/validateToken`, {
|
|
173
176
|
method: "POST",
|
|
174
|
-
headers: {
|
|
177
|
+
headers: {
|
|
178
|
+
"Content-Type": "application/json",
|
|
179
|
+
"X-Codiedev-Cli-Version": version_1.CLI_VERSION,
|
|
180
|
+
},
|
|
175
181
|
body: JSON.stringify({ token: config.token }),
|
|
176
182
|
});
|
|
177
183
|
if (res.ok) {
|
package/dist/commands/shared.js
CHANGED
|
@@ -40,6 +40,7 @@ exports.stripQuotes = stripQuotes;
|
|
|
40
40
|
const https = __importStar(require("https"));
|
|
41
41
|
const http = __importStar(require("http"));
|
|
42
42
|
const utils_1 = require("../utils");
|
|
43
|
+
const version_1 = require("../version");
|
|
43
44
|
/**
|
|
44
45
|
* Require a connected CodieDev config. Exits the process with a helpful
|
|
45
46
|
* message if the user hasn't run `codiedev connect` yet.
|
|
@@ -75,6 +76,7 @@ function apiRequest(method, path, options) {
|
|
|
75
76
|
method,
|
|
76
77
|
headers: {
|
|
77
78
|
Authorization: `Bearer ${options.config.token}`,
|
|
79
|
+
"X-Codiedev-Cli-Version": version_1.CLI_VERSION,
|
|
78
80
|
...(data
|
|
79
81
|
? {
|
|
80
82
|
"Content-Type": "application/json",
|
package/dist/connect.js
CHANGED
|
@@ -39,6 +39,8 @@ const https = __importStar(require("https"));
|
|
|
39
39
|
const http = __importStar(require("http"));
|
|
40
40
|
const utils_1 = require("./utils");
|
|
41
41
|
const connectFlow_1 = require("./connectFlow");
|
|
42
|
+
const version_1 = require("./version");
|
|
43
|
+
const upgradeNudge_1 = require("./upgradeNudge");
|
|
42
44
|
const BACKEND_URL = process.env.CODIEDEV_URL || "https://judicious-falcon-861.convex.site";
|
|
43
45
|
function prompt(rl, question) {
|
|
44
46
|
return new Promise((resolve) => {
|
|
@@ -59,6 +61,7 @@ function postJson(url, body) {
|
|
|
59
61
|
headers: {
|
|
60
62
|
"Content-Type": "application/json",
|
|
61
63
|
"Content-Length": Buffer.byteLength(data),
|
|
64
|
+
"X-Codiedev-Cli-Version": version_1.CLI_VERSION,
|
|
62
65
|
},
|
|
63
66
|
};
|
|
64
67
|
const lib = parsed.protocol === "https:" ? https : http;
|
|
@@ -95,6 +98,7 @@ async function runConnect(args = []) {
|
|
|
95
98
|
// engineer when he interpreted "no visible token" as "the old one is gone".
|
|
96
99
|
const force = args.includes("--force") || args.includes("-f");
|
|
97
100
|
console.log("\nWelcome to CodieDev CLI\n");
|
|
101
|
+
await (0, upgradeNudge_1.maybePrintUpgradeNudge)();
|
|
98
102
|
console.log("This will connect your coding agent to your CodieDev workspace and install");
|
|
99
103
|
console.log("the session capture hook for org-wide session sharing.\n");
|
|
100
104
|
const saved = (0, utils_1.readConfig)();
|
package/dist/hook.js
CHANGED
|
@@ -38,6 +38,7 @@ const fs = __importStar(require("fs"));
|
|
|
38
38
|
const https = __importStar(require("https"));
|
|
39
39
|
const http = __importStar(require("http"));
|
|
40
40
|
const utils_1 = require("./utils");
|
|
41
|
+
const version_1 = require("./version");
|
|
41
42
|
function postJson(url, body, bearerToken) {
|
|
42
43
|
return new Promise((resolve, reject) => {
|
|
43
44
|
const parsed = new URL(url);
|
|
@@ -51,6 +52,7 @@ function postJson(url, body, bearerToken) {
|
|
|
51
52
|
"Content-Type": "application/json",
|
|
52
53
|
"Content-Length": Buffer.byteLength(data),
|
|
53
54
|
Authorization: `Bearer ${bearerToken}`,
|
|
55
|
+
"X-Codiedev-Cli-Version": version_1.CLI_VERSION,
|
|
54
56
|
},
|
|
55
57
|
};
|
|
56
58
|
const lib = parsed.protocol === "https:" ? https : http;
|
package/dist/mcp.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fail-silent — never throws, never blocks on network. If the registry is
|
|
3
|
+
* unreachable or the cache is corrupt, the warning just doesn't print. The
|
|
4
|
+
* worst outcome is "user keeps running an old version" — same as before
|
|
5
|
+
* this feature existed.
|
|
6
|
+
*/
|
|
7
|
+
export declare function maybePrintUpgradeNudge(): Promise<void>;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Client-side "you're outdated" warning. Prints at the top of connect/doctor
|
|
3
|
+
// when there's a newer `codiedev` published on npm. Pure helpers tested in
|
|
4
|
+
// __tests__/versionCheck.test.ts; this module does the IO (registry fetch +
|
|
5
|
+
// disk cache) and is exercised by manual smoke.
|
|
6
|
+
//
|
|
7
|
+
// Cache lives at ~/.codiedev/.update-cache.json. 24h TTL — long enough that
|
|
8
|
+
// the registry isn't hit on every command, short enough that newly-published
|
|
9
|
+
// versions surface the day after release.
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.maybePrintUpgradeNudge = maybePrintUpgradeNudge;
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
const os = __importStar(require("os"));
|
|
48
|
+
const version_1 = require("./version");
|
|
49
|
+
const versionCheck_1 = require("./versionCheck");
|
|
50
|
+
const CACHE_PATH = path.join(os.homedir(), ".codiedev", ".update-cache.json");
|
|
51
|
+
const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
52
|
+
const REGISTRY_URL = "https://registry.npmjs.org/codiedev/latest";
|
|
53
|
+
const FETCH_TIMEOUT_MS = 1500;
|
|
54
|
+
function readCache() {
|
|
55
|
+
try {
|
|
56
|
+
const raw = fs.readFileSync(CACHE_PATH, "utf8");
|
|
57
|
+
const parsed = JSON.parse(raw);
|
|
58
|
+
if (typeof parsed.fetchedAt !== "number")
|
|
59
|
+
return null;
|
|
60
|
+
return parsed;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function writeCache(entry) {
|
|
67
|
+
try {
|
|
68
|
+
const dir = path.dirname(CACHE_PATH);
|
|
69
|
+
if (!fs.existsSync(dir))
|
|
70
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
71
|
+
fs.writeFileSync(CACHE_PATH, JSON.stringify(entry), "utf8");
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// ignore — cache is best-effort
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function fetchLatestFromNpm() {
|
|
78
|
+
try {
|
|
79
|
+
const controller = new AbortController();
|
|
80
|
+
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
81
|
+
const res = await fetch(REGISTRY_URL, {
|
|
82
|
+
headers: { Accept: "application/json" },
|
|
83
|
+
signal: controller.signal,
|
|
84
|
+
});
|
|
85
|
+
clearTimeout(timer);
|
|
86
|
+
if (!res.ok)
|
|
87
|
+
return null;
|
|
88
|
+
const json = (await res.json());
|
|
89
|
+
return json.version ?? null;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Fail-silent — never throws, never blocks on network. If the registry is
|
|
97
|
+
* unreachable or the cache is corrupt, the warning just doesn't print. The
|
|
98
|
+
* worst outcome is "user keeps running an old version" — same as before
|
|
99
|
+
* this feature existed.
|
|
100
|
+
*/
|
|
101
|
+
async function maybePrintUpgradeNudge() {
|
|
102
|
+
const now = Date.now();
|
|
103
|
+
const cache = readCache();
|
|
104
|
+
let latest = cache?.latest ?? null;
|
|
105
|
+
const cacheStale = !cache || now - cache.fetchedAt > CACHE_TTL_MS;
|
|
106
|
+
if (cacheStale) {
|
|
107
|
+
latest = await fetchLatestFromNpm();
|
|
108
|
+
writeCache({ latest, fetchedAt: now });
|
|
109
|
+
}
|
|
110
|
+
const warn = (0, versionCheck_1.shouldShowUpdateWarning)({
|
|
111
|
+
current: version_1.CLI_VERSION,
|
|
112
|
+
latest,
|
|
113
|
+
lastChecked: cache?.fetchedAt ?? 0,
|
|
114
|
+
nowMs: now,
|
|
115
|
+
cacheTtlMs: CACHE_TTL_MS,
|
|
116
|
+
});
|
|
117
|
+
if (warn && latest) {
|
|
118
|
+
console.log("");
|
|
119
|
+
console.log(`[33m⚠️ codiedev ${latest} available (you're on ${version_1.CLI_VERSION})[0m`);
|
|
120
|
+
console.log(` Upgrade: [36mnpm i -g codiedev@latest[0m`);
|
|
121
|
+
console.log("");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const CLI_VERSION: string;
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Resolves the running CLI version. Read once at startup so subsequent
|
|
3
|
+
// auth calls don't pay an fs.readFile per request.
|
|
4
|
+
//
|
|
5
|
+
// We could `import packageJson from "../package.json"` but that requires
|
|
6
|
+
// `resolveJsonModule` and emits the JSON into dist. Reading at runtime
|
|
7
|
+
// keeps the bundle smaller and works regardless of tsconfig settings.
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.CLI_VERSION = void 0;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
function resolveCliVersion() {
|
|
46
|
+
// dist/version.js sits alongside dist/cli.js. The package.json is one
|
|
47
|
+
// directory up from dist/, i.e. `../package.json` relative to this file.
|
|
48
|
+
// In TS source we're at src/version.ts so the path is `../package.json`.
|
|
49
|
+
const candidates = [
|
|
50
|
+
path.join(__dirname, "..", "package.json"),
|
|
51
|
+
path.join(__dirname, "..", "..", "package.json"),
|
|
52
|
+
];
|
|
53
|
+
for (const p of candidates) {
|
|
54
|
+
try {
|
|
55
|
+
const raw = fs.readFileSync(p, "utf8");
|
|
56
|
+
const json = JSON.parse(raw);
|
|
57
|
+
if (json.name === "codiedev" && typeof json.version === "string") {
|
|
58
|
+
return json.version;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// try next candidate
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return "0.0.0";
|
|
66
|
+
}
|
|
67
|
+
exports.CLI_VERSION = resolveCliVersion();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface Semver {
|
|
2
|
+
major: number;
|
|
3
|
+
minor: number;
|
|
4
|
+
patch: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseSemver(input: string): Semver | null;
|
|
7
|
+
/**
|
|
8
|
+
* Returns -1 if a < b, 0 if equal, 1 if a > b.
|
|
9
|
+
*
|
|
10
|
+
* Malformed input on either side returns 0 — we never want to nag a user
|
|
11
|
+
* because of garbage version strings (corrupt cache, registry returned
|
|
12
|
+
* something weird, prerelease format we don't recognize).
|
|
13
|
+
*/
|
|
14
|
+
export declare function compareSemver(a: string, b: string): -1 | 0 | 1;
|
|
15
|
+
export interface UpdateWarningInput {
|
|
16
|
+
current: string;
|
|
17
|
+
latest: string | null;
|
|
18
|
+
lastChecked: number;
|
|
19
|
+
nowMs: number;
|
|
20
|
+
cacheTtlMs: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Warning policy: only show when we have a known-newer `latest` from a
|
|
24
|
+
* recent-enough cache. Stale-cache freshness is enforced by the *caller*
|
|
25
|
+
* (which decides whether to refetch); this helper takes the cache state
|
|
26
|
+
* as-given and answers a single question — should the user see a nag?
|
|
27
|
+
*/
|
|
28
|
+
export declare function shouldShowUpdateWarning(input: UpdateWarningInput): boolean;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Pure version-comparison helpers for the "is your CLI outdated" warning.
|
|
3
|
+
// The IO (fetching npm registry, reading/writing the cache file) lives in
|
|
4
|
+
// connect.ts/doctor.ts and is exercised by manual smoke. Keeping the policy
|
|
5
|
+
// pure means the truth table is unit-testable without mocking fetch or fs.
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.parseSemver = parseSemver;
|
|
8
|
+
exports.compareSemver = compareSemver;
|
|
9
|
+
exports.shouldShowUpdateWarning = shouldShowUpdateWarning;
|
|
10
|
+
function parseSemver(input) {
|
|
11
|
+
if (!input)
|
|
12
|
+
return null;
|
|
13
|
+
const stripped = input.replace(/^v/i, "");
|
|
14
|
+
const m = stripped.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
15
|
+
if (!m)
|
|
16
|
+
return null;
|
|
17
|
+
return { major: Number(m[1]), minor: Number(m[2]), patch: Number(m[3]) };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns -1 if a < b, 0 if equal, 1 if a > b.
|
|
21
|
+
*
|
|
22
|
+
* Malformed input on either side returns 0 — we never want to nag a user
|
|
23
|
+
* because of garbage version strings (corrupt cache, registry returned
|
|
24
|
+
* something weird, prerelease format we don't recognize).
|
|
25
|
+
*/
|
|
26
|
+
function compareSemver(a, b) {
|
|
27
|
+
const pa = parseSemver(a);
|
|
28
|
+
const pb = parseSemver(b);
|
|
29
|
+
if (!pa || !pb)
|
|
30
|
+
return 0;
|
|
31
|
+
if (pa.major !== pb.major)
|
|
32
|
+
return pa.major < pb.major ? -1 : 1;
|
|
33
|
+
if (pa.minor !== pb.minor)
|
|
34
|
+
return pa.minor < pb.minor ? -1 : 1;
|
|
35
|
+
if (pa.patch !== pb.patch)
|
|
36
|
+
return pa.patch < pb.patch ? -1 : 1;
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Warning policy: only show when we have a known-newer `latest` from a
|
|
41
|
+
* recent-enough cache. Stale-cache freshness is enforced by the *caller*
|
|
42
|
+
* (which decides whether to refetch); this helper takes the cache state
|
|
43
|
+
* as-given and answers a single question — should the user see a nag?
|
|
44
|
+
*/
|
|
45
|
+
function shouldShowUpdateWarning(input) {
|
|
46
|
+
if (!input.latest)
|
|
47
|
+
return false;
|
|
48
|
+
return compareSemver(input.current, input.latest) === -1;
|
|
49
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codiedev",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.9",
|
|
4
4
|
"description": "Connect Claude Code, Codex, Cursor, or VS Code Copilot to CodieDev for org-wide session capture and artifact collaboration",
|
|
5
5
|
"bin": {
|
|
6
|
-
"codiedev": "
|
|
7
|
-
"codiedev-hook": "
|
|
6
|
+
"codiedev": "dist/cli.js",
|
|
7
|
+
"codiedev-hook": "dist/hook.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "tsc",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const connectFlow_1 = require("../connectFlow");
|
|
5
|
-
const SAVED = {
|
|
6
|
-
token: "cdv_savedToken_xxxx",
|
|
7
|
-
companyId: "co_1",
|
|
8
|
-
companyName: "Sonifi",
|
|
9
|
-
repos: [],
|
|
10
|
-
lastSynced: new Date().toISOString(),
|
|
11
|
-
backendUrl: "https://example.test",
|
|
12
|
-
};
|
|
13
|
-
(0, vitest_1.describe)("resolveConnectToken", () => {
|
|
14
|
-
(0, vitest_1.it)("uses saved token when present and force=false", () => {
|
|
15
|
-
const res = (0, connectFlow_1.resolveConnectToken)({ savedConfig: SAVED, force: false });
|
|
16
|
-
(0, vitest_1.expect)(res).toEqual({ source: "reused", token: SAVED.token });
|
|
17
|
-
});
|
|
18
|
-
(0, vitest_1.it)("requires a prompt when no config exists", () => {
|
|
19
|
-
const res = (0, connectFlow_1.resolveConnectToken)({ savedConfig: null, force: false });
|
|
20
|
-
(0, vitest_1.expect)(res).toEqual({ source: "prompt-required" });
|
|
21
|
-
});
|
|
22
|
-
(0, vitest_1.it)("requires a prompt when --force is set, even if a saved token exists", () => {
|
|
23
|
-
const res = (0, connectFlow_1.resolveConnectToken)({ savedConfig: SAVED, force: true });
|
|
24
|
-
(0, vitest_1.expect)(res).toEqual({ source: "prompt-required" });
|
|
25
|
-
});
|
|
26
|
-
(0, vitest_1.it)("requires a prompt when saved config has empty token", () => {
|
|
27
|
-
const res = (0, connectFlow_1.resolveConnectToken)({
|
|
28
|
-
savedConfig: { ...SAVED, token: "" },
|
|
29
|
-
force: false,
|
|
30
|
-
});
|
|
31
|
-
(0, vitest_1.expect)(res).toEqual({ source: "prompt-required" });
|
|
32
|
-
});
|
|
33
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const detection_1 = require("../detection");
|
|
5
|
-
(0, vitest_1.describe)("detectClaudeCode", () => {
|
|
6
|
-
(0, vitest_1.it)("returns false when neither ~/.claude nor `claude` binary present", () => {
|
|
7
|
-
(0, vitest_1.expect)((0, detection_1.detectClaudeCode)({ dirExists: false, binOnPath: false })).toBe(false);
|
|
8
|
-
});
|
|
9
|
-
(0, vitest_1.it)("returns true when only ~/.claude exists", () => {
|
|
10
|
-
(0, vitest_1.expect)((0, detection_1.detectClaudeCode)({ dirExists: true, binOnPath: false })).toBe(true);
|
|
11
|
-
});
|
|
12
|
-
(0, vitest_1.it)("returns true when only `claude` is on PATH (CC installed but never launched)", () => {
|
|
13
|
-
(0, vitest_1.expect)((0, detection_1.detectClaudeCode)({ dirExists: false, binOnPath: true })).toBe(true);
|
|
14
|
-
});
|
|
15
|
-
(0, vitest_1.it)("returns true when both are present", () => {
|
|
16
|
-
(0, vitest_1.expect)((0, detection_1.detectClaudeCode)({ dirExists: true, binOnPath: true })).toBe(true);
|
|
17
|
-
});
|
|
18
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const prUrl_1 = require("../prUrl");
|
|
5
|
-
(0, vitest_1.describe)("parsePrOrMrUrl", () => {
|
|
6
|
-
(0, vitest_1.it)("parses a GitHub PR url", () => {
|
|
7
|
-
(0, vitest_1.expect)((0, prUrl_1.parsePrOrMrUrl)("https://github.com/foo/bar/pull/123")).toEqual({
|
|
8
|
-
provider: "github",
|
|
9
|
-
host: "github.com",
|
|
10
|
-
owner: "foo",
|
|
11
|
-
repo: "bar",
|
|
12
|
-
number: 123,
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
(0, vitest_1.it)("parses a GitLab.com MR url", () => {
|
|
16
|
-
(0, vitest_1.expect)((0, prUrl_1.parsePrOrMrUrl)("https://gitlab.com/sonifi/platform/-/merge_requests/42")).toEqual({
|
|
17
|
-
provider: "gitlab",
|
|
18
|
-
host: "gitlab.com",
|
|
19
|
-
owner: "sonifi",
|
|
20
|
-
repo: "platform",
|
|
21
|
-
number: 42,
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
(0, vitest_1.it)("parses a self-hosted GitLab MR url", () => {
|
|
25
|
-
(0, vitest_1.expect)((0, prUrl_1.parsePrOrMrUrl)("https://git.sonifi.com/internal/platform/-/merge_requests/7")).toEqual({
|
|
26
|
-
provider: "gitlab",
|
|
27
|
-
host: "git.sonifi.com",
|
|
28
|
-
owner: "internal",
|
|
29
|
-
repo: "platform",
|
|
30
|
-
number: 7,
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
(0, vitest_1.it)("parses a GitLab MR url with a nested group path", () => {
|
|
34
|
-
(0, vitest_1.expect)((0, prUrl_1.parsePrOrMrUrl)("https://gitlab.com/sonifi/team-a/platform/-/merge_requests/9")).toEqual({
|
|
35
|
-
provider: "gitlab",
|
|
36
|
-
host: "gitlab.com",
|
|
37
|
-
owner: "sonifi/team-a",
|
|
38
|
-
repo: "platform",
|
|
39
|
-
number: 9,
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
(0, vitest_1.it)("returns null for unrecognized URLs", () => {
|
|
43
|
-
(0, vitest_1.expect)((0, prUrl_1.parsePrOrMrUrl)("https://example.com/foo")).toBe(null);
|
|
44
|
-
(0, vitest_1.expect)((0, prUrl_1.parsePrOrMrUrl)("not a url")).toBe(null);
|
|
45
|
-
(0, vitest_1.expect)((0, prUrl_1.parsePrOrMrUrl)("")).toBe(null);
|
|
46
|
-
});
|
|
47
|
-
(0, vitest_1.it)("returns null when the number segment isn't an integer", () => {
|
|
48
|
-
(0, vitest_1.expect)((0, prUrl_1.parsePrOrMrUrl)("https://github.com/foo/bar/pull/abc")).toBe(null);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const repoResolver_1 = require("../repoResolver");
|
|
5
|
-
const ghRepo = { _id: "rep_gh1", owner: "Signal-and-Code", name: "vm-demo", gitProvider: "github" };
|
|
6
|
-
const glRepo = { _id: "rep_gl1", owner: "sonifi", name: "platform", gitProvider: "gitlab" };
|
|
7
|
-
(0, vitest_1.describe)("resolveRepoForCapture", () => {
|
|
8
|
-
(0, vitest_1.it)("returns the provided repoId when it matches a current repo", () => {
|
|
9
|
-
const res = (0, repoResolver_1.resolveRepoForCapture)({
|
|
10
|
-
remoteUrl: "https://github.com/Signal-and-Code/vm-demo.git",
|
|
11
|
-
providedRepoId: "rep_gh1",
|
|
12
|
-
companyRepos: [ghRepo],
|
|
13
|
-
});
|
|
14
|
-
(0, vitest_1.expect)(res).toEqual({ repoId: "rep_gh1", source: "provided" });
|
|
15
|
-
});
|
|
16
|
-
(0, vitest_1.it)("falls back to remoteUrl resolution when providedRepoId is stale", () => {
|
|
17
|
-
const res = (0, repoResolver_1.resolveRepoForCapture)({
|
|
18
|
-
remoteUrl: "https://github.com/Signal-and-Code/vm-demo.git",
|
|
19
|
-
providedRepoId: "rep_deleted",
|
|
20
|
-
companyRepos: [ghRepo],
|
|
21
|
-
});
|
|
22
|
-
(0, vitest_1.expect)(res).toEqual({ repoId: "rep_gh1", source: "resolved" });
|
|
23
|
-
});
|
|
24
|
-
(0, vitest_1.it)("resolves from remoteUrl when no providedRepoId is given (HTTPS form)", () => {
|
|
25
|
-
const res = (0, repoResolver_1.resolveRepoForCapture)({
|
|
26
|
-
remoteUrl: "https://github.com/Signal-and-Code/vm-demo.git",
|
|
27
|
-
providedRepoId: null,
|
|
28
|
-
companyRepos: [ghRepo],
|
|
29
|
-
});
|
|
30
|
-
(0, vitest_1.expect)(res).toEqual({ repoId: "rep_gh1", source: "resolved" });
|
|
31
|
-
});
|
|
32
|
-
(0, vitest_1.it)("resolves from remoteUrl when no providedRepoId is given (SSH form)", () => {
|
|
33
|
-
const res = (0, repoResolver_1.resolveRepoForCapture)({
|
|
34
|
-
remoteUrl: "git@github.com:Signal-and-Code/vm-demo.git",
|
|
35
|
-
providedRepoId: null,
|
|
36
|
-
companyRepos: [ghRepo],
|
|
37
|
-
});
|
|
38
|
-
(0, vitest_1.expect)(res).toEqual({ repoId: "rep_gh1", source: "resolved" });
|
|
39
|
-
});
|
|
40
|
-
(0, vitest_1.it)("resolves a GitLab remote against a gitlab-provider repo", () => {
|
|
41
|
-
const res = (0, repoResolver_1.resolveRepoForCapture)({
|
|
42
|
-
remoteUrl: "https://gitlab.com/sonifi/platform.git",
|
|
43
|
-
providedRepoId: null,
|
|
44
|
-
companyRepos: [ghRepo, glRepo],
|
|
45
|
-
});
|
|
46
|
-
(0, vitest_1.expect)(res).toEqual({ repoId: "rep_gl1", source: "resolved" });
|
|
47
|
-
});
|
|
48
|
-
(0, vitest_1.it)("resolves SSH-form GitLab URL", () => {
|
|
49
|
-
const res = (0, repoResolver_1.resolveRepoForCapture)({
|
|
50
|
-
remoteUrl: "git@gitlab.com:sonifi/platform.git",
|
|
51
|
-
providedRepoId: null,
|
|
52
|
-
companyRepos: [glRepo],
|
|
53
|
-
});
|
|
54
|
-
(0, vitest_1.expect)(res).toEqual({ repoId: "rep_gl1", source: "resolved" });
|
|
55
|
-
});
|
|
56
|
-
(0, vitest_1.it)("returns unmatched when remoteUrl matches no repo (don't drop the session — let backend decide)", () => {
|
|
57
|
-
const res = (0, repoResolver_1.resolveRepoForCapture)({
|
|
58
|
-
remoteUrl: "https://github.com/some/other-repo.git",
|
|
59
|
-
providedRepoId: null,
|
|
60
|
-
companyRepos: [ghRepo, glRepo],
|
|
61
|
-
});
|
|
62
|
-
(0, vitest_1.expect)(res).toEqual({ repoId: null, source: "unmatched" });
|
|
63
|
-
});
|
|
64
|
-
(0, vitest_1.it)("matches case-insensitively on owner/name (GitHub is case-insensitive on org/repo names)", () => {
|
|
65
|
-
const res = (0, repoResolver_1.resolveRepoForCapture)({
|
|
66
|
-
remoteUrl: "https://github.com/SIGNAL-AND-CODE/vm-demo.git",
|
|
67
|
-
providedRepoId: null,
|
|
68
|
-
companyRepos: [ghRepo],
|
|
69
|
-
});
|
|
70
|
-
(0, vitest_1.expect)(res).toEqual({ repoId: "rep_gh1", source: "resolved" });
|
|
71
|
-
});
|
|
72
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const scope_1 = require("../scope");
|
|
5
|
-
(0, vitest_1.describe)("formatScope", () => {
|
|
6
|
-
(0, vitest_1.it)("formats matched-repo case", () => {
|
|
7
|
-
(0, vitest_1.expect)((0, scope_1.formatScope)({
|
|
8
|
-
workspaceName: "Sonifi",
|
|
9
|
-
matchedRepo: { fullName: "Signal-and-Code/codiedev-ea" },
|
|
10
|
-
})).toBe("→ Sonifi (matched Signal-and-Code/codiedev-ea)");
|
|
11
|
-
});
|
|
12
|
-
(0, vitest_1.it)("formats no-match case", () => {
|
|
13
|
-
(0, vitest_1.expect)((0, scope_1.formatScope)({ workspaceName: "Sonifi", matchedRepo: null })).toBe("→ Sonifi (default profile, no repo match)");
|
|
14
|
-
});
|
|
15
|
-
(0, vitest_1.it)("handles unknown workspace gracefully", () => {
|
|
16
|
-
(0, vitest_1.expect)((0, scope_1.formatScope)({ workspaceName: "", matchedRepo: null })).toBe("→ unknown workspace");
|
|
17
|
-
});
|
|
18
|
-
(0, vitest_1.it)("handles unknown workspace with matched repo", () => {
|
|
19
|
-
(0, vitest_1.expect)((0, scope_1.formatScope)({
|
|
20
|
-
workspaceName: "",
|
|
21
|
-
matchedRepo: { fullName: "Foo/Bar" },
|
|
22
|
-
})).toBe("→ unknown workspace");
|
|
23
|
-
});
|
|
24
|
-
});
|