How to use ast-grep with GraphQL
ast-grep is a code search + replace tool that uses the abstract syntax tree (AST). It has language support for TypeScript, Python, and others, but it doesn't support GraphQL out of the box. However, there is documentation for supporting other languages: Custom Language Support.
These are my notes using that Custom Language Support documentation along with the Multi-Language Documents documentation to set up GraphQL support for ast-grep on macOS.
Prepare Tree-sitter Tool and Parser
- Install tree-sitter CLI - brew install tree-sitter- (Alternatively, - npm install -g tree-sitter-cli)
- Test tree-sitter is installed - tree-sitter --version- tree-sitter 0.23.0
- Use a working directory - I'll use - /tmpas my working directory, but a different directory can be used- cd /tmp
- Get the tree-sitter GraphQL grammar - git clone https://github.com/bkegley/tree-sitter-graphql.git- (This is the repo used by the neovim tree-sitter library.) 
Compile the Parser as a Dynamic Library
- Compile the GraphQL parser as a dynamic library - cd tree-sitter-graphql export TREE_SITTER_LIBDIR=/tmp tree-sitter test- Note: I got the following error when I ran this. If anyone knows what is going on, please let me know. - Error in query file "formatter.scm" Caused by: Query error at 5:31. Impossible pattern: (input_object_type_definition (input_value_definition) @field_definition)- However, it still generated the - graphql.dylibfile in- /tmp. Note: according to ChatGPT,- .dylibis used on Mac,- .sois used on Linux, and- .dllis used on Windows.
Register Language in sgconfig.yml
- Create a new ast-grep project - cd /tmp sg new- No sgconfig.yml found. Creating a new ast-grep project... > Where do you want to have your rules? rules > Do you want to create rule tests? No > Do you want to create folder for utility rules? No Your new ast-grep project has been created!
- Edit - sgconfig.ymlto add GraphQL as a custom language- /tmp/sgconfig.yml:- ruleDirs: - ./rules customLanguages: graphql: libraryPath: graphql.dylib extensions: [graphql] expandoChar: $
Use It!
- Search for all - inputtypes in- /path/to/my/schema.graphql- sg -p "input" -l graphql /path/to/my/schema.graphql- /path/to/my/schema.graphql 6│input AddOrUpdateResidualWorksheetInputType { 120│input AutoAssignStyleCodeInputType { 478│input BulkCreateVehicleReleaseInputType { 483│input BulkDeleteVehicleReleaseInputType { 487│input BulkEditVehicleReleaseInputType { 492│input BulkImportStyleFromCppInputType { 949│input CloneModelInputType { 958│input CloneModelStyleInputType { 973│input CloneStyleInputType { 1749│input CppConfigurationInputType {
- Search for all - DateTimeinput fields (but not output fields) in- /path/to/my/schema.graphql. Note: the- tree-sitter-graphqlgrammer.js file contains different- kinds that can be used for filtering.- sg scan --inline-rules ' id: datetimeinputs language: graphql rule: regex: "DateTime" kind: input_value_definition ' /path/to/my/schema.graphql- help[datetimeinputs]: ┌─ /path/to/my/schema.graphql:2356:3 │ 2356 │ configurationLastUpdatedAt: DateTime │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help[datetimeinputs]: ┌─ /path/to/my/schema.graphql:8331:69 │ 8331 │ previousStyleSnapshot(styleSnapshotRowId: Guid, styleRowId: Long, versionDate: DateTime): StyleSnapshotTypeOrOperationErrorType │ ^^^^^^^^^^^^^^^^^^^^^ help[datetimeinputs]: ┌─ /path/to/my/schema.graphql:8794:16 │ 8794 │ whatsChanged(date: DateTime!, flags: [WhatsChangedFilterFlagsEnumType], includeCppOrEmbargoedData: CppEmbargoedDataFilterEnumType): WhatsChangedType │ ^^^^^^^^^^^^^^^ help[datetimeinputs]: ┌─ /path/to/my/schema.graphql:11536:3 │ 11536 │ configurationLastUpdatedAt: DateTime │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Related posts
- Next.js App Router (RSC) projects w/ open source code — posted 2024-07-30
- Next.js Relay GraphQL Pokemon example — posted 2024-05-22
- Example Node.js Passport.js SAML app using OneLogin — posted 2024-05-10
- Aphrodite to CSS Modules codemod — posted 2022-12-09
- Simple codemod example with jscodeshift — posted 2021-05-03

 
  
  
 