@coderule/mcp 1.7.2 → 2.0.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/dist/cli.cjs +224 -45
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +220 -42
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +203 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +199 -31
- package/dist/index.js.map +1 -1
- package/dist/mcp-cli.cjs +236 -46
- package/dist/mcp-cli.cjs.map +1 -1
- package/dist/mcp-cli.js +232 -43
- package/dist/mcp-cli.js.map +1 -1
- package/package.json +6 -4
package/dist/mcp-cli.cjs
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
4
|
+
var fs5 = require('fs/promises');
|
|
5
|
+
var path2 = require('path');
|
|
6
6
|
var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
7
7
|
var crypto = require('crypto');
|
|
8
8
|
var envPaths = require('env-paths');
|
|
9
9
|
var pino = require('pino');
|
|
10
|
+
var os = require('os');
|
|
10
11
|
var Database = require('better-sqlite3');
|
|
11
12
|
var qulite = require('@coderule/qulite');
|
|
12
13
|
var clients = require('@coderule/clients');
|
|
13
|
-
var
|
|
14
|
+
var fs3 = require('fs');
|
|
14
15
|
var worker_threads = require('worker_threads');
|
|
15
16
|
var chokidar = require('chokidar');
|
|
16
17
|
var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
@@ -18,12 +19,13 @@ var zod = require('zod');
|
|
|
18
19
|
|
|
19
20
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
20
21
|
|
|
21
|
-
var
|
|
22
|
-
var
|
|
22
|
+
var fs5__default = /*#__PURE__*/_interopDefault(fs5);
|
|
23
|
+
var path2__default = /*#__PURE__*/_interopDefault(path2);
|
|
23
24
|
var envPaths__default = /*#__PURE__*/_interopDefault(envPaths);
|
|
24
25
|
var pino__default = /*#__PURE__*/_interopDefault(pino);
|
|
26
|
+
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
25
27
|
var Database__default = /*#__PURE__*/_interopDefault(Database);
|
|
26
|
-
var
|
|
28
|
+
var fs3__default = /*#__PURE__*/_interopDefault(fs3);
|
|
27
29
|
var chokidar__default = /*#__PURE__*/_interopDefault(chokidar);
|
|
28
30
|
|
|
29
31
|
// node_modules/tsup/assets/cjs_shims.js
|
|
@@ -50,6 +52,166 @@ var DEFAULT_MAX_SNAPSHOT_ATTEMPTS = 5;
|
|
|
50
52
|
var DEFAULT_HTTP_TIMEOUT_MS = 12e4;
|
|
51
53
|
var DEFAULT_UPLOAD_CHUNK_SIZE = 1;
|
|
52
54
|
var DEFAULT_MAX_QUERY_WAIT_MS = 5e4;
|
|
55
|
+
function collectCandidateSources(options) {
|
|
56
|
+
const sources = [];
|
|
57
|
+
if (options?.cliRoot) {
|
|
58
|
+
sources.push({
|
|
59
|
+
value: options.cliRoot,
|
|
60
|
+
source: "cli-arg",
|
|
61
|
+
baseConfidence: 1
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (process.env.CODERULE_ROOT) {
|
|
65
|
+
sources.push({
|
|
66
|
+
value: process.env.CODERULE_ROOT,
|
|
67
|
+
source: "env-coderule-root",
|
|
68
|
+
baseConfidence: 0.9
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (process.env.WORKSPACE_FOLDER_PATHS) {
|
|
72
|
+
sources.push({
|
|
73
|
+
value: process.env.WORKSPACE_FOLDER_PATHS,
|
|
74
|
+
source: "env-workspace",
|
|
75
|
+
baseConfidence: 0.8
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
sources.push({
|
|
79
|
+
value: process.cwd(),
|
|
80
|
+
source: "process-cwd",
|
|
81
|
+
baseConfidence: 0.6
|
|
82
|
+
});
|
|
83
|
+
return sources;
|
|
84
|
+
}
|
|
85
|
+
async function pathExists(targetPath) {
|
|
86
|
+
try {
|
|
87
|
+
await fs5__default.default.access(targetPath);
|
|
88
|
+
return true;
|
|
89
|
+
} catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async function isDirectory(targetPath) {
|
|
94
|
+
try {
|
|
95
|
+
const stat = await fs5__default.default.stat(targetPath);
|
|
96
|
+
return stat.isDirectory();
|
|
97
|
+
} catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async function hasGitDirectory(rootPath) {
|
|
102
|
+
const gitPath = path2__default.default.join(rootPath, ".git");
|
|
103
|
+
return pathExists(gitPath);
|
|
104
|
+
}
|
|
105
|
+
function isShallowPath(absolutePath) {
|
|
106
|
+
const normalized = absolutePath.replace(/\\/g, "/");
|
|
107
|
+
const separatorCount = (normalized.match(/\//g) || []).length;
|
|
108
|
+
return separatorCount <= 1;
|
|
109
|
+
}
|
|
110
|
+
function isHomeDirectory(candidatePath) {
|
|
111
|
+
const home = os__default.default.homedir();
|
|
112
|
+
const normalizedCandidate = path2__default.default.normalize(candidatePath);
|
|
113
|
+
const normalizedHome = path2__default.default.normalize(home);
|
|
114
|
+
return normalizedCandidate === normalizedHome;
|
|
115
|
+
}
|
|
116
|
+
async function applyModifiers(candidate) {
|
|
117
|
+
const modifiers = [];
|
|
118
|
+
if (await hasGitDirectory(candidate.path)) {
|
|
119
|
+
modifiers.push({ reason: "has .git directory", delta: 0.1 });
|
|
120
|
+
}
|
|
121
|
+
if (isShallowPath(candidate.path)) {
|
|
122
|
+
modifiers.push({ reason: "shallow path (likely root)", delta: -0.2 });
|
|
123
|
+
}
|
|
124
|
+
if (isHomeDirectory(candidate.path)) {
|
|
125
|
+
modifiers.push({ reason: "is home directory", delta: -0.3 });
|
|
126
|
+
}
|
|
127
|
+
const totalModifier = modifiers.reduce((sum, m) => sum + m.delta, 0);
|
|
128
|
+
const finalConfidence = candidate.baseConfidence + totalModifier;
|
|
129
|
+
return {
|
|
130
|
+
...candidate,
|
|
131
|
+
modifiers,
|
|
132
|
+
finalConfidence
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
async function createCandidate(source) {
|
|
136
|
+
const absolutePath = path2__default.default.resolve(source.value);
|
|
137
|
+
const exists = await pathExists(absolutePath);
|
|
138
|
+
const isDir = exists ? await isDirectory(absolutePath) : false;
|
|
139
|
+
const candidate = {
|
|
140
|
+
path: absolutePath,
|
|
141
|
+
source: source.source,
|
|
142
|
+
baseConfidence: source.baseConfidence,
|
|
143
|
+
modifiers: [],
|
|
144
|
+
finalConfidence: source.baseConfidence,
|
|
145
|
+
exists,
|
|
146
|
+
isDirectory: isDir
|
|
147
|
+
};
|
|
148
|
+
if (exists && isDir) {
|
|
149
|
+
return applyModifiers(candidate);
|
|
150
|
+
}
|
|
151
|
+
return candidate;
|
|
152
|
+
}
|
|
153
|
+
async function resolveRootPath(options) {
|
|
154
|
+
const logger2 = options?.logger;
|
|
155
|
+
const sources = collectCandidateSources(options);
|
|
156
|
+
const candidates = await Promise.all(sources.map(createCandidate));
|
|
157
|
+
logger2?.debug(
|
|
158
|
+
{
|
|
159
|
+
candidates: candidates.map((c) => ({
|
|
160
|
+
path: c.path,
|
|
161
|
+
source: c.source,
|
|
162
|
+
baseConfidence: c.baseConfidence,
|
|
163
|
+
finalConfidence: c.finalConfidence,
|
|
164
|
+
exists: c.exists,
|
|
165
|
+
isDirectory: c.isDirectory,
|
|
166
|
+
modifiers: c.modifiers
|
|
167
|
+
}))
|
|
168
|
+
},
|
|
169
|
+
"Collected root path candidates"
|
|
170
|
+
);
|
|
171
|
+
const validCandidates = candidates.filter((c) => c.exists && c.isDirectory);
|
|
172
|
+
if (validCandidates.length === 0) {
|
|
173
|
+
const attempted = candidates.map((c) => c.path).join(", ");
|
|
174
|
+
throw new Error(
|
|
175
|
+
`No valid root directory found. Attempted: ${attempted}. Ensure the directory exists and is accessible.`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
const sourcePriority = {
|
|
179
|
+
"cli-arg": 1,
|
|
180
|
+
"env-coderule-root": 2,
|
|
181
|
+
"env-workspace": 3,
|
|
182
|
+
"process-cwd": 4
|
|
183
|
+
};
|
|
184
|
+
validCandidates.sort((a, b) => {
|
|
185
|
+
const confidenceDiff = b.finalConfidence - a.finalConfidence;
|
|
186
|
+
if (confidenceDiff !== 0) {
|
|
187
|
+
return confidenceDiff;
|
|
188
|
+
}
|
|
189
|
+
return sourcePriority[a.source] - sourcePriority[b.source];
|
|
190
|
+
});
|
|
191
|
+
const best = validCandidates[0];
|
|
192
|
+
if (best.finalConfidence < 0.7) {
|
|
193
|
+
logger2?.warn(
|
|
194
|
+
{
|
|
195
|
+
path: best.path,
|
|
196
|
+
source: best.source,
|
|
197
|
+
confidence: best.finalConfidence,
|
|
198
|
+
modifiers: best.modifiers
|
|
199
|
+
},
|
|
200
|
+
"Selected root path has low confidence"
|
|
201
|
+
);
|
|
202
|
+
} else {
|
|
203
|
+
logger2?.info(
|
|
204
|
+
{
|
|
205
|
+
path: best.path,
|
|
206
|
+
source: best.source,
|
|
207
|
+
confidence: best.finalConfidence,
|
|
208
|
+
modifiers: best.modifiers
|
|
209
|
+
},
|
|
210
|
+
"Resolved root path"
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
return best;
|
|
214
|
+
}
|
|
53
215
|
|
|
54
216
|
// src/config/Configurator.ts
|
|
55
217
|
var DEFAULT_RETRIEVAL_FORMATTER = "standard";
|
|
@@ -62,9 +224,9 @@ var DEFAULTS = {
|
|
|
62
224
|
maxSnapshotAttempts: DEFAULT_MAX_SNAPSHOT_ATTEMPTS
|
|
63
225
|
};
|
|
64
226
|
function normalizeRoot(root) {
|
|
65
|
-
const resolved =
|
|
66
|
-
const normalized =
|
|
67
|
-
return normalized.split(
|
|
227
|
+
const resolved = path2__default.default.resolve(root);
|
|
228
|
+
const normalized = path2__default.default.normalize(resolved);
|
|
229
|
+
return normalized.split(path2__default.default.sep).join("/");
|
|
68
230
|
}
|
|
69
231
|
function sha256(input) {
|
|
70
232
|
return crypto.createHash("sha256").update(input).digest("hex");
|
|
@@ -96,7 +258,8 @@ function parseFormatter(value) {
|
|
|
96
258
|
);
|
|
97
259
|
}
|
|
98
260
|
async function resolveConfig({
|
|
99
|
-
token
|
|
261
|
+
token,
|
|
262
|
+
rootPath: cliRoot
|
|
100
263
|
}) {
|
|
101
264
|
const resolvedToken = token ?? process.env.CODERULE_TOKEN;
|
|
102
265
|
if (!resolvedToken) {
|
|
@@ -104,14 +267,17 @@ async function resolveConfig({
|
|
|
104
267
|
"Missing token: provide params.token or CODERULE_TOKEN env"
|
|
105
268
|
);
|
|
106
269
|
}
|
|
107
|
-
const rootCandidate =
|
|
108
|
-
|
|
270
|
+
const rootCandidate = await resolveRootPath({
|
|
271
|
+
cliRoot,
|
|
272
|
+
logger: logger.child({ scope: "root-resolver" })
|
|
273
|
+
});
|
|
274
|
+
const rootPath = rootCandidate.path;
|
|
109
275
|
const normalized = normalizeRoot(rootPath);
|
|
110
276
|
const rootId = sha256(normalized);
|
|
111
277
|
const dataDir = process.env.CODERULE_DATA_DIR || envPaths__default.default("coderule").data;
|
|
112
|
-
const watchDir =
|
|
113
|
-
await
|
|
114
|
-
const dbPath =
|
|
278
|
+
const watchDir = path2__default.default.join(dataDir, "watch");
|
|
279
|
+
await fs5__default.default.mkdir(watchDir, { recursive: true });
|
|
280
|
+
const dbPath = path2__default.default.join(watchDir, `${rootId}.sqlite`);
|
|
115
281
|
const baseConfig = {
|
|
116
282
|
token: resolvedToken,
|
|
117
283
|
rootPath,
|
|
@@ -188,6 +354,9 @@ async function resolveConfig({
|
|
|
188
354
|
logger.debug(
|
|
189
355
|
{
|
|
190
356
|
rootPath,
|
|
357
|
+
rootSource: rootCandidate.source,
|
|
358
|
+
rootConfidence: rootCandidate.finalConfidence,
|
|
359
|
+
rootModifiers: rootCandidate.modifiers,
|
|
191
360
|
dbPath,
|
|
192
361
|
dataDir,
|
|
193
362
|
authBaseUrl: baseConfig.authBaseUrl,
|
|
@@ -688,7 +857,7 @@ async function fetchVisitorRules(clients, logger2) {
|
|
|
688
857
|
return rules;
|
|
689
858
|
}
|
|
690
859
|
function toPosix(input) {
|
|
691
|
-
return input.split(
|
|
860
|
+
return input.split(path2__default.default.sep).join("/");
|
|
692
861
|
}
|
|
693
862
|
function getLowerBasename(input) {
|
|
694
863
|
const base = input.split("/").pop();
|
|
@@ -707,7 +876,7 @@ function compileRulesBundle(rules) {
|
|
|
707
876
|
if (!info) {
|
|
708
877
|
logger.debug({ path: fullPath }, "Predicate fallback lstat");
|
|
709
878
|
try {
|
|
710
|
-
info =
|
|
879
|
+
info = fs3__default.default.lstatSync(fullPath);
|
|
711
880
|
} catch (error) {
|
|
712
881
|
logger.warn(
|
|
713
882
|
{ err: error, path: fullPath },
|
|
@@ -856,14 +1025,14 @@ var Hasher = class {
|
|
|
856
1025
|
await new Promise((resolve) => setImmediate(resolve));
|
|
857
1026
|
}
|
|
858
1027
|
resolveAbsolutePath(record) {
|
|
859
|
-
if (
|
|
1028
|
+
if (path2__default.default.isAbsolute(record.display_path)) {
|
|
860
1029
|
return record.display_path;
|
|
861
1030
|
}
|
|
862
|
-
return
|
|
1031
|
+
return path2__default.default.join(this.options.rootPath, record.rel_path);
|
|
863
1032
|
}
|
|
864
1033
|
async ensureExists(absPath, record) {
|
|
865
1034
|
try {
|
|
866
|
-
await
|
|
1035
|
+
await fs5__default.default.access(absPath);
|
|
867
1036
|
return true;
|
|
868
1037
|
} catch (error) {
|
|
869
1038
|
this.log.warn(
|
|
@@ -886,7 +1055,7 @@ var Hasher = class {
|
|
|
886
1055
|
const service = crypto.createHash("sha256");
|
|
887
1056
|
service.update(relPath);
|
|
888
1057
|
service.update("\n");
|
|
889
|
-
const stream =
|
|
1058
|
+
const stream = fs3__default.default.createReadStream(absPath);
|
|
890
1059
|
stream.on("data", (chunk) => {
|
|
891
1060
|
content.update(chunk);
|
|
892
1061
|
service.update(chunk);
|
|
@@ -1001,13 +1170,13 @@ async function bootstrap(params) {
|
|
|
1001
1170
|
return runtime;
|
|
1002
1171
|
}
|
|
1003
1172
|
function toPosixRelative(root, target) {
|
|
1004
|
-
const rel =
|
|
1173
|
+
const rel = path2__default.default.relative(root, target);
|
|
1005
1174
|
if (!rel || rel === "") return "";
|
|
1006
|
-
return rel.split(
|
|
1175
|
+
return rel.split(path2__default.default.sep).join("/");
|
|
1007
1176
|
}
|
|
1008
1177
|
function isInsideRoot(root, target) {
|
|
1009
|
-
const rel =
|
|
1010
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
1178
|
+
const rel = path2__default.default.relative(root, target);
|
|
1179
|
+
return rel === "" || !rel.startsWith("..") && !path2__default.default.isAbsolute(rel);
|
|
1011
1180
|
}
|
|
1012
1181
|
|
|
1013
1182
|
// src/fs/Walker.ts
|
|
@@ -1022,7 +1191,7 @@ function cloneStats(stats) {
|
|
|
1022
1191
|
}
|
|
1023
1192
|
async function readSymlinkTarget(absPath, log) {
|
|
1024
1193
|
try {
|
|
1025
|
-
return await
|
|
1194
|
+
return await fs5__default.default.readlink(absPath);
|
|
1026
1195
|
} catch (error) {
|
|
1027
1196
|
log.warn({ err: error, path: absPath }, "Failed to read symlink target");
|
|
1028
1197
|
return null;
|
|
@@ -1032,13 +1201,13 @@ async function walkDirectory(current, opts, stats) {
|
|
|
1032
1201
|
const dirLogger = opts.logger;
|
|
1033
1202
|
let dirents;
|
|
1034
1203
|
try {
|
|
1035
|
-
dirents = await
|
|
1204
|
+
dirents = await fs5__default.default.readdir(current, { withFileTypes: true });
|
|
1036
1205
|
} catch (error) {
|
|
1037
1206
|
dirLogger.warn({ err: error, path: current }, "Failed to read directory");
|
|
1038
1207
|
return;
|
|
1039
1208
|
}
|
|
1040
1209
|
for (const dirent of dirents) {
|
|
1041
|
-
const absPath =
|
|
1210
|
+
const absPath = path2__default.default.join(current, dirent.name);
|
|
1042
1211
|
const relPath = toPosixRelative(opts.rootPath, absPath);
|
|
1043
1212
|
if (dirent.isDirectory()) {
|
|
1044
1213
|
if (shouldPruneDirectory(relPath, opts.bundle)) {
|
|
@@ -1051,7 +1220,7 @@ async function walkDirectory(current, opts, stats) {
|
|
|
1051
1220
|
if (dirent.isSymbolicLink() || dirent.isFile()) {
|
|
1052
1221
|
let stat;
|
|
1053
1222
|
try {
|
|
1054
|
-
stat = await
|
|
1223
|
+
stat = await fs5__default.default.lstat(absPath);
|
|
1055
1224
|
} catch (error) {
|
|
1056
1225
|
dirLogger.warn({ err: error, path: absPath }, "Failed to stat file");
|
|
1057
1226
|
continue;
|
|
@@ -1143,9 +1312,9 @@ async function uploadMissing(rootPath, missing, syncClient, logger2, maxAttempts
|
|
|
1143
1312
|
const list = chunks[idx];
|
|
1144
1313
|
const map = /* @__PURE__ */ new Map();
|
|
1145
1314
|
for (const missingFile of list) {
|
|
1146
|
-
const absPath =
|
|
1315
|
+
const absPath = path2__default.default.join(rootPath, missingFile.file_path);
|
|
1147
1316
|
try {
|
|
1148
|
-
const buffer = await
|
|
1317
|
+
const buffer = await fs5__default.default.readFile(absPath);
|
|
1149
1318
|
map.set(missingFile.file_hash, {
|
|
1150
1319
|
path: missingFile.file_path,
|
|
1151
1320
|
content: buffer
|
|
@@ -1410,7 +1579,7 @@ function computeBackoff(attempts) {
|
|
|
1410
1579
|
}
|
|
1411
1580
|
async function readSymlinkTarget2(absPath) {
|
|
1412
1581
|
try {
|
|
1413
|
-
return await
|
|
1582
|
+
return await fs5__default.default.readlink(absPath);
|
|
1414
1583
|
} catch {
|
|
1415
1584
|
return null;
|
|
1416
1585
|
}
|
|
@@ -1551,7 +1720,7 @@ var ServiceRunner = class {
|
|
|
1551
1720
|
async handleEvent(event, absPath, stats) {
|
|
1552
1721
|
if (!this.running) return;
|
|
1553
1722
|
const root = this.runtime.config.rootPath;
|
|
1554
|
-
const absolute =
|
|
1723
|
+
const absolute = path2__default.default.isAbsolute(absPath) ? absPath : path2__default.default.join(root, absPath);
|
|
1555
1724
|
if (!isInsideRoot(root, absolute)) {
|
|
1556
1725
|
return;
|
|
1557
1726
|
}
|
|
@@ -1571,7 +1740,7 @@ var ServiceRunner = class {
|
|
|
1571
1740
|
async handleAddChange(absPath, _stats) {
|
|
1572
1741
|
let fileStats;
|
|
1573
1742
|
try {
|
|
1574
|
-
fileStats = await
|
|
1743
|
+
fileStats = await fs5__default.default.lstat(absPath);
|
|
1575
1744
|
} catch (error) {
|
|
1576
1745
|
this.runtime.logger.warn(
|
|
1577
1746
|
{ err: error, path: absPath },
|
|
@@ -1823,9 +1992,19 @@ function formatStatus(status) {
|
|
|
1823
1992
|
` Pass 2 (Cross-Reference): ${formatDuration(timing.pass2)}`
|
|
1824
1993
|
);
|
|
1825
1994
|
}
|
|
1826
|
-
if (timing.
|
|
1995
|
+
if (timing.pass2_hdf5_compile !== void 0) {
|
|
1996
|
+
lines.push(
|
|
1997
|
+
` HDF5 Compilation: ${formatDuration(timing.pass2_hdf5_compile)}`
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
2000
|
+
if (timing.pass2_hdf5_dedup !== void 0) {
|
|
1827
2001
|
lines.push(
|
|
1828
|
-
`
|
|
2002
|
+
` HDF5 Deduplication: ${formatDuration(timing.pass2_hdf5_dedup)}`
|
|
2003
|
+
);
|
|
2004
|
+
}
|
|
2005
|
+
if (timing.pass2_hdf5_write !== void 0) {
|
|
2006
|
+
lines.push(
|
|
2007
|
+
` HDF5 Write I/O: ${formatDuration(timing.pass2_hdf5_write)}`
|
|
1829
2008
|
);
|
|
1830
2009
|
}
|
|
1831
2010
|
const totalTime = (timing.pass1 ?? 0) + (timing.gap ?? 0) + (timing.pass2 ?? 0);
|
|
@@ -2062,7 +2241,6 @@ ${statusText}`;
|
|
|
2062
2241
|
|
|
2063
2242
|
// src/mcp-cli.ts
|
|
2064
2243
|
var ENV_FLAG_MAP = {
|
|
2065
|
-
root: "CODERULE_ROOT",
|
|
2066
2244
|
"data-dir": "CODERULE_DATA_DIR",
|
|
2067
2245
|
"auth-url": "CODERULE_AUTH_URL",
|
|
2068
2246
|
"sync-url": "CODERULE_SYNC_URL",
|
|
@@ -2133,6 +2311,7 @@ function printUsage() {
|
|
|
2133
2311
|
}
|
|
2134
2312
|
function parseArgs(argv) {
|
|
2135
2313
|
let token = process.env.CODERULE_TOKEN;
|
|
2314
|
+
let rootPath;
|
|
2136
2315
|
let clean = false;
|
|
2137
2316
|
let inlineHasher = false;
|
|
2138
2317
|
const env = {};
|
|
@@ -2163,6 +2342,14 @@ function parseArgs(argv) {
|
|
|
2163
2342
|
token = arg.slice("--token=".length);
|
|
2164
2343
|
continue;
|
|
2165
2344
|
}
|
|
2345
|
+
if (arg === "--root") {
|
|
2346
|
+
const value = args.shift();
|
|
2347
|
+
if (!value) {
|
|
2348
|
+
throw new Error("Missing value for --root");
|
|
2349
|
+
}
|
|
2350
|
+
rootPath = value;
|
|
2351
|
+
continue;
|
|
2352
|
+
}
|
|
2166
2353
|
if (arg.startsWith("--")) {
|
|
2167
2354
|
const flag = arg.slice(2);
|
|
2168
2355
|
const envKey = ENV_FLAG_MAP[flag];
|
|
@@ -2195,22 +2382,22 @@ function parseArgs(argv) {
|
|
|
2195
2382
|
"Missing token. Provide via argument or CODERULE_TOKEN environment variable."
|
|
2196
2383
|
);
|
|
2197
2384
|
}
|
|
2198
|
-
return { token, clean, inlineHasher, env };
|
|
2385
|
+
return { token, rootPath, clean, inlineHasher, env };
|
|
2199
2386
|
}
|
|
2200
|
-
async function ensureClean(configToken) {
|
|
2201
|
-
const config = await resolveConfig({ token: configToken });
|
|
2387
|
+
async function ensureClean(configToken, rootPath) {
|
|
2388
|
+
const config = await resolveConfig({ token: configToken, rootPath });
|
|
2202
2389
|
const targets = [
|
|
2203
2390
|
config.dbPath,
|
|
2204
2391
|
`${config.dbPath}-shm`,
|
|
2205
2392
|
`${config.dbPath}-wal`
|
|
2206
2393
|
];
|
|
2207
|
-
await Promise.all(targets.map((target) =>
|
|
2208
|
-
await
|
|
2394
|
+
await Promise.all(targets.map((target) => fs5__default.default.rm(target, { force: true })));
|
|
2395
|
+
await fs5__default.default.rm(path2__default.default.join(config.dataDir, "watch", `${config.rootId}.sqlite-shm`), {
|
|
2209
2396
|
force: true
|
|
2210
2397
|
}).catch(() => {
|
|
2211
2398
|
});
|
|
2212
|
-
const dir =
|
|
2213
|
-
await
|
|
2399
|
+
const dir = path2__default.default.dirname(config.dbPath);
|
|
2400
|
+
await fs5__default.default.mkdir(dir, { recursive: true });
|
|
2214
2401
|
console.log(`Removed scanner database at ${config.dbPath}`);
|
|
2215
2402
|
}
|
|
2216
2403
|
function awaitShutdownSignals() {
|
|
@@ -2241,9 +2428,12 @@ async function main() {
|
|
|
2241
2428
|
process.env[key] = value;
|
|
2242
2429
|
}
|
|
2243
2430
|
if (options.clean) {
|
|
2244
|
-
await ensureClean(options.token);
|
|
2431
|
+
await ensureClean(options.token, options.rootPath);
|
|
2245
2432
|
}
|
|
2246
|
-
const runtime = await bootstrap({
|
|
2433
|
+
const runtime = await bootstrap({
|
|
2434
|
+
token: options.token,
|
|
2435
|
+
rootPath: options.rootPath
|
|
2436
|
+
});
|
|
2247
2437
|
const runner = new ServiceRunner(runtime);
|
|
2248
2438
|
try {
|
|
2249
2439
|
await runner.prepareWatcher(true);
|