graphjin 3.11.3 → 3.12.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/README.md +42 -2
- package/bin/graphjin.js +14 -1
- package/bin/install.js +49 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,6 +61,7 @@ GraphJin started
|
|
|
61
61
|
Web UI: http://localhost:8080/
|
|
62
62
|
GraphQL: http://localhost:8080/api/v1/graphql
|
|
63
63
|
REST API: http://localhost:8080/api/v1/rest/
|
|
64
|
+
Workflows: http://localhost:8080/api/v1/workflows/<name>
|
|
64
65
|
MCP: http://localhost:8080/api/v1/mcp
|
|
65
66
|
|
|
66
67
|
Claude Desktop Configuration
|
|
@@ -155,7 +156,8 @@ Copy paste the Claude Desktop Config provided by `graphjin serve` into the Claud
|
|
|
155
156
|
1. **Connects to database** - Reads your schema automatically
|
|
156
157
|
2. **Discovers relationships** - Foreign keys become navigable joins
|
|
157
158
|
3. **Exposes MCP tools** - Teach any LLM the query syntax
|
|
158
|
-
4. **
|
|
159
|
+
4. **Runs JS workflows** - Chain multiple GraphJin MCP tools in one reusable workflow
|
|
160
|
+
5. **Compiles to SQL** - Every request becomes a single optimized query
|
|
159
161
|
|
|
160
162
|
No resolvers. No ORM. No N+1 queries. Just point and query.
|
|
161
163
|
|
|
@@ -221,7 +223,45 @@ Works from Node.js, Go, or any WebSocket client.
|
|
|
221
223
|
|
|
222
224
|
## MCP Tools
|
|
223
225
|
|
|
224
|
-
GraphJin exposes several tools that guide AI models to write valid queries. Key tools: `list_tables` and `describe_table` for schema discovery, `get_query_syntax` for learning the DSL, `execute_graphql` for running queries, and `execute_saved_query` for production-approved queries.
|
|
226
|
+
GraphJin exposes several tools that guide AI models to write valid queries. Key tools: `list_tables` and `describe_table` for schema discovery, `get_query_syntax` for learning the DSL, `execute_graphql` for running queries, and `execute_saved_query` for production-approved queries.
|
|
227
|
+
|
|
228
|
+
For JS orchestration, use:
|
|
229
|
+
- `get_js_runtime_api` to discover exactly which globals/functions are available inside workflow scripts
|
|
230
|
+
- `execute_workflow` to run `./workflows/<name>.js` with input variables
|
|
231
|
+
|
|
232
|
+
Prompts like `write_query` and `fix_query_error` help models construct and debug queries.
|
|
233
|
+
|
|
234
|
+
## JS Workflows (MCP + REST)
|
|
235
|
+
|
|
236
|
+
Workflows let an LLM run multi-step logic in JavaScript while still using GraphJin MCP tools for DB-aware operations.
|
|
237
|
+
|
|
238
|
+
Create a file in `./workflows`, for example `./workflows/customer_insights.js`:
|
|
239
|
+
|
|
240
|
+
```js
|
|
241
|
+
function main(input) {
|
|
242
|
+
const tables = gj.tools.listTables({});
|
|
243
|
+
const top = gj.tools.executeSavedQuery({
|
|
244
|
+
name: "top_customers",
|
|
245
|
+
variables: { limit: input.limit || 5 }
|
|
246
|
+
});
|
|
247
|
+
return { tables, top };
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Run via MCP
|
|
252
|
+
|
|
253
|
+
Call:
|
|
254
|
+
- `get_js_runtime_api` first (for exact runtime schema)
|
|
255
|
+
- `execute_workflow` with:
|
|
256
|
+
- `name`: workflow file name (with or without `.js`)
|
|
257
|
+
- `variables`: input payload passed to global `input` and `main(input)`
|
|
258
|
+
|
|
259
|
+
### Run via REST
|
|
260
|
+
|
|
261
|
+
- `POST /api/v1/workflows/<name>` with JSON body
|
|
262
|
+
- `GET /api/v1/workflows/<name>?variables={...json...}`
|
|
263
|
+
|
|
264
|
+
Both map variables to the same workflow input object.
|
|
225
265
|
|
|
226
266
|
## Chat Walkthroughs
|
|
227
267
|
|
package/bin/graphjin.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const { spawn } = require('child_process');
|
|
3
3
|
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
4
5
|
|
|
5
6
|
const ext = process.platform === 'win32' ? '.exe' : '';
|
|
6
7
|
const binary = path.join(__dirname, 'graphjin' + ext);
|
|
7
8
|
|
|
9
|
+
if (!fs.existsSync(binary)) {
|
|
10
|
+
console.error(`GraphJin binary not found at: ${binary}`);
|
|
11
|
+
console.error('Try reinstalling: npm install -g graphjin');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
|
|
9
16
|
|
|
10
17
|
child.on('error', (err) => {
|
|
@@ -13,4 +20,10 @@ child.on('error', (err) => {
|
|
|
13
20
|
process.exit(1);
|
|
14
21
|
});
|
|
15
22
|
|
|
16
|
-
child.on('exit', (code) =>
|
|
23
|
+
child.on('exit', (code, signal) => {
|
|
24
|
+
if (signal) {
|
|
25
|
+
console.error(`graphjin terminated by signal: ${signal}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
process.exit(code ?? 0);
|
|
29
|
+
});
|
package/bin/install.js
CHANGED
|
@@ -39,6 +39,29 @@ async function download(url, dest) {
|
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
async function downloadWithFallback(candidates, binDir) {
|
|
43
|
+
let lastErr;
|
|
44
|
+
|
|
45
|
+
for (const candidate of candidates) {
|
|
46
|
+
const archivePath = path.join(binDir, candidate.filename);
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
await download(candidate.url, archivePath);
|
|
50
|
+
return {
|
|
51
|
+
archivePath,
|
|
52
|
+
filename: candidate.filename,
|
|
53
|
+
};
|
|
54
|
+
} catch (err) {
|
|
55
|
+
lastErr = err;
|
|
56
|
+
try {
|
|
57
|
+
fs.unlinkSync(archivePath);
|
|
58
|
+
} catch {}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
throw lastErr || new Error('No download candidates available');
|
|
63
|
+
}
|
|
64
|
+
|
|
42
65
|
async function extract(tarPath, destDir) {
|
|
43
66
|
// Use tar module for extraction
|
|
44
67
|
const tar = require('tar');
|
|
@@ -62,14 +85,28 @@ async function install() {
|
|
|
62
85
|
process.exit(1);
|
|
63
86
|
}
|
|
64
87
|
|
|
65
|
-
const ext = platform === 'windows' ? '.zip' : '.tar.gz';
|
|
66
|
-
const filename = `graphjin_${platform}_${arch}${ext}`;
|
|
67
|
-
const url = `https://github.com/dosco/graphjin/releases/download/v${version}/${filename}`;
|
|
68
|
-
|
|
69
88
|
const binDir = __dirname;
|
|
70
|
-
const archivePath = path.join(binDir, filename);
|
|
71
89
|
const binaryName = platform === 'windows' ? 'graphjin.exe' : 'graphjin';
|
|
72
90
|
const binaryPath = path.join(binDir, binaryName);
|
|
91
|
+
const releaseBase = `https://github.com/dosco/graphjin/releases/download/v${version}`;
|
|
92
|
+
|
|
93
|
+
// New releases include version in the archive name. Keep legacy fallback
|
|
94
|
+
// names to remain backward compatible with older tags.
|
|
95
|
+
const filenames = platform === 'windows'
|
|
96
|
+
? [
|
|
97
|
+
`graphjin_${version}_${platform}_${arch}.tar.gz`,
|
|
98
|
+
`graphjin_${version}_${platform}_${arch}.zip`,
|
|
99
|
+
`graphjin_${platform}_${arch}.tar.gz`,
|
|
100
|
+
`graphjin_${platform}_${arch}.zip`,
|
|
101
|
+
]
|
|
102
|
+
: [
|
|
103
|
+
`graphjin_${version}_${platform}_${arch}.tar.gz`,
|
|
104
|
+
`graphjin_${platform}_${arch}.tar.gz`,
|
|
105
|
+
];
|
|
106
|
+
const candidates = filenames.map((filename) => ({
|
|
107
|
+
filename,
|
|
108
|
+
url: `${releaseBase}/${filename}`,
|
|
109
|
+
}));
|
|
73
110
|
|
|
74
111
|
// Skip if binary already exists
|
|
75
112
|
if (fs.existsSync(binaryPath)) {
|
|
@@ -79,12 +116,17 @@ async function install() {
|
|
|
79
116
|
|
|
80
117
|
console.log(`Downloading GraphJin v${version} for ${platform}/${arch}...`);
|
|
81
118
|
|
|
119
|
+
let archivePath = '';
|
|
120
|
+
let selectedFilename = '';
|
|
121
|
+
|
|
82
122
|
try {
|
|
83
|
-
await
|
|
123
|
+
const selected = await downloadWithFallback(candidates, binDir);
|
|
124
|
+
archivePath = selected.archivePath;
|
|
125
|
+
selectedFilename = selected.filename;
|
|
84
126
|
|
|
85
127
|
console.log('Extracting...');
|
|
86
128
|
|
|
87
|
-
if (platform === 'windows') {
|
|
129
|
+
if (platform === 'windows' && selectedFilename.endsWith('.zip')) {
|
|
88
130
|
// For Windows, use PowerShell to extract
|
|
89
131
|
execSync(`powershell -command "Expand-Archive -Path '${archivePath}' -DestinationPath '${binDir}' -Force"`, {
|
|
90
132
|
stdio: 'inherit',
|