@graphox/cli 0.1.13

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 ADDED
@@ -0,0 +1,133 @@
1
+ # @graphox/cli
2
+
3
+ NPM package for installing the `Graphox` CLI - a high-performance GraphQL toolset for TypeScript monorepos.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @graphox/cli
9
+ # or
10
+ npm install @graphox/cli
11
+ # or
12
+ yarn add @graphox/cli
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Once installed, you can use the `Graphox` command:
18
+
19
+ ```bash
20
+ # Start the Language Server
21
+ pnpm graphox lsp
22
+
23
+ # Validate GraphQL files
24
+ pnpm graphox check
25
+
26
+ # Generate TypeScript types
27
+ pnpm graphox codegen
28
+ pnpm graphox codegen --clean
29
+ pnpm graphox codegen --watch
30
+
31
+ # Run performance benchmarks
32
+ pnpm graphox benchmark
33
+ ```
34
+
35
+ ### Global Installation
36
+
37
+ ```bash
38
+ pnpm add -g @graphox/cli
39
+
40
+ # Now you can use it directly
41
+ graphox lsp
42
+ graphox check
43
+ graphox codegen
44
+ ```
45
+
46
+ ## Supported Platforms
47
+
48
+ This package automatically downloads the correct binary for your platform:
49
+
50
+ - **macOS**: x86_64 (Intel) and ARM64 (Apple Silicon)
51
+ - **Linux**: x86_64 and ARM64
52
+ - **Windows**: x86_64 and ARM64
53
+
54
+ ## Features
55
+
56
+ - **Language Server (LSP)**: Real-time GraphQL validation, autocomplete, go-to-definition, hover docs, and more
57
+ - **Type Generation**: TypeScript type generation from GraphQL operations
58
+ - **Validation**: Granular diagnostics for GraphQL schemas and operations
59
+ - **Fragment Tracking**: Automatic fragment dependency resolution across packages
60
+
61
+ ## Configuration
62
+
63
+ Create a `graphox.yaml` file in your project root. See the [main documentation](https://github.com/soundtrackyourbrand/graphox#configuration) for details.
64
+
65
+ ### Editor Support
66
+
67
+ To get validation and autocomplete in your editor, add the following line at the top of your `graphox.yaml` file:
68
+
69
+ ```yaml
70
+ # yaml-language-server: $schema=node_modules/@graphox/cli/graphox.schema.json
71
+ ```
72
+
73
+ Or, if you use VS Code with the [YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml), you can add the following to your workspace settings:
74
+
75
+ ```json
76
+ {
77
+ "yaml.schemas": {
78
+ "node_modules/@graphox/cli/graphox.schema.json": "graphox.yaml"
79
+ }
80
+ }
81
+ ```
82
+
83
+ ## Local Development
84
+
85
+ If you're developing the CLI itself, you can use a local build instead of downloading from releases:
86
+
87
+ ### Option 1: Using Environment Variable (Recommended)
88
+
89
+ ```bash
90
+ # Build the CLI locally
91
+ cd /path/to/graphox
92
+ cargo build --release
93
+
94
+ # Set environment variable to point to your local build
95
+ export GRAPHOX_LOCAL_BUILD=/path/to/graphox/target/release/graphox
96
+
97
+ # Now install the npm package - it will use your local build
98
+ cd /path/to/your/project
99
+ pnpm add /path/to/graphox/npm/graphox-cli
100
+ ```
101
+
102
+ The install script will copy your local binary instead of downloading from GitHub releases.
103
+
104
+ ### Option 2: Using pnpm link
105
+
106
+ ```bash
107
+ # In the graphox repository, build the binary
108
+ cargo build --release
109
+
110
+ # Set up the local binary
111
+ ./scripts/setup-npm-dev.sh
112
+
113
+ # Link globally
114
+ cd npm/graphox-cli
115
+ pnpm link --global
116
+ ```
117
+
118
+ ## Manual Binary Download
119
+
120
+ If automatic installation fails, you can manually download binaries from the [releases page](https://github.com/soundtrackyourbrand/graphox/releases).
121
+
122
+ ## Environment Variables
123
+
124
+ - `GRAPHOX_LOCAL_BUILD`: Path to a local binary to use instead of downloading (useful for development)
125
+ - `GRAPHOX_DOWNLOAD_URL`: Override the download URL for the binary (useful for mirrors or custom builds)
126
+
127
+ ## License
128
+
129
+ MIT
130
+
131
+ ## Repository
132
+
133
+ https://github.com/soundtrackyourbrand/graphox
package/bin/graphox ADDED
@@ -0,0 +1,20 @@
1
+ #!/bin/sh
2
+
3
+ # This script is the entry point for the Graphox CLI
4
+ # It locates the actual binary and executes it with all arguments
5
+
6
+ set -e
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
9
+ BINARY="$SCRIPT_DIR/graphox-bin"
10
+
11
+ # Check if binary exists and is executable
12
+ if [ ! -x "$BINARY" ]; then
13
+ echo "Error: Graphox native binary not found at $BINARY"
14
+ echo "This usually means the postinstall script was skipped (for pnpm, check ignored builds)."
15
+ echo "Try: pnpm approve-builds @graphox/cli && pnpm rebuild @graphox/cli"
16
+ exit 1
17
+ fi
18
+
19
+ # Execute the binary with all arguments
20
+ exec "$BINARY" "$@"
@@ -0,0 +1,306 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Graphox Configuration",
4
+ "description": "Configuration for Graphox, a high-performance GraphQL toolset.",
5
+ "type": "object",
6
+ "properties": {
7
+ "projects": {
8
+ "type": "array",
9
+ "description": "Project configurations. Projects are matched in order; the first matching project is used for each file.",
10
+ "items": { "$ref": "#/definitions/ProjectConfig" }
11
+ },
12
+ "schema_types": {
13
+ "type": "array",
14
+ "description": "Generate standalone TypeScript types from the schema without operations.",
15
+ "items": { "$ref": "#/definitions/SchemaTypeConfig" }
16
+ },
17
+ "scalars": {
18
+ "type": "object",
19
+ "description": "Map GraphQL scalar types to TypeScript types.",
20
+ "additionalProperties": { "type": "string" }
21
+ },
22
+ "ignore_deprecations": {
23
+ "type": "array",
24
+ "description": "Suppress warnings for deprecated fields or types globally.",
25
+ "items": { "type": "string" }
26
+ },
27
+ "tracing": { "$ref": "#/definitions/TracingConfig" },
28
+ "timeouts": { "$ref": "#/definitions/TimeoutConfig" },
29
+ "watch_all_files": {
30
+ "type": "boolean",
31
+ "description": "Whether to watch all workspace files for changes. If false, only GraphQL files are watched.",
32
+ "default": true
33
+ },
34
+ "lsp_automatic_codegen": {
35
+ "type": "boolean",
36
+ "description": "Whether to automatically run codegen on file changes in the LSP.",
37
+ "default": true
38
+ },
39
+ "lsp_codegen_throttle_ms": {
40
+ "type": "integer",
41
+ "description": "Throttle automatic codegen in the LSP (ms).",
42
+ "default": 300
43
+ },
44
+ "codegen_watch_debounce_ms": {
45
+ "type": "integer",
46
+ "description": "Debounce file changes in watch mode (ms).",
47
+ "default": 200
48
+ },
49
+ "enable_schema_cache": {
50
+ "type": "boolean",
51
+ "description": "Enable two-tier schema cache for better performance.",
52
+ "default": true
53
+ },
54
+ "rules": { "$ref": "#/definitions/RulesConfig" },
55
+ "codegen": { "$ref": "#/definitions/CodegenConfig" }
56
+ },
57
+ "definitions": {
58
+ "ProjectConfig": {
59
+ "type": "object",
60
+ "required": ["schema", "include"],
61
+ "properties": {
62
+ "schema": {
63
+ "description": "Single schema file path or an array of paths for multi-file schemas.",
64
+ "$ref": "#/definitions/SchemaSource"
65
+ },
66
+ "include": {
67
+ "description": "Glob pattern(s) for GraphQL operations to include in this project.",
68
+ "$ref": "#/definitions/GlobPattern"
69
+ },
70
+ "documents": {
71
+ "description": "Legacy alias for include.",
72
+ "$ref": "#/definitions/GlobPattern"
73
+ },
74
+ "exclude": {
75
+ "description": "Glob pattern(s) for files to exclude from this project.",
76
+ "$ref": "#/definitions/GlobPattern"
77
+ },
78
+ "output_dir": {
79
+ "type": "string",
80
+ "description": "Directory where generated files will be placed."
81
+ },
82
+ "import": {
83
+ "type": "string",
84
+ "description": "The import path used by other projects to reference fragments from this project."
85
+ },
86
+ "codegen": {
87
+ "description": "Codegen configuration for this project. Set to false to disable codegen.",
88
+ "oneOf": [
89
+ { "type": "boolean" },
90
+ { "$ref": "#/definitions/CodegenConfig" }
91
+ ]
92
+ },
93
+ "possible_types": {
94
+ "type": "string",
95
+ "description": "Path to generate possibleTypes introspection data for Apollo Client's InMemoryCache."
96
+ },
97
+ "type_policies": {
98
+ "type": "string",
99
+ "description": "Path to generate strict TypeScript types for Apollo Client TypePolicies."
100
+ },
101
+ "rules": { "$ref": "#/definitions/RulesConfig" }
102
+ }
103
+ },
104
+ "SchemaSource": {
105
+ "oneOf": [
106
+ { "type": "string" },
107
+ { "type": "array", "items": { "type": "string" } }
108
+ ]
109
+ },
110
+ "GlobPattern": {
111
+ "oneOf": [
112
+ { "type": "string" },
113
+ { "type": "array", "items": { "type": "string" } }
114
+ ]
115
+ },
116
+ "SchemaTypeConfig": {
117
+ "type": "object",
118
+ "required": ["schema", "output"],
119
+ "properties": {
120
+ "schema": { "$ref": "#/definitions/SchemaSource" },
121
+ "output": {
122
+ "type": "string",
123
+ "description": "File path where schema types will be generated."
124
+ },
125
+ "import": {
126
+ "type": "string",
127
+ "description": "How generated files import these types."
128
+ },
129
+ "possible_types": {
130
+ "type": "string",
131
+ "description": "Path to generate possibleTypes introspection data for Apollo Client."
132
+ },
133
+ "type_policies": {
134
+ "type": "string",
135
+ "description": "Path to generate Apollo Client TypePolicies."
136
+ }
137
+ }
138
+ },
139
+ "RulesConfig": {
140
+ "type": "object",
141
+ "properties": {
142
+ "required_fields": {
143
+ "description": "Enforce required fields in selections. Can be a boolean shorthand or a map of field names to rules.",
144
+ "oneOf": [
145
+ { "type": "boolean", "const": false, "description": "Disable all required field rules." },
146
+ {
147
+ "type": "object",
148
+ "additionalProperties": { "$ref": "#/definitions/RequiredFieldRule" }
149
+ }
150
+ ]
151
+ },
152
+ "unique_operation_name": {
153
+ "type": "boolean",
154
+ "description": "Enforce unique names for all operations across the project.",
155
+ "default": false
156
+ },
157
+ "no_duplicate_fields": {
158
+ "type": "boolean",
159
+ "description": "Prevent selecting the same field multiple times in a single selection set.",
160
+ "default": false
161
+ },
162
+ "no_unused_fragments": {
163
+ "type": "boolean",
164
+ "description": "Identify and error on fragments that are defined but not used.",
165
+ "default": false
166
+ }
167
+ }
168
+ },
169
+ "RequiredFieldRule": {
170
+ "oneOf": [
171
+ { "type": "boolean", "description": "Whether this field is always required." },
172
+ {
173
+ "type": "array",
174
+ "items": { "type": "string" },
175
+ "description": "List of operation types (query, mutation, subscription) where this field is required."
176
+ }
177
+ ]
178
+ },
179
+ "CodegenConfig": {
180
+ "type": "object",
181
+ "properties": {
182
+ "enabled": { "type": "boolean", "default": true },
183
+ "document_suffix": {
184
+ "type": "string",
185
+ "description": "Suffix for the generated document constant.",
186
+ "default": "Document"
187
+ },
188
+ "variables_suffix": {
189
+ "type": "string",
190
+ "description": "Suffix for the generated variables type.",
191
+ "default": "Variables"
192
+ },
193
+ "fragment_suffix": {
194
+ "type": "string",
195
+ "description": "Suffix for the generated fragment type.",
196
+ "default": ""
197
+ },
198
+ "fragment_document_suffix": {
199
+ "type": "string",
200
+ "description": "Suffix for the generated fragment document constant.",
201
+ "default": ""
202
+ },
203
+ "query_suffix": {
204
+ "type": "string",
205
+ "description": "Suffix for the generated query type.",
206
+ "default": "Query"
207
+ },
208
+ "mutation_suffix": {
209
+ "type": "string",
210
+ "description": "Suffix for the generated mutation type.",
211
+ "default": "Mutation"
212
+ },
213
+ "subscription_suffix": {
214
+ "type": "string",
215
+ "description": "Suffix for the generated subscription type.",
216
+ "default": "Subscription"
217
+ },
218
+ "naming_convention": {
219
+ "type": "string",
220
+ "enum": ["pascal_case", "pascalcase", "pascal", "preserve"],
221
+ "default": "pascal_case",
222
+ "description": "Naming convention for generated types."
223
+ },
224
+ "fragment_masking": {
225
+ "description": "Enable fragment masking to prevent fragment fields from 'leaking' into parent operation types.",
226
+ "oneOf": [
227
+ { "type": "boolean" },
228
+ { "type": "string", "enum": ["enabled", "true", "disabled", "false"] },
229
+ {
230
+ "type": "object",
231
+ "properties": {
232
+ "unmask_function_name": {
233
+ "type": "string",
234
+ "description": "Custom function name for unmasking fragment data.",
235
+ "default": "getFragmentData"
236
+ }
237
+ }
238
+ }
239
+ ]
240
+ },
241
+ "emit_extensions": {
242
+ "type": "string",
243
+ "enum": ["ts", "dts", "d.ts", "js", "javascript"],
244
+ "description": "File extension for generated files."
245
+ },
246
+ "generate_ast_for_fragments": {
247
+ "type": "boolean",
248
+ "description": "Generate and reuse AST nodes for fragments to reduce bundle sizes.",
249
+ "default": false
250
+ },
251
+ "re_exports": {
252
+ "type": "boolean",
253
+ "description": "Re-export all operation and fragment types/documents from the root graphql.ts file.",
254
+ "default": false
255
+ },
256
+ "emit_permission_data": {
257
+ "type": "boolean",
258
+ "description": "Generate permission metadata for operations.",
259
+ "default": false
260
+ },
261
+ "emit_ast_directives": { "type": "boolean", "default": false },
262
+ "emit_ast_aliases": { "type": "boolean", "default": true },
263
+ "emit_ast_arguments": { "type": "boolean", "default": true },
264
+ "emit_ast_variable_defaults": { "type": "boolean", "default": true },
265
+ "inline_fragments": { "type": "boolean", "default": false },
266
+ "default_scalar_type": {
267
+ "type": "string",
268
+ "description": "Default type for scalars not defined in 'scalars' mapping.",
269
+ "default": "any"
270
+ },
271
+ "schema_import": {
272
+ "type": "string",
273
+ "description": "The import path used in generated operation files to reference schema types."
274
+ }
275
+ }
276
+ },
277
+ "TracingConfig": {
278
+ "type": "object",
279
+ "description": "LSP request tracing configuration.",
280
+ "properties": {
281
+ "enabled": { "type": "boolean", "default": false },
282
+ "threshold_ms": {
283
+ "type": "integer",
284
+ "description": "Only trace requests exceeding this threshold in milliseconds.",
285
+ "default": 20
286
+ }
287
+ }
288
+ },
289
+ "TimeoutConfig": {
290
+ "type": "object",
291
+ "description": "Configuration for various operation timeouts.",
292
+ "properties": {
293
+ "workspace_scan_ms": {
294
+ "type": "integer",
295
+ "description": "Timeout for initial workspace scan (ms).",
296
+ "default": 60000
297
+ },
298
+ "lsp_request_ms": {
299
+ "type": "integer",
300
+ "description": "Timeout for individual LSP requests (ms).",
301
+ "default": 1000
302
+ }
303
+ }
304
+ }
305
+ }
306
+ }
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@graphox/cli",
3
+ "version": "0.1.13",
4
+ "description": "Graphox CLI - High-performance GraphQL toolset",
5
+ "bin": {
6
+ "graphox": "./bin/graphox"
7
+ },
8
+ "optionalDependencies": {
9
+ "@graphox/darwin-arm64": "0.1.13",
10
+ "@graphox/darwin-x64": "0.1.13",
11
+ "@graphox/linux-arm64": "0.1.13",
12
+ "@graphox/linux-x64": "0.1.13",
13
+ "@graphox/win32-arm64": "0.1.13",
14
+ "@graphox/win32-x64": "0.1.13"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/soundtrackyourbrand/graphox"
22
+ },
23
+ "keywords": [
24
+ "graphql",
25
+ "lsp",
26
+ "language-server",
27
+ "codegen",
28
+ "typescript",
29
+ "rust"
30
+ ],
31
+ "author": "soundtrackyourbrand",
32
+ "license": "UNLICENSED",
33
+ "files": [
34
+ "postinstall.js",
35
+ "README.md",
36
+ "graphox.schema.json"
37
+ ],
38
+ "engines": {
39
+ "node": ">=14"
40
+ },
41
+ "os": [
42
+ "darwin",
43
+ "linux",
44
+ "win32"
45
+ ],
46
+ "cpu": [
47
+ "x64",
48
+ "arm64"
49
+ ],
50
+ "scripts": {
51
+ "postinstall": "node postinstall.js"
52
+ }
53
+ }
package/postinstall.js ADDED
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const PLATFORMS = [
7
+ 'darwin-arm64',
8
+ 'darwin-x64',
9
+ 'linux-arm64',
10
+ 'linux-x64',
11
+ 'win32-arm64',
12
+ 'win32-x64'
13
+ ];
14
+
15
+ function getPlatform() {
16
+ const platform = process.platform;
17
+ const arch = process.arch;
18
+ return `${platform}-${arch}`;
19
+ }
20
+
21
+ function install() {
22
+ const currentPlatform = getPlatform();
23
+ const binDir = path.join(__dirname, 'bin');
24
+ const binaryName = process.platform === 'win32' ? 'graphox-bin.exe' : 'graphox-bin';
25
+ const binaryPath = path.join(binDir, binaryName);
26
+
27
+ if (!fs.existsSync(binDir)) {
28
+ fs.mkdirSync(binDir, { recursive: true });
29
+ }
30
+
31
+ // 1. Check for local build first (for development)
32
+ if (process.env.GRAPHOX_LOCAL_BUILD) {
33
+ try {
34
+ if (fs.existsSync(binaryPath)) {
35
+ fs.unlinkSync(binaryPath);
36
+ }
37
+
38
+ const absoluteLocalBuild = path.resolve(process.env.GRAPHOX_LOCAL_BUILD);
39
+
40
+ // Use symlink for local development so rebuilding Rust updates the CLI immediately
41
+ fs.symlinkSync(absoluteLocalBuild, binaryPath);
42
+ console.log(`Using local build via symlink: ${absoluteLocalBuild}`);
43
+ return;
44
+ } catch (e) {
45
+ console.warn('Failed to create symlink for local build:', e.message);
46
+ // Fallback to copy if symlink fails
47
+ try {
48
+ fs.copyFileSync(process.env.GRAPHOX_LOCAL_BUILD, binaryPath);
49
+ fs.chmodSync(binaryPath, 0o755);
50
+ console.log('Using local build (copy fallback).');
51
+ return;
52
+ } catch (copyErr) {
53
+ console.error('Failed to copy local build:', copyErr.message);
54
+ }
55
+ }
56
+ }
57
+
58
+ // 2. Try to find the binary from optionalDependencies
59
+ const pkgName = `@graphox/${currentPlatform}`;
60
+ try {
61
+ const pkgPath = require.resolve(`${pkgName}/bin/graphox${process.platform === 'win32' ? '.exe' : ''}`);
62
+
63
+ // Copy or link the binary
64
+ fs.copyFileSync(pkgPath, binaryPath);
65
+ fs.chmodSync(binaryPath, 0o755);
66
+ console.log(`Successfully installed binary from ${pkgName}`);
67
+ } catch (e) {
68
+ console.error(`Error: Could not find platform-specific package ${pkgName}.`);
69
+ console.error('This typically means the package was not installed as an optional dependency.');
70
+ console.error('Please ensure you have access to @graphox scope on the NPM registry.');
71
+ process.exit(1);
72
+ }
73
+ }
74
+
75
+ install();