@grafema/cli 0.2.1-beta → 0.2.3-beta
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 +7 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +29 -2
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +75 -28
- package/package.json +3 -3
- package/src/cli.ts +8 -1
- package/src/commands/analyze.ts +30 -3
- package/src/commands/server.ts +85 -30
package/dist/cli.js
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
* @grafema/cli - CLI for Grafema code analysis toolkit
|
|
4
4
|
*/
|
|
5
5
|
import { Command } from 'commander';
|
|
6
|
+
import { readFileSync } from 'fs';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { dirname, join } from 'path';
|
|
6
9
|
import { initCommand } from './commands/init.js';
|
|
7
10
|
import { analyzeCommand } from './commands/analyze.js';
|
|
8
11
|
import { overviewCommand } from './commands/overview.js';
|
|
@@ -20,11 +23,14 @@ import { coverageCommand } from './commands/coverage.js';
|
|
|
20
23
|
import { doctorCommand } from './commands/doctor.js';
|
|
21
24
|
import { schemaCommand } from './commands/schema.js';
|
|
22
25
|
import { explainCommand } from './commands/explain.js';
|
|
26
|
+
// Read version from package.json
|
|
27
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
23
29
|
const program = new Command();
|
|
24
30
|
program
|
|
25
31
|
.name('grafema')
|
|
26
32
|
.description('Grafema code analysis CLI')
|
|
27
|
-
.version(
|
|
33
|
+
.version(pkg.version);
|
|
28
34
|
// Commands in logical order
|
|
29
35
|
program.addCommand(initCommand);
|
|
30
36
|
program.addCommand(analyzeCommand);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgLpC,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgLpC,eAAO,MAAM,cAAc,SAgMvB,CAAC"}
|
package/dist/commands/analyze.js
CHANGED
|
@@ -135,6 +135,7 @@ export const analyzeCommand = new Command('analyze')
|
|
|
135
135
|
.option('--debug', 'Enable debug mode (writes diagnostics.log)')
|
|
136
136
|
.option('--log-level <level>', 'Set log level (silent, errors, warnings, info, debug)')
|
|
137
137
|
.option('--strict', 'Enable strict mode (fail on unresolved references)')
|
|
138
|
+
.option('--auto-start', 'Auto-start RFDB server if not running')
|
|
138
139
|
.addHelpText('after', `
|
|
139
140
|
Examples:
|
|
140
141
|
grafema analyze Analyze current project
|
|
@@ -144,6 +145,9 @@ Examples:
|
|
|
144
145
|
grafema analyze -v Verbose output with progress details
|
|
145
146
|
grafema analyze --debug Write diagnostics.log for debugging
|
|
146
147
|
grafema analyze --strict Fail on unresolved references (debugging)
|
|
148
|
+
grafema analyze --auto-start Auto-start server (useful for CI)
|
|
149
|
+
|
|
150
|
+
Note: Start the server first with: grafema server start
|
|
147
151
|
`)
|
|
148
152
|
.action(async (path, options) => {
|
|
149
153
|
const projectPath = resolve(path);
|
|
@@ -157,8 +161,31 @@ Examples:
|
|
|
157
161
|
const logLevel = getLogLevel(options);
|
|
158
162
|
const logger = createLogger(logLevel);
|
|
159
163
|
log(`Analyzing project: ${projectPath}`);
|
|
160
|
-
|
|
161
|
-
|
|
164
|
+
// Connect to RFDB server
|
|
165
|
+
// Default: require explicit `grafema server start`
|
|
166
|
+
// Use --auto-start for CI or backwards compatibility
|
|
167
|
+
const backend = new RFDBServerBackend({
|
|
168
|
+
dbPath,
|
|
169
|
+
autoStart: options.autoStart ?? false
|
|
170
|
+
});
|
|
171
|
+
try {
|
|
172
|
+
await backend.connect();
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
if (!options.autoStart && err instanceof Error && err.message.includes('not running')) {
|
|
176
|
+
console.error('');
|
|
177
|
+
console.error('RFDB server is not running.');
|
|
178
|
+
console.error('');
|
|
179
|
+
console.error('Start the server first:');
|
|
180
|
+
console.error(' grafema server start');
|
|
181
|
+
console.error('');
|
|
182
|
+
console.error('Or use --auto-start flag:');
|
|
183
|
+
console.error(' grafema analyze --auto-start');
|
|
184
|
+
console.error('');
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
throw err;
|
|
188
|
+
}
|
|
162
189
|
if (options.clear) {
|
|
163
190
|
log('Clearing existing database...');
|
|
164
191
|
await backend.clear();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoHpC,eAAO,MAAM,aAAa,SAaxB,CAAC"}
|
package/dist/commands/server.js
CHANGED
|
@@ -12,18 +12,39 @@ import { existsSync, unlinkSync, writeFileSync, readFileSync } from 'fs';
|
|
|
12
12
|
import { spawn } from 'child_process';
|
|
13
13
|
import { fileURLToPath } from 'url';
|
|
14
14
|
import { setTimeout as sleep } from 'timers/promises';
|
|
15
|
-
import { RFDBClient } from '@grafema/core';
|
|
15
|
+
import { RFDBClient, loadConfig } from '@grafema/core';
|
|
16
16
|
import { exitWithError } from '../utils/errorFormatter.js';
|
|
17
17
|
const __filename = fileURLToPath(import.meta.url);
|
|
18
18
|
const __dirname = dirname(__filename);
|
|
19
19
|
/**
|
|
20
20
|
* Find RFDB server binary in order of preference:
|
|
21
|
-
* 1.
|
|
22
|
-
* 2.
|
|
23
|
-
* 3.
|
|
21
|
+
* 1. Explicit path (from --binary flag or config)
|
|
22
|
+
* 2. Monorepo development (target/release, target/debug)
|
|
23
|
+
* 3. @grafema/rfdb npm package (prebuilt binaries)
|
|
24
|
+
* 4. ~/.local/bin/rfdb-server (user-installed)
|
|
24
25
|
*/
|
|
25
|
-
function findServerBinary() {
|
|
26
|
-
// 1.
|
|
26
|
+
function findServerBinary(explicitPath) {
|
|
27
|
+
// 1. Explicit path from --binary flag or config
|
|
28
|
+
if (explicitPath) {
|
|
29
|
+
const resolved = resolve(explicitPath);
|
|
30
|
+
if (existsSync(resolved)) {
|
|
31
|
+
return resolved;
|
|
32
|
+
}
|
|
33
|
+
// Explicit path specified but not found - this is an error
|
|
34
|
+
console.error(`Specified binary not found: ${resolved}`);
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
// 2. Check packages/rfdb-server in monorepo (for development)
|
|
38
|
+
const projectRoot = join(__dirname, '../../../..');
|
|
39
|
+
const releaseBinary = join(projectRoot, 'packages/rfdb-server/target/release/rfdb-server');
|
|
40
|
+
if (existsSync(releaseBinary)) {
|
|
41
|
+
return releaseBinary;
|
|
42
|
+
}
|
|
43
|
+
const debugBinary = join(projectRoot, 'packages/rfdb-server/target/debug/rfdb-server');
|
|
44
|
+
if (existsSync(debugBinary)) {
|
|
45
|
+
return debugBinary;
|
|
46
|
+
}
|
|
47
|
+
// 3. Check @grafema/rfdb npm package
|
|
27
48
|
try {
|
|
28
49
|
const rfdbPkg = require.resolve('@grafema/rfdb');
|
|
29
50
|
const rfdbDir = dirname(rfdbPkg);
|
|
@@ -47,17 +68,10 @@ function findServerBinary() {
|
|
|
47
68
|
catch {
|
|
48
69
|
// @grafema/rfdb not installed
|
|
49
70
|
}
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (existsSync(releaseBinary)) {
|
|
55
|
-
return releaseBinary;
|
|
56
|
-
}
|
|
57
|
-
// 3. Check debug build
|
|
58
|
-
const debugBinary = join(projectRoot, 'packages/rfdb-server/target/debug/rfdb-server');
|
|
59
|
-
if (existsSync(debugBinary)) {
|
|
60
|
-
return debugBinary;
|
|
71
|
+
// 4. Check ~/.local/bin (user-installed binary for unsupported platforms)
|
|
72
|
+
const homeBinary = join(process.env.HOME || '', '.local', 'bin', 'rfdb-server');
|
|
73
|
+
if (existsSync(homeBinary)) {
|
|
74
|
+
return homeBinary;
|
|
61
75
|
}
|
|
62
76
|
return null;
|
|
63
77
|
}
|
|
@@ -97,16 +111,22 @@ export const serverCommand = new Command('server')
|
|
|
97
111
|
.description('Manage RFDB server lifecycle')
|
|
98
112
|
.addHelpText('after', `
|
|
99
113
|
Examples:
|
|
100
|
-
grafema server start
|
|
101
|
-
grafema server
|
|
102
|
-
grafema server
|
|
103
|
-
grafema server status
|
|
114
|
+
grafema server start Start the RFDB server
|
|
115
|
+
grafema server start --binary /path/to/bin Start with specific binary
|
|
116
|
+
grafema server stop Stop the running server
|
|
117
|
+
grafema server status Check if server is running
|
|
118
|
+
grafema server status --json Server status as JSON
|
|
119
|
+
|
|
120
|
+
Config (in .grafema/config.yaml):
|
|
121
|
+
server:
|
|
122
|
+
binaryPath: /path/to/rfdb-server # Optional: path to binary
|
|
104
123
|
`);
|
|
105
124
|
// grafema server start
|
|
106
125
|
serverCommand
|
|
107
126
|
.command('start')
|
|
108
127
|
.description('Start the RFDB server')
|
|
109
128
|
.option('-p, --project <path>', 'Project path', '.')
|
|
129
|
+
.option('-b, --binary <path>', 'Path to rfdb-server binary')
|
|
110
130
|
.action(async (options) => {
|
|
111
131
|
const projectPath = resolve(options.project);
|
|
112
132
|
const { grafemaDir, socketPath, dbPath, pidPath } = getProjectPaths(projectPath);
|
|
@@ -130,15 +150,41 @@ serverCommand
|
|
|
130
150
|
if (existsSync(socketPath)) {
|
|
131
151
|
unlinkSync(socketPath);
|
|
132
152
|
}
|
|
133
|
-
//
|
|
134
|
-
|
|
153
|
+
// Determine binary path: CLI flag > config > auto-detect
|
|
154
|
+
let binaryPath = null;
|
|
155
|
+
if (options.binary) {
|
|
156
|
+
// Explicit --binary flag
|
|
157
|
+
binaryPath = findServerBinary(options.binary);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// Try to read from config
|
|
161
|
+
try {
|
|
162
|
+
const config = loadConfig(projectPath);
|
|
163
|
+
const serverConfig = config.server;
|
|
164
|
+
if (serverConfig?.binaryPath) {
|
|
165
|
+
binaryPath = findServerBinary(serverConfig.binaryPath);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// Config not found or invalid - continue with auto-detect
|
|
170
|
+
}
|
|
171
|
+
// Auto-detect if not specified
|
|
172
|
+
if (!binaryPath) {
|
|
173
|
+
binaryPath = findServerBinary();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
135
176
|
if (!binaryPath) {
|
|
136
177
|
exitWithError('RFDB server binary not found', [
|
|
137
|
-
'
|
|
138
|
-
'Or
|
|
178
|
+
'Specify path: grafema server start --binary /path/to/rfdb-server',
|
|
179
|
+
'Or add to config.yaml:',
|
|
180
|
+
' server:',
|
|
181
|
+
' binaryPath: /path/to/rfdb-server',
|
|
182
|
+
'Or install: npm install @grafema/rfdb',
|
|
183
|
+
'Or build: cargo build --release && cp target/release/rfdb-server ~/.local/bin/'
|
|
139
184
|
]);
|
|
140
185
|
}
|
|
141
186
|
console.log(`Starting RFDB server...`);
|
|
187
|
+
console.log(` Binary: ${binaryPath}`);
|
|
142
188
|
console.log(` Database: ${dbPath}`);
|
|
143
189
|
console.log(` Socket: ${socketPath}`);
|
|
144
190
|
// Start server
|
|
@@ -152,16 +198,17 @@ serverCommand
|
|
|
152
198
|
if (serverProcess.pid) {
|
|
153
199
|
writeFileSync(pidPath, String(serverProcess.pid));
|
|
154
200
|
}
|
|
155
|
-
// Wait for socket to appear
|
|
201
|
+
// Wait for socket to appear (increased timeout for slow systems)
|
|
156
202
|
let attempts = 0;
|
|
157
|
-
while (!existsSync(socketPath) && attempts <
|
|
203
|
+
while (!existsSync(socketPath) && attempts < 100) {
|
|
158
204
|
await sleep(100);
|
|
159
205
|
attempts++;
|
|
160
206
|
}
|
|
161
207
|
if (!existsSync(socketPath)) {
|
|
162
208
|
exitWithError('Server failed to start', [
|
|
163
209
|
'Check if database path is valid',
|
|
164
|
-
'Check server logs for errors'
|
|
210
|
+
'Check server logs for errors',
|
|
211
|
+
`Binary used: ${binaryPath}`
|
|
165
212
|
]);
|
|
166
213
|
}
|
|
167
214
|
// Verify server is responsive
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafema/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3-beta",
|
|
4
4
|
"description": "CLI for Grafema code analysis toolkit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"ink-text-input": "^6.0.0",
|
|
38
38
|
"react": "^19.2.3",
|
|
39
39
|
"yaml": "^2.8.2",
|
|
40
|
-
"@grafema/core": "0.2.
|
|
41
|
-
"@grafema/types": "0.2.
|
|
40
|
+
"@grafema/core": "0.2.3-beta",
|
|
41
|
+
"@grafema/types": "0.2.1-beta"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^25.0.8",
|
package/src/cli.ts
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Command } from 'commander';
|
|
7
|
+
import { readFileSync } from 'fs';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname, join } from 'path';
|
|
7
10
|
import { initCommand } from './commands/init.js';
|
|
8
11
|
import { analyzeCommand } from './commands/analyze.js';
|
|
9
12
|
import { overviewCommand } from './commands/overview.js';
|
|
@@ -22,12 +25,16 @@ import { doctorCommand } from './commands/doctor.js';
|
|
|
22
25
|
import { schemaCommand } from './commands/schema.js';
|
|
23
26
|
import { explainCommand } from './commands/explain.js';
|
|
24
27
|
|
|
28
|
+
// Read version from package.json
|
|
29
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
30
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
31
|
+
|
|
25
32
|
const program = new Command();
|
|
26
33
|
|
|
27
34
|
program
|
|
28
35
|
.name('grafema')
|
|
29
36
|
.description('Grafema code analysis CLI')
|
|
30
|
-
.version(
|
|
37
|
+
.version(pkg.version);
|
|
31
38
|
|
|
32
39
|
// Commands in logical order
|
|
33
40
|
program.addCommand(initCommand);
|
package/src/commands/analyze.ts
CHANGED
|
@@ -189,6 +189,7 @@ export const analyzeCommand = new Command('analyze')
|
|
|
189
189
|
.option('--debug', 'Enable debug mode (writes diagnostics.log)')
|
|
190
190
|
.option('--log-level <level>', 'Set log level (silent, errors, warnings, info, debug)')
|
|
191
191
|
.option('--strict', 'Enable strict mode (fail on unresolved references)')
|
|
192
|
+
.option('--auto-start', 'Auto-start RFDB server if not running')
|
|
192
193
|
.addHelpText('after', `
|
|
193
194
|
Examples:
|
|
194
195
|
grafema analyze Analyze current project
|
|
@@ -198,8 +199,11 @@ Examples:
|
|
|
198
199
|
grafema analyze -v Verbose output with progress details
|
|
199
200
|
grafema analyze --debug Write diagnostics.log for debugging
|
|
200
201
|
grafema analyze --strict Fail on unresolved references (debugging)
|
|
202
|
+
grafema analyze --auto-start Auto-start server (useful for CI)
|
|
203
|
+
|
|
204
|
+
Note: Start the server first with: grafema server start
|
|
201
205
|
`)
|
|
202
|
-
.action(async (path: string, options: { service?: string; entrypoint?: string; clear?: boolean; quiet?: boolean; verbose?: boolean; debug?: boolean; logLevel?: string; strict?: boolean }) => {
|
|
206
|
+
.action(async (path: string, options: { service?: string; entrypoint?: string; clear?: boolean; quiet?: boolean; verbose?: boolean; debug?: boolean; logLevel?: string; strict?: boolean; autoStart?: boolean }) => {
|
|
203
207
|
const projectPath = resolve(path);
|
|
204
208
|
const grafemaDir = join(projectPath, '.grafema');
|
|
205
209
|
const dbPath = join(grafemaDir, 'graph.rfdb');
|
|
@@ -216,8 +220,31 @@ Examples:
|
|
|
216
220
|
|
|
217
221
|
log(`Analyzing project: ${projectPath}`);
|
|
218
222
|
|
|
219
|
-
|
|
220
|
-
|
|
223
|
+
// Connect to RFDB server
|
|
224
|
+
// Default: require explicit `grafema server start`
|
|
225
|
+
// Use --auto-start for CI or backwards compatibility
|
|
226
|
+
const backend = new RFDBServerBackend({
|
|
227
|
+
dbPath,
|
|
228
|
+
autoStart: options.autoStart ?? false
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
try {
|
|
232
|
+
await backend.connect();
|
|
233
|
+
} catch (err) {
|
|
234
|
+
if (!options.autoStart && err instanceof Error && err.message.includes('not running')) {
|
|
235
|
+
console.error('');
|
|
236
|
+
console.error('RFDB server is not running.');
|
|
237
|
+
console.error('');
|
|
238
|
+
console.error('Start the server first:');
|
|
239
|
+
console.error(' grafema server start');
|
|
240
|
+
console.error('');
|
|
241
|
+
console.error('Or use --auto-start flag:');
|
|
242
|
+
console.error(' grafema analyze --auto-start');
|
|
243
|
+
console.error('');
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
throw err;
|
|
247
|
+
}
|
|
221
248
|
|
|
222
249
|
if (options.clear) {
|
|
223
250
|
log('Clearing existing database...');
|
package/src/commands/server.ts
CHANGED
|
@@ -13,20 +13,49 @@ import { existsSync, unlinkSync, writeFileSync, readFileSync } from 'fs';
|
|
|
13
13
|
import { spawn } from 'child_process';
|
|
14
14
|
import { fileURLToPath } from 'url';
|
|
15
15
|
import { setTimeout as sleep } from 'timers/promises';
|
|
16
|
-
import { RFDBClient } from '@grafema/core';
|
|
16
|
+
import { RFDBClient, loadConfig } from '@grafema/core';
|
|
17
17
|
import { exitWithError } from '../utils/errorFormatter.js';
|
|
18
18
|
|
|
19
19
|
const __filename = fileURLToPath(import.meta.url);
|
|
20
20
|
const __dirname = dirname(__filename);
|
|
21
21
|
|
|
22
|
+
// Extend config type for server settings
|
|
23
|
+
interface ServerConfig {
|
|
24
|
+
binaryPath?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
22
27
|
/**
|
|
23
28
|
* Find RFDB server binary in order of preference:
|
|
24
|
-
* 1.
|
|
25
|
-
* 2.
|
|
26
|
-
* 3.
|
|
29
|
+
* 1. Explicit path (from --binary flag or config)
|
|
30
|
+
* 2. Monorepo development (target/release, target/debug)
|
|
31
|
+
* 3. @grafema/rfdb npm package (prebuilt binaries)
|
|
32
|
+
* 4. ~/.local/bin/rfdb-server (user-installed)
|
|
27
33
|
*/
|
|
28
|
-
function findServerBinary(): string | null {
|
|
29
|
-
// 1.
|
|
34
|
+
function findServerBinary(explicitPath?: string): string | null {
|
|
35
|
+
// 1. Explicit path from --binary flag or config
|
|
36
|
+
if (explicitPath) {
|
|
37
|
+
const resolved = resolve(explicitPath);
|
|
38
|
+
if (existsSync(resolved)) {
|
|
39
|
+
return resolved;
|
|
40
|
+
}
|
|
41
|
+
// Explicit path specified but not found - this is an error
|
|
42
|
+
console.error(`Specified binary not found: ${resolved}`);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 2. Check packages/rfdb-server in monorepo (for development)
|
|
47
|
+
const projectRoot = join(__dirname, '../../../..');
|
|
48
|
+
const releaseBinary = join(projectRoot, 'packages/rfdb-server/target/release/rfdb-server');
|
|
49
|
+
if (existsSync(releaseBinary)) {
|
|
50
|
+
return releaseBinary;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const debugBinary = join(projectRoot, 'packages/rfdb-server/target/debug/rfdb-server');
|
|
54
|
+
if (existsSync(debugBinary)) {
|
|
55
|
+
return debugBinary;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 3. Check @grafema/rfdb npm package
|
|
30
59
|
try {
|
|
31
60
|
const rfdbPkg = require.resolve('@grafema/rfdb');
|
|
32
61
|
const rfdbDir = dirname(rfdbPkg);
|
|
@@ -50,18 +79,10 @@ function findServerBinary(): string | null {
|
|
|
50
79
|
// @grafema/rfdb not installed
|
|
51
80
|
}
|
|
52
81
|
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (existsSync(releaseBinary)) {
|
|
58
|
-
return releaseBinary;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// 3. Check debug build
|
|
62
|
-
const debugBinary = join(projectRoot, 'packages/rfdb-server/target/debug/rfdb-server');
|
|
63
|
-
if (existsSync(debugBinary)) {
|
|
64
|
-
return debugBinary;
|
|
82
|
+
// 4. Check ~/.local/bin (user-installed binary for unsupported platforms)
|
|
83
|
+
const homeBinary = join(process.env.HOME || '', '.local', 'bin', 'rfdb-server');
|
|
84
|
+
if (existsSync(homeBinary)) {
|
|
85
|
+
return homeBinary;
|
|
65
86
|
}
|
|
66
87
|
|
|
67
88
|
return null;
|
|
@@ -106,10 +127,15 @@ export const serverCommand = new Command('server')
|
|
|
106
127
|
.description('Manage RFDB server lifecycle')
|
|
107
128
|
.addHelpText('after', `
|
|
108
129
|
Examples:
|
|
109
|
-
grafema server start
|
|
110
|
-
grafema server
|
|
111
|
-
grafema server
|
|
112
|
-
grafema server status
|
|
130
|
+
grafema server start Start the RFDB server
|
|
131
|
+
grafema server start --binary /path/to/bin Start with specific binary
|
|
132
|
+
grafema server stop Stop the running server
|
|
133
|
+
grafema server status Check if server is running
|
|
134
|
+
grafema server status --json Server status as JSON
|
|
135
|
+
|
|
136
|
+
Config (in .grafema/config.yaml):
|
|
137
|
+
server:
|
|
138
|
+
binaryPath: /path/to/rfdb-server # Optional: path to binary
|
|
113
139
|
`);
|
|
114
140
|
|
|
115
141
|
// grafema server start
|
|
@@ -117,7 +143,8 @@ serverCommand
|
|
|
117
143
|
.command('start')
|
|
118
144
|
.description('Start the RFDB server')
|
|
119
145
|
.option('-p, --project <path>', 'Project path', '.')
|
|
120
|
-
.
|
|
146
|
+
.option('-b, --binary <path>', 'Path to rfdb-server binary')
|
|
147
|
+
.action(async (options: { project: string; binary?: string }) => {
|
|
121
148
|
const projectPath = resolve(options.project);
|
|
122
149
|
const { grafemaDir, socketPath, dbPath, pidPath } = getProjectPaths(projectPath);
|
|
123
150
|
|
|
@@ -144,16 +171,43 @@ serverCommand
|
|
|
144
171
|
unlinkSync(socketPath);
|
|
145
172
|
}
|
|
146
173
|
|
|
147
|
-
//
|
|
148
|
-
|
|
174
|
+
// Determine binary path: CLI flag > config > auto-detect
|
|
175
|
+
let binaryPath: string | null = null;
|
|
176
|
+
|
|
177
|
+
if (options.binary) {
|
|
178
|
+
// Explicit --binary flag
|
|
179
|
+
binaryPath = findServerBinary(options.binary);
|
|
180
|
+
} else {
|
|
181
|
+
// Try to read from config
|
|
182
|
+
try {
|
|
183
|
+
const config = loadConfig(projectPath);
|
|
184
|
+
const serverConfig = (config as unknown as { server?: ServerConfig }).server;
|
|
185
|
+
if (serverConfig?.binaryPath) {
|
|
186
|
+
binaryPath = findServerBinary(serverConfig.binaryPath);
|
|
187
|
+
}
|
|
188
|
+
} catch {
|
|
189
|
+
// Config not found or invalid - continue with auto-detect
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Auto-detect if not specified
|
|
193
|
+
if (!binaryPath) {
|
|
194
|
+
binaryPath = findServerBinary();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
149
198
|
if (!binaryPath) {
|
|
150
199
|
exitWithError('RFDB server binary not found', [
|
|
151
|
-
'
|
|
152
|
-
'Or
|
|
200
|
+
'Specify path: grafema server start --binary /path/to/rfdb-server',
|
|
201
|
+
'Or add to config.yaml:',
|
|
202
|
+
' server:',
|
|
203
|
+
' binaryPath: /path/to/rfdb-server',
|
|
204
|
+
'Or install: npm install @grafema/rfdb',
|
|
205
|
+
'Or build: cargo build --release && cp target/release/rfdb-server ~/.local/bin/'
|
|
153
206
|
]);
|
|
154
207
|
}
|
|
155
208
|
|
|
156
209
|
console.log(`Starting RFDB server...`);
|
|
210
|
+
console.log(` Binary: ${binaryPath}`);
|
|
157
211
|
console.log(` Database: ${dbPath}`);
|
|
158
212
|
console.log(` Socket: ${socketPath}`);
|
|
159
213
|
|
|
@@ -171,9 +225,9 @@ serverCommand
|
|
|
171
225
|
writeFileSync(pidPath, String(serverProcess.pid));
|
|
172
226
|
}
|
|
173
227
|
|
|
174
|
-
// Wait for socket to appear
|
|
228
|
+
// Wait for socket to appear (increased timeout for slow systems)
|
|
175
229
|
let attempts = 0;
|
|
176
|
-
while (!existsSync(socketPath) && attempts <
|
|
230
|
+
while (!existsSync(socketPath) && attempts < 100) {
|
|
177
231
|
await sleep(100);
|
|
178
232
|
attempts++;
|
|
179
233
|
}
|
|
@@ -181,7 +235,8 @@ serverCommand
|
|
|
181
235
|
if (!existsSync(socketPath)) {
|
|
182
236
|
exitWithError('Server failed to start', [
|
|
183
237
|
'Check if database path is valid',
|
|
184
|
-
'Check server logs for errors'
|
|
238
|
+
'Check server logs for errors',
|
|
239
|
+
`Binary used: ${binaryPath}`
|
|
185
240
|
]);
|
|
186
241
|
}
|
|
187
242
|
|