Skip to content

sf-explorer/soql-to-graphql

Repository files navigation

SOQL to GraphQL

npm version CI Test Coverage Security Audit License: MIT Downloads

🚀 Transform your SOQL queries into GraphQL with zero learning curve

logo

Are you a Salesforce developer struggling with GraphQL syntax? Already an SOQL ninja 🥷🏿? This library is your bridge between the familiar SOQL world and the powerful GraphQL ecosystem.

Perfect for:

  • Salesforce developers migrating to GraphQL
  • Teams building modern APIs with Salesforce data
  • Developers who want to leverage GraphQL without learning new syntax
  • Projects requiring type-safe, efficient data queries

📋 Table of Contents

✨ Features

  • 🔄 Seamless Conversion: Convert any SOQL query to GraphQL instantly
  • 🎯 Type Safety: Full TypeScript support with comprehensive type
  • 🧪 Battle Tested: Comprehensive test suite with 104+ test cases
  • 🔧 Developer Friendly: Excellent error messages and debugging support
  • 📚 Well Documented: Extensive documentation and examples
  • Real-time: Supports dynamic queries with variable binding

🎯 Quick Start

📦 Installation

npm

npm install @sf-explorer/soql-to-graphql

yarn

yarn add @sf-explorer/soql-to-graphql

pnpm

pnpm add @sf-explorer/soql-to-graphql

CDN (Browser)

<script src="https://unpkg.com/@sf-explorer/soql-to-graphql@latest/dist/index.js"></script>

Requirements

  • Node.js 18.x or higher
  • TypeScript 5.x (optional, for type definitions)

🚀 Usage

Basic Example

import soql2graphql from '@sf-explorer/soql-to-graphql';

// Simple SOQL query
const soql = 'SELECT Id, Name FROM Account LIMIT 5';
const graphql = soql2graphql(soql);

console.log(graphql);

Output:

query {
  uiapi {
    query {
      Account(first: 5) {
        edges {
          node {
            Id
            Name {
              value
            }
          }
        }
      }
    }
  }
}

Advanced Queries with Relationships

const soql = `
  SELECT Id, Name, Owner.Name, 
         (SELECT Id, Name, Amount FROM Opportunities WHERE StageName = 'Closed Won')
  FROM Account 
  WHERE Industry = 'Technology' 
  ORDER BY Name ASC 
  LIMIT 10
`;

const graphql = soql2graphql(soql);

Output:

query {
  uiapi {
    query {
      Account(
        first: 10
        where: { Industry: { eq: "Technology" } }
        orderBy: { Name: { order: ASC } }
      ) {
        edges {
          node {
            Id
            Name {
              value
            }
            Owner {
              Name {
                value
              }
            }
            Opportunities(where: { StageName: { eq: "Closed Won" } }) {
              edges {
                node {
                  Id
                  Name {
                    value
                  }
                  Amount {
                    value
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Dynamic Queries with Variables

const soql = `
  SELECT Id, Name, Email 
  FROM Contact 
  WHERE AccountId = :accountId 
    AND IsActive = :isActive
  ORDER BY Name ASC
`;

const variables = {
  accountId: 'ID!',
  isActive: 'Boolean',
};

const graphql = soql2graphql(soql, variables);

Output:

query ($accountId: ID!, $isActive: Boolean) {
  uiapi {
    query {
      Contact(
        where: {
          and: [
            { AccountId: { eq: $accountId } }
            { IsActive: { eq: $isActive } }
          ]
        }
        orderBy: { Name: { order: ASC } }
      ) {
        edges {
          node {
            Id
            Name {
              value
            }
            Email {
              value
            }
          }
        }
      }
    }
  }
}

Complex WHERE Conditions

const soql = `
  SELECT Id, Name, Amount, StageName
  FROM Opportunity
  WHERE (Amount > 10000 AND StageName = 'Closed Won')
     OR (Amount > 5000 AND StageName = 'Prospecting')
  ORDER BY Amount DESC
  LIMIT 20
`;

const graphql = soql2graphql(soql);

Output:

query {
  uiapi {
    query {
      Opportunity(
        first: 20
        where: {
          or: [
            {
              and: [
                { Amount: { gt: 10000 } }
                { StageName: { eq: "Closed Won" } }
              ]
            }
            {
              and: [
                { Amount: { gt: 5000 } }
                { StageName: { eq: "Prospecting" } }
              ]
            }
          ]
        }
        orderBy: { Amount: { order: DESC } }
      ) {
        edges {
          node {
            Id
            Name {
              value
            }
            Amount {
              value
            }
            StageName {
              value
            }
          }
        }
      }
    }
  }
}

📚 API Documentation

soql2graphql(soql: string, variables?: VariableDefinitions): string

Converts a SOQL query string to GraphQL format.

Parameters

  • soql (string, required): The SOQL query to convert
  • variables (VariableDefinitions, optional): Variable definitions for bind variables

Returns

  • string: The generated GraphQL query

Example

import soql2graphql, {
  VariableDefinitions,
} from '@sf-explorer/soql-to-graphql';

const soql = 'SELECT Id FROM Account WHERE Name = :name';
const variables: VariableDefinitions = { name: 'String' };
const graphql = soql2graphql(soql, variables);

Type Definitions

interface VariableDefinitions {
  [prop: string]: string;
}

type ComparisonOperator =
  | 'eq'
  | 'ne'
  | 'like'
  | 'in'
  | 'gt'
  | 'gte'
  | 'lt'
  | 'lte';
type LogicalOperator = 'and' | 'or';
type OrderDirection = 'ASC' | 'DESC';

Supported SOQL Features

Feature Status Example
Basic SELECT SELECT Id, Name FROM Account
WHERE clauses WHERE Name = 'Test'
ORDER BY ORDER BY Name ASC
LIMIT LIMIT 10
Relationships SELECT Owner.Name FROM Account
Subqueries SELECT Id, (SELECT Id FROM Opportunities) FROM Account
Variable binding WHERE Name = :name
Logical operators WHERE A = 1 AND B = 2
Comparison operators WHERE Amount > 1000
IN clauses WHERE Id IN ('001', '002')
LIKE patterns WHERE Name LIKE '%Test%'
Functions SELECT COUNT(Id) FROM Account

🔧 Configuration

Environment Variables

# Optional: Set custom GraphQL endpoint
GRAPHQL_ENDPOINT=https://your-instance.salesforce.com/graphql

# Optional: Enable debug mode
DEBUG=soql-to-graphql

Error Handling

try {
  const graphql = soql2graphql(invalidSoql);
} catch (error) {
  console.error('Conversion failed:', error.message);
  // Handle error appropriately
}

🛠️ Troubleshooting

Common Issues

"Invalid SOQL query" Error

// ❌ Incorrect
const soql = 'SELECT Id FROM'; // Missing table name

// ✅ Correct
const soql = 'SELECT Id FROM Account';

Variable Binding Issues

// ❌ Incorrect
const soql = 'SELECT Id FROM Account WHERE Name = :name';
const variables = { name: 'John' }; // Missing type definition

// ✅ Correct
const soql = 'SELECT Id FROM Account WHERE Name = :name';
const variables = { name: 'String' }; // Include type

Complex WHERE Conditions

// ❌ Incorrect - Missing parentheses
const soql = 'SELECT Id FROM Account WHERE A = 1 AND B = 2 OR C = 3';

// ✅ Correct - Proper grouping
const soql = 'SELECT Id FROM Account WHERE (A = 1 AND B = 2) OR C = 3';

Debug Mode

Enable debug mode to see detailed conversion information:

process.env.DEBUG = 'soql-to-graphql';
const graphql = soql2graphql(soql);

Getting Help

  1. Check the Issues for known problems
  2. Create a new issue with:
    • Your SOQL query
    • Expected vs actual output
    • Error messages
    • Environment details

FAQ

Q: Can I use this with any GraphQL client? A: Yes! The output is standard GraphQL that works with any client.

Q: Does this support all SOQL features? A: We support the most common SOQL features. Check the supported features table.

Q: How do I handle custom fields? A: Custom fields work the same as standard fields. Just use the API name: SELECT Custom_Field__c FROM Account.

Q: Can I convert multiple queries at once? A: Currently, you need to convert each query individually, but you can batch the calls for efficiency.

🛠️ Development

Prerequisites

  • Node.js 18.x or higher
  • npm 8.x or higher
  • Git

Quick Setup

# Clone the repository
git clone https://github.com/sf-explorer/soql-to-graphql.git
cd soql-to-graphql

# Install dependencies
npm install

# Run the development server
npm run dev

# Run tests in watch mode
npm run test:watch

Available Scripts

Script Description
npm run build Build the project for production
npm run build:watch Build in watch mode for development
npm run test Run the complete test suite
npm run test:watch Run tests in watch mode
npm run test:ci Run tests for CI environment
npm run lint Run ESLint code quality checks
npm run lint:fix Fix ESLint issues automatically
npm run prettier Format code with Prettier
npm run type-check Run TypeScript type checking
npm run ci Run complete CI pipeline locally

Project Structure

src/
├── types.ts           # TypeScript type definitions
├── constants.ts       # Application constants
├── operators.ts       # SOQL operator conversion logic
├── whereConverter.ts  # WHERE clause conversion
├── fieldConverter.ts  # Field conversion logic
├── queryConverter.ts  # Main query conversion
├── converter.ts       # Main entry point
└── main.ts           # Public API

__test__/
├── unit/              # Unit tests for individual modules
├── integration/       # End-to-end integration tests

└── fixtures/          # Test data and fixtures

Testing Strategy

The project includes comprehensive testing with 96%+ coverage:

  • 🧪 Unit Tests: Individual module testing

  • 🔗 Integration Tests: End-to-end functionality

  • 🛡️ Error Handling: Edge cases and error scenarios

  • 📊 Coverage Reports: Detailed coverage analysis

Code Quality

  • ESLint: Code quality and style enforcement
  • Prettier: Consistent code formatting
  • TypeScript: Type safety and IntelliSense
  • Husky: Git hooks for quality gates
  • Jest: Comprehensive testing framework

Git Hooks

This project uses Git hooks to ensure code quality:

  • Pre-commit: Automatically formats and lints staged files
  • Pre-push: Verifies all files are properly formatted before push

See Git Hooks Documentation for detailed information.

Contributing Guidelines

We welcome contributions! Here's how to get started:

1. Fork and Clone

git clone https://github.com/YOUR_USERNAME/soql-to-graphql.git
cd soql-to-graphql

2. Create a Feature Branch

git checkout -b feature/your-feature-name

3. Make Your Changes

  • Write clean, well-documented code
  • Add tests for new functionality
  • Update documentation as needed
  • Follow the existing code style

4. Test Your Changes

npm run ci  # Run complete CI pipeline

5. Submit a Pull Request

  • Provide a clear description of your changes
  • Reference any related issues
  • Ensure all CI checks pass

CI/CD Pipeline

Our GitHub Actions workflow ensures code quality:

  • 🔄 Continuous Integration: Runs on every push and PR
  • 🔒 Security Audits: Automated vulnerability scanning
  • 📦 Dependency Updates: Weekly automated updates
  • 🚀 Release Automation: Automated versioning and publishing
  • 📊 Coverage Reporting: Code coverage tracking

Release Process

We use automated releases with GitHub Actions:

  1. Trigger Release: Use GitHub Actions workflow or create a git tag
  2. Automated Testing: All tests run automatically
  3. Version Update: Version number incremented automatically
  4. NPM Publishing: Package published to NPM automatically
  5. GitHub Release: Release notes and changelog generated

Quick Release Commands:

# Patch release (bug fixes)
npm run version:patch

# Minor release (new features)
npm run version:minor

# Major release (breaking changes)
npm run version:major

See Release Guide for detailed instructions.

📄 License

This project is licensed under the MIT License - a permissive open-source license that allows you to:

What You Can Do

  • Use commercially - Use in commercial projects and products
  • Modify - Change the code to fit your needs
  • Distribute - Share the code with others
  • Sublicense - Include in your own projects with different licenses
  • Private use - Use in private projects without restrictions

📋 License Requirements

  • Include the license - Keep the MIT license text in your distribution
  • Include copyright - Maintain the copyright notice
  • No warranty - The software is provided "as is" without warranty

🔗 Full License Text

See the complete LICENSE file for the full legal text.

💡 Why MIT?

The MIT License was chosen because it:

  • Maximizes adoption - Easy for businesses to use
  • Minimal restrictions - Simple and permissive
  • Industry standard - Widely recognized and trusted
  • Developer friendly - Clear and easy to understand

🤝 Support

🙏 Credits

This utility would be nothing without these powerful libraries:

⭐ Star History

Star History Chart


Made with ❤️ for the Salesforce community
If this project helps you, please give it a ⭐ on GitHub!