gcyphrq 0.12.6

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.
@@ -0,0 +1,416 @@
1
+ /* === Reset & Base === */
2
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
3
+
4
+ :root {
5
+ --color-bg: #ffffff;
6
+ --color-bg-secondary: #f8f9fb;
7
+ --color-text: #1a1a2e;
8
+ --color-text-secondary: #555;
9
+ --color-accent: #4f46e5;
10
+ --color-accent-light: #eef2ff;
11
+ --color-border: #e2e8f0;
12
+ --color-code-bg: #f4f5f7;
13
+ --color-code-text: #1f2937;
14
+ --color-success: #16a34a;
15
+ --color-warning: #f59e0b;
16
+ --color-danger: #dc2626;
17
+ --max-width: 1100px;
18
+ --header-height: 64px;
19
+ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
20
+ --font-mono: "SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", Consolas, monospace;
21
+ }
22
+
23
+ html { scroll-behavior: smooth; font-size: 16px; }
24
+
25
+ body {
26
+ font-family: var(--font-sans);
27
+ color: var(--color-text);
28
+ background: var(--color-bg);
29
+ line-height: 1.7;
30
+ min-height: 100vh;
31
+ display: flex;
32
+ flex-direction: column;
33
+ }
34
+
35
+ a { color: var(--color-accent); text-decoration: none; }
36
+ a:hover { text-decoration: underline; }
37
+
38
+ .container { max-width: var(--max-width); margin: 0 auto; padding: 0 2.5rem; }
39
+
40
+ @media (max-width: 768px) {
41
+ .container { padding: 0 1.25rem; }
42
+ }
43
+
44
+ /* === Header === */
45
+ .site-header {
46
+ position: sticky;
47
+ top: 0;
48
+ z-index: 100;
49
+ background: rgba(255, 255, 255, 0.92);
50
+ backdrop-filter: blur(12px);
51
+ border-bottom: 1px solid var(--color-border);
52
+ height: var(--header-height);
53
+ }
54
+
55
+ .site-header .container {
56
+ display: flex;
57
+ align-items: center;
58
+ justify-content: space-between;
59
+ height: 100%;
60
+ }
61
+
62
+ .logo {
63
+ display: flex;
64
+ align-items: center;
65
+ gap: 0.5rem;
66
+ font-weight: 700;
67
+ font-size: 1.25rem;
68
+ color: var(--color-text);
69
+ text-decoration: none;
70
+ }
71
+
72
+ .logo:hover { text-decoration: none; }
73
+
74
+ .logo-icon { font-size: 1.5rem; color: var(--color-accent); }
75
+ .logo-text small { font-weight: 400; font-size: 0.75rem; color: var(--color-text-secondary); margin-left: 0.25rem; }
76
+
77
+ /* === Navigation === */
78
+ .main-nav ul {
79
+ display: flex;
80
+ list-style: none;
81
+ gap: 0.25rem;
82
+ }
83
+
84
+ .main-nav a {
85
+ display: block;
86
+ padding: 0.4rem 0.85rem;
87
+ border-radius: 6px;
88
+ font-size: 0.9rem;
89
+ font-weight: 500;
90
+ color: var(--color-text-secondary);
91
+ transition: background 0.15s, color 0.15s;
92
+ }
93
+
94
+ .main-nav a:hover, .main-nav a.active {
95
+ background: var(--color-accent-light);
96
+ color: var(--color-accent);
97
+ text-decoration: none;
98
+ }
99
+
100
+ .external-icon { font-size: 0.75rem; opacity: 0.6; }
101
+
102
+ .nav-toggle { display: none; }
103
+ .nav-toggle-label { display: none; flex-direction: column; gap: 4px; cursor: pointer; padding: 0.5rem; }
104
+ .nav-toggle-label span { display: block; width: 20px; height: 2px; background: var(--color-text); border-radius: 1px; }
105
+
106
+ @media (max-width: 768px) {
107
+ .nav-toggle-label { display: flex; }
108
+ .main-nav ul {
109
+ display: none;
110
+ flex-direction: column;
111
+ position: absolute;
112
+ top: var(--header-height);
113
+ left: 0;
114
+ right: 0;
115
+ background: var(--color-bg);
116
+ border-bottom: 1px solid var(--color-border);
117
+ padding: 0.5rem;
118
+ gap: 0;
119
+ }
120
+ .nav-toggle:checked ~ ul { display: flex; }
121
+ .main-nav a { padding: 0.6rem 0.85rem; }
122
+ }
123
+
124
+ /* === Content === */
125
+ .content { flex: 1; padding: 3rem 0; }
126
+
127
+ .content h1 { font-size: 2.25rem; font-weight: 800; line-height: 1.2; margin-bottom: 0.5rem; }
128
+ .content h2 { font-size: 1.6rem; font-weight: 700; margin-top: 2.5rem; margin-bottom: 0.75rem; padding-bottom: 0.4rem; border-bottom: 1px solid var(--color-border); }
129
+ .content h3 { font-size: 1.25rem; font-weight: 600; margin-top: 2rem; margin-bottom: 0.5rem; }
130
+ .content h4 { font-size: 1.1rem; font-weight: 600; margin-top: 1.5rem; margin-bottom: 0.5rem; }
131
+
132
+ .content p { margin-bottom: 1.25rem; }
133
+ .content ul, .content ol { margin-bottom: 1.25rem; padding-left: 1.5rem; }
134
+ .content li { margin-bottom: 0.35rem; }
135
+
136
+ .content strong { font-weight: 600; }
137
+
138
+ .content table {
139
+ width: 100%;
140
+ border-collapse: collapse;
141
+ margin-bottom: 1.5rem;
142
+ font-size: 0.9rem;
143
+ }
144
+
145
+ @media (max-width: 768px) {
146
+ .content table {
147
+ display: block;
148
+ overflow-x: auto;
149
+ }
150
+ }
151
+
152
+ .content th {
153
+ text-align: left;
154
+ padding: 0.6rem 0.8rem;
155
+ background: var(--color-bg-secondary);
156
+ font-weight: 600;
157
+ border-bottom: 2px solid var(--color-border);
158
+ }
159
+
160
+ .content td {
161
+ padding: 0.55rem 0.8rem;
162
+ border-bottom: 1px solid var(--color-border);
163
+ }
164
+
165
+ .content tr:hover td { background: var(--color-bg-secondary); }
166
+
167
+ /* Inline code */
168
+ .content p code, .content li code, .content td code {
169
+ background: var(--color-accent-light);
170
+ color: var(--color-accent);
171
+ padding: 0.15em 0.4em;
172
+ border-radius: 4px;
173
+ font-size: 0.88em;
174
+ font-family: var(--font-mono);
175
+ }
176
+
177
+ /* Code blocks */
178
+ .highlight, pre.highlight {
179
+ background: var(--color-code-bg) !important;
180
+ border-radius: 4px;
181
+ margin: 1rem 0;
182
+ overflow-x: auto;
183
+ }
184
+
185
+ .highlight code, pre.highlight code {
186
+ color: var(--color-code-text) !important;
187
+ background: none !important;
188
+ padding: 0 !important;
189
+ font-size: 0.84rem;
190
+ line-height: 1.5;
191
+ }
192
+
193
+ .highlight { padding: 0.6rem; }
194
+
195
+ /* Copy button */
196
+ .code-block-wrapper {
197
+ position: relative;
198
+ margin: 1rem 0;
199
+ }
200
+
201
+ .code-block-wrapper .highlight {
202
+ margin: 0;
203
+ }
204
+
205
+ .code-copy-btn {
206
+ position: absolute;
207
+ top: 0.4rem;
208
+ right: 0.4rem;
209
+ display: flex;
210
+ align-items: center;
211
+ justify-content: center;
212
+ width: 26px;
213
+ height: 26px;
214
+ padding: 0;
215
+ background: rgba(0,0,0,0.04);
216
+ border: 1px solid rgba(0,0,0,0.08);
217
+ border-radius: 4px;
218
+ color: rgba(0,0,0,0.35);
219
+ cursor: pointer;
220
+ opacity: 0;
221
+ transition: opacity 0.15s, color 0.15s, background 0.15s;
222
+ }
223
+
224
+ .code-block-wrapper:hover .code-copy-btn {
225
+ opacity: 1;
226
+ }
227
+
228
+ /* Always visible on touch devices where :hover doesn't work */
229
+ @media (hover: none) {
230
+ .code-copy-btn {
231
+ opacity: 1;
232
+ }
233
+ }
234
+
235
+ .code-copy-btn:hover {
236
+ color: rgba(0,0,0,0.7);
237
+ background: rgba(0,0,0,0.07);
238
+ }
239
+
240
+ .code-copy-btn.copied {
241
+ color: #059669;
242
+ border-color: rgba(5,150,105,0.3);
243
+ }
244
+
245
+ /* Cypher keyword highlighting */
246
+ .highlight .cy-kw { color: #7c3aed; font-weight: 600; }
247
+ .highlight .cy-fn { color: #2563eb; }
248
+ .highlight .cy-label { color: #d97706; }
249
+ .highlight .cy-rel { color: #0d9488; font-weight: 600; }
250
+ .highlight .cy-str { color: #059669; }
251
+ .highlight .cy-num { color: #d97706; }
252
+ .highlight .cy-cmt { color: #52525b; font-style: italic; }
253
+
254
+ /* Rouge syntax highlighting (light theme) */
255
+ .highlight .c, .highlight .c1, .highlight .cm, .highlight .cp { color: #52525b; font-style: italic; }
256
+ .highlight .err { color: #dc2626; }
257
+ .highlight .k, .highlight .kd, .highlight .kn, .highlight .kp, .highlight .kr { color: #7c3aed; }
258
+ .highlight .kt { color: #d97706; }
259
+ .highlight .m, .highlight .mf, .highlight .mh, .highlight .mi { color: #d97706; }
260
+ .highlight .s, .highlight .s1, .highlight .s2, .highlight .sc, .highlight .se, .highlight .sh, .highlight .si, .highlight .sx { color: #059669; }
261
+ .highlight .n, .highlight .nn, .highlight .py { color: #1f2937; }
262
+ .highlight .na, .highlight .nc, .highlight .nd, .highlight .ne, .highlight .nf { color: #2563eb; }
263
+ .highlight .nl, .highlight .nv, .highlight .vc, .highlight .vg, .highlight .vi { color: #dc2626; }
264
+ .highlight .o { color: #0d9488; }
265
+ .highlight .p { color: #6b7280; }
266
+ .highlight .ow { color: #7c3aed; }
267
+ .highlight .e { color: #dc2626; }
268
+ .highlight .gu, .highlight .gd { color: #dc2626; }
269
+ .highlight .gi { color: #059669; }
270
+
271
+ /* === Hero (home page) === */
272
+ .hero {
273
+ text-align: center;
274
+ padding: 3rem 0 2rem;
275
+ }
276
+
277
+ .hero h1 {
278
+ font-size: 3rem;
279
+ font-weight: 800;
280
+ margin-bottom: 1rem;
281
+ background: linear-gradient(135deg, var(--color-accent), #7c3aed);
282
+ -webkit-background-clip: text;
283
+ -webkit-text-fill-color: transparent;
284
+ background-clip: text;
285
+ }
286
+
287
+ .hero .tagline {
288
+ font-size: 1.2rem;
289
+ color: var(--color-text-secondary);
290
+ max-width: 600px;
291
+ margin: 0 auto 2rem;
292
+ }
293
+
294
+ .hero-actions {
295
+ display: flex;
296
+ gap: 1rem;
297
+ justify-content: center;
298
+ flex-wrap: wrap;
299
+ margin-bottom: 2rem;
300
+ }
301
+
302
+ .btn {
303
+ display: inline-flex;
304
+ align-items: center;
305
+ gap: 0.4rem;
306
+ padding: 0.7rem 1.5rem;
307
+ border-radius: 8px;
308
+ font-weight: 600;
309
+ font-size: 0.95rem;
310
+ transition: transform 0.15s, box-shadow 0.15s;
311
+ }
312
+
313
+ .btn:hover { transform: translateY(-1px); text-decoration: none; }
314
+
315
+ .btn-primary {
316
+ background: var(--color-accent);
317
+ color: #fff;
318
+ box-shadow: 0 2px 8px rgba(79, 70, 229, 0.3);
319
+ }
320
+
321
+ .btn-primary:hover { box-shadow: 0 4px 16px rgba(79, 70, 229, 0.4); }
322
+
323
+ .btn-secondary {
324
+ background: var(--color-bg-secondary);
325
+ color: var(--color-text);
326
+ border: 1px solid var(--color-border);
327
+ }
328
+
329
+ .btn-secondary:hover { border-color: var(--color-accent); }
330
+
331
+ /* === Feature Cards === */
332
+ .feature-grid {
333
+ display: grid;
334
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
335
+ gap: 1.25rem;
336
+ margin: 2rem 0;
337
+ }
338
+
339
+ .feature-card {
340
+ background: var(--color-bg-secondary);
341
+ border: 1px solid var(--color-border);
342
+ border-radius: 6px;
343
+ padding: 1rem 1.15rem;
344
+ transition: box-shadow 0.2s, border-color 0.2s;
345
+ }
346
+
347
+ .feature-card:hover {
348
+ border-color: var(--color-accent);
349
+ box-shadow: 0 4px 12px rgba(79, 70, 229, 0.08);
350
+ }
351
+
352
+ .feature-card h3 {
353
+ margin-top: 0;
354
+ margin-bottom: 0.5rem;
355
+ font-size: 1.1rem;
356
+ }
357
+
358
+ .feature-card p {
359
+ color: var(--color-text-secondary);
360
+ font-size: 0.92rem;
361
+ margin-bottom: 0;
362
+ }
363
+
364
+ /* === Callout === */
365
+ .callout {
366
+ border-left: 3px solid var(--color-accent);
367
+ background: var(--color-accent-light);
368
+ padding: 0.6rem 0.85rem;
369
+ border-radius: 0 4px 4px 0;
370
+ margin: 1.25rem 0;
371
+ }
372
+
373
+ .callout p { margin-bottom: 0; }
374
+ .callout p + p { margin-top: 0.5rem; }
375
+
376
+ /* === Breadcrumb === */
377
+ .breadcrumb {
378
+ font-size: 0.85rem;
379
+ color: var(--color-text-secondary);
380
+ margin-bottom: 1rem;
381
+ }
382
+
383
+ .breadcrumb a { color: var(--color-text-secondary); }
384
+ .breadcrumb a:hover { color: var(--color-accent); }
385
+ .breadcrumb span { margin: 0 0.4rem; }
386
+
387
+ /* === Status badges === */
388
+ .badge {
389
+ display: inline-block;
390
+ padding: 0.15em 0.5em;
391
+ border-radius: 4px;
392
+ font-size: 0.8rem;
393
+ font-weight: 600;
394
+ vertical-align: middle;
395
+ }
396
+
397
+ .badge-success { background: #dcfce7; color: var(--color-success); }
398
+ .badge-warning { background: #fef3c7; color: var(--color-warning); }
399
+ .badge-danger { background: #fee2e2; color: var(--color-danger); }
400
+
401
+ /* === Footer === */
402
+ .site-footer {
403
+ border-top: 1px solid var(--color-border);
404
+ padding: 2rem 0;
405
+ text-align: center;
406
+ font-size: 0.85rem;
407
+ color: var(--color-text-secondary);
408
+ }
409
+
410
+ .site-footer a { color: var(--color-text-secondary); }
411
+ .site-footer a:hover { color: var(--color-accent); }
412
+
413
+ /* === Scrollbar === */
414
+ .highlight::-webkit-scrollbar { height: 6px; }
415
+ .highlight::-webkit-scrollbar-track { background: transparent; }
416
+ .highlight::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); border-radius: 3px; }
package/docs/cli.md ADDED
@@ -0,0 +1,115 @@
1
+ ---
2
+ layout: default
3
+ title: CLI Reference
4
+ description: Command-line interface reference for gcyphrq.
5
+ ---
6
+
7
+ <div class="breadcrumb">
8
+ <a href="{{ '/' | relative_url }}">Home</a> <span>›</span> CLI Reference
9
+ </div>
10
+
11
+ # CLI Reference
12
+
13
+ The `gcyphrq` CLI executes Cypher graph queries against a JSON graph file and outputs raw JSON results to stdout.
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ gcyphrq [options]
19
+ ```
20
+
21
+ ## Options
22
+
23
+ | Option | Description |
24
+ |---|---|
25
+ | `-e, --expr <query>` | Cypher query expression (**required**) |
26
+ | `-g, --graph <file>` | Path to a JSON graph file, or `"-"` to read from stdin (**required**) |
27
+ | `-h, --help` | Show help message |
28
+
29
+ Both `-e` and `-g` are required. The tool exits with code 1 and prints to stderr if either is missing.
30
+
31
+ ## Loading a Graph
32
+
33
+ ### From a file
34
+
35
+ ```bash
36
+ gcyphrq -g examples/social-graph.json -e 'MATCH (u:User) RETURN u'
37
+ ```
38
+
39
+ ### From stdin
40
+
41
+ ```bash
42
+ cat my-graph.json | gcyphrq -g - -e 'MATCH (u:User) RETURN u'
43
+ ```
44
+
45
+ ## Output Format
46
+
47
+ The CLI outputs **raw JSON** — a JSON array of result objects with no prefixes, no markdown, and no extra text. Stdout is pipe-friendly for downstream tools like `jq`:
48
+
49
+ ```bash
50
+ gcyphrq -g examples/social-graph.json -e 'MATCH (u:User) RETURN u.name' | jq '.[0].name'
51
+ ```
52
+
53
+ ## Error Handling
54
+
55
+ All errors are printed to **stderr** with an `Error: ` prefix, and the process exits with code 1:
56
+
57
+ ```
58
+ Error: Invalid graph data: missing "nodes" array
59
+ ```
60
+
61
+ This separation of stdout (results) and stderr (errors) ensures you can safely pipe results without capturing error messages.
62
+
63
+ ## Common Patterns
64
+
65
+ ### Quick inspection
66
+
67
+ List all nodes of a specific label:
68
+
69
+ ```bash
70
+ gcyphrq -g graph.json -e 'MATCH (s:Service) RETURN s.name'
71
+ ```
72
+
73
+ ### Filter with WHERE (on WITH)
74
+
75
+ ```bash
76
+ gcyphrq -g graph.json -e 'MATCH (s:Service) WITH s WHERE s.name CONTAINS "api" RETURN s.name'
77
+ ```
78
+
79
+ ### Aggregation
80
+
81
+ ```bash
82
+ gcyphrq -g graph.json -e 'MATCH (n) RETURN count(n) AS totalNodes'
83
+ ```
84
+
85
+ ### Top-N with ORDER BY + LIMIT
86
+
87
+ ```bash
88
+ gcyphrq -g graph.json -e 'MATCH (s:Service)-[]->(t) WITH s, count(t) AS outDegree ORDER BY outDegree DESC LIMIT 3 RETURN s.name, outDegree'
89
+ ```
90
+
91
+ ### Variable-length paths
92
+
93
+ ```bash
94
+ gcyphrq -g graph.json -e 'MATCH (a:Service {name: "API Gateway"})-[r*1..3]->(b) RETURN a, r, b'
95
+ ```
96
+
97
+ ## Exit Codes
98
+
99
+ | Code | Meaning |
100
+ |---|---|
101
+ | `0` | Query executed successfully |
102
+ | `1` | Error (missing arguments, invalid graph, query parse error, etc.) |
103
+
104
+ ## Running without installing
105
+
106
+ You can run the tool directly from source using `tsx`:
107
+
108
+ ```bash
109
+ npx tsx src/index.ts -g examples/social-graph.json -e 'MATCH (u:User) RETURN u'
110
+ ```
111
+
112
+ ## Next Steps
113
+
114
+ - **[Query Guide](query-guide)** — Full Cypher syntax reference and query patterns
115
+ - **[Examples](examples)** — Ready-to-run queries against the bundled graph files