SlideShare a Scribd company logo
1 of 46
Download to read offline
Building custom GraphQL
tooling for your team
Sashko Stubailo
Engineering Manager, Dashboard Discovery
@stubailo, sashko@stripe.com
1. What has made GraphQL impactful in the
Stripe Dashboard
2. Novel tools we've built internally
3. How you can build your own GraphQL tooling
Everything I'm about to present has been a
team effort at Stripe!
It takes a village to create a great
development environment.
Developing in the
Stripe Dashboard
• Lots of product teams
contributing at once
• Needs to work together as a
unified whole
S T R I P E D A S H B O A R D S TA C K
• React
• Flow
• Jest
• Webpack
• Ruby
• GraphQL and Apollo
PA R T 1
What does it take to make
product development
better at scale?
P R O D U C T D E V E L O P M E N T
Frontend
API
Backend
P R O D U C T D E V E L O P M E N T
Components
API
Backend
State
management
Tests
Backend
Component
explorer
Editor
CI
Monitoring
Type
generation
P R O D U C T D E V E L O P M E N T
Components
GraphQL API
Backend
Apollo
State Management
Tests
Backend
Component
explorer
Editor
CI
Monitoring
Type
generation
P R O D U C T D E V E L O P M E N T
Components
GraphQL API
Backend
Apollo
State Management
Tests
Backend
Component
explorer
Editor
CI
Monitoring
Type
generation
GQL
GQL
GQL
GQL
GQL
GQL
GQL
Components
GraphQL API
Backend
Apollo
State Management
Tests
Backend
Component
explorer
Editor
CI
Monitoring
Type
generation
GQL
GQL
GQL
GQL
GQL
GQL
GQL
The most impactful technologies improve
all parts of the product development process.
Main benefit of GraphQL for us:
The wealth of community tools
and content
T O O L S W E U S E M O S T LY O F F T H E S H E L F :
• Apollo Client: Simplifies data fetching and
management in React
• GraphQL Ruby: Makes it easy to build a typed API
• Apollo CLI: Static type generation
• graphql-tools: Easy data mocking
Content and documentation
Less content to maintain, easier to onboard new engineers
Why does GraphQL have such a big impact?
The schema defines capabilities
type Author {
id: Int!
firstName: String
lastName: String
posts: [Post]
}
type Post {
id: Int!
title: String
author: Author
votes: Int
}
type Query {
posts: [Post]
author(id: ID!): Author
}
query PostsForAuthor {
author(id: "1") {
firstName
posts {
title
votes
}
}
}
Query describes requirements
What makes it possible to build great tools?
• Tooling integrates between frontend and backend
• Can rely on schema being present and correct
• Stable spec and ecosystem means you can build tools once and
they work for a long time
The last point is why it actually makes sense to have internal tooling
around GraphQL!
PA R T 2
Tools at Stripe
Tools at Stripe: Mocking
Write unit tests and examples without
having to call a real API
• Faster, more resilient tests
• Possible to develop components
before backend is built
• Easy to generate edge case states
Frontend
Fake API
GraphQL enables automatic mocking
Because GraphQL is strongly typed, libraries like graphql-tools can
generate correctly-shaped mock results automatically for any query.
Any valid
query
Schema + mocks
for each type
Result of the
correct shape
What about edge cases?
A single globally mocked schema is convenient, but isn't well suited
to test specific pathological cases:
• Error states
• Loading states
• Rendering specific values
Per-request
mocking?
Allows you to specify
edge cases, but a lot of
boilerplate for each test.
Example from the Apollo docs →
Best of both worlds: Global mocking with overrides
const mocks = {
Todo: () => ({
text: () => faker.sentence(),
completed: () => faker.boolean(),
}),
User: () => ({
name: () => faker.findName()
})
}
const customResolvers = {
Query: () => ({
todoItems: [
{ completed: true },
{ completed: false },
]
})
};
G L O B A L M O C K S O V E R R I D E S
Now, results are automatically filled in from
global mocks, but we can override specific
values for individual tests.
type Todo {
text: String
completed: Boolean
user: User
}
type User {
name: String
}
type Query {
todoItems: [Todo]
}
S C H E M A
Example: default mocks
In this example, we're just trying to check if the component renders
correctly. The specific data isn't important, so we don't need to
specify anything.
const wrapper = mount(
<ApolloTestProvider>
<ConnectOverviewPage />
</ApolloTestProvider>,
);
expect(wrapper.find('ConnectLandingPage'))
.toHaveLength(1);
Example:
Overriding fields
We want to assert for
specific values in the
rendered component.
We don't want to rely on
values in the global mocks, so
we specify them in the test.
it('renders populated state', async () => {
const customResolvers = {
Merchant: () => ({
balanceSummaries: () => [{
currency: 'usd',
available: 1000,
pending: 2000,
}],
defaultCurrency: () => 'usd',
}),
};
const wrapper = mount(
<ApolloTestProvider
customResolvers={customResolvers}>
<ApolloExample />
</ApolloTestProvider>,
);
await jestHelpers.asyncWait();
const text = wrapper.text();
expect(text).toMatch(/Default currency: usd/);
expect(text).toMatch(/Currency.*Available.*Pending/);
expect(text).toMatch(/$10.*$20/);
});
Mock for loading/error states
We've also added helpers for a very common type of edge case:
Errors and loading state.
it('renders loading state', async () => {
const wrapper = mount(
<LoadingProvider>
<ApolloExample />
</LoadingProvider>,
);
await jestHelpers.asyncWait();
expect(wrapper.text())
.toBe('Loading...');
});
it('renders error state', async () => {
const wrapper = mount(
<ErrorProvider>
<ApolloExample />
</ErrorProvider>,
);
await jestHelpers.asyncWait();
expect(wrapper.text())
.toBe('Error! Oh no!');
});
GraphQL mocks for prototyping
Designers and developers can combine our component system with
fake data with no additional effort.
Mocking overview
✅ Automatic global mocks
✅ Specific overrides to test edge cases
✅ Error states
✅ Loading states
✅ Built in mocks for prototypes
Read the blog post at bit.ly/graphql-mocking
Tools at Stripe:
Schema management
• There's one GraphQL schema for the Dashboard
• Anyone at Stripe should be able to independently make changes
• We want to rely on tooling to prevent breakages
Our schema.graphql file
encodes the current state of
the schema
It's automatically generated
from the API code and
checked in to Git
Detecting breaking
changes in CI
Frontend builds stay in the
wild for a while, so we need to
be carefun about backwards
compatibility.
Custom GraphQL tools
• Stable: Built on a standard spec
• Convenient: Leverage community tools like
GraphQL.js, Apollo Codegen, and Babel
• Tailored: Uniquely designed for our team, codebase,
and development environment
PA R T 3
Building our own
tooling
Let's build a GraphQL field usage finder together
How would we build a tool that searches our codebase for usage of
a specific GraphQL field?
.jsx
.jsx
.jsx
User.name
?
GraphQL
Schema
Let's build a GraphQL field usage finder together
How would we build a tool that searches our codebase for usage of
a specific GraphQL field?
1. Get the GraphQL schema
2. Find queries in our codebase
3. Search those queries for usage of the desired field
Getting our schema
Super easy using graphql-config. With a .graphqlconfig in your repo:
const { getGraphQLProjectConfig } = require("graphql-config");
const schema = getGraphQLProjectConfig().getSchema();
Accessing it is as easy as:
{
"schemaPath": "src/graphql/schema.graphql"
}
Finding GraphQL queries in the codebase
If we're using graphql-tag, we can look for gql template literals:
github.com/apollographql/graphql-tag
const ExampleQuery = gql`
query ExampleQuery {
currentMerchant {
id, defaultCurrency
balanceSummaries {
currency, available, pending
}
}
}
`;
Finding GraphQL queries in the codebase
const fs = require("fs");
const { parse } = require("@babel/parser");
// Read a file
const fileContents = fs.readFileSync(filename, { encoding: "utf-8" });
// Create an AST by parsing the file using Babel
const ast = parse(fileContents);
Using Babel to create an Abstract Syntax Tree (AST):
Finding GraphQL queries in the codebase
const traverse = require("@babel/traverse").default;
const graphqlStrings = [];
traverse(ast, {
TaggedTemplateExpression: function(path) {
if (path.node.tag.name === "gql") {
graphqlStrings.push(path.node.quasi.quasis[0]);
}
}
});
Looking for TaggedTemplateExpressions named "gql":
Useful tool: AST Explorer
Searching for fields in each query
const { parse } = require("graphql");
const ast = parse(jsNode.value.raw);
Parsing the GraphQL query:
Searching for fields in each query
const { visit, visitWithTypeInfo, TypeInfo } = require("graphql");
const typeInfo = new TypeInfo(schema);
visit(ast, visitWithTypeInfo(typeInfo, {
Field(graphqlNode) {
const fieldName = typeInfo.getParentType().name +
"." + graphqlNode.name.value;
// Now, check if it's the field we're looking for
}
}));
Looking through all the fields:
Searching for fields in each query
if (fieldName === fieldWeAreLookingFor) {
const operationName = ast.definitions[0].name.value,
const line = jsNode.loc.start.line;
console.log(`${filename}:${line} ${operationName}`);
}
Compare to the field we're looking for and print results:
Searching for fields in each query
const { parse, visit, visitWithTypeInfo, TypeInfo } = require("graphql");
const ast = parse(jsNode.value.raw);
const typeInfo = new TypeInfo(schema);
visit(ast, visitWithTypeInfo(typeInfo, {
Field(graphqlNode) {
const fieldName = typeInfo.getParentType().name + "." + graphqlNode.name.value;
if (fieldName === fieldWeAreLookingFor) {
const operationName = ast.definitions[0].name.value,
const line = jsNode.loc.start.line;
console.log(`${filename}:${line} ${operationName}`);
}
}
}));
The whole GraphQL part:
Putting it all together
Once we add some plumbing to read in files and accept an
argument, it looks like this:
$ node graphql-field-finder.js Query.user
src/components/customers/CardsSection.js:40 AllCardsQuery
src/graphql/queries/UnauthedClientsQuery.js:13 UnauthedClientsQuery
src/user_settings/TwoFactorAuthenticationSettings.js:46 TwoFactorSettingsQuery
tests/functional/full_flows_test.jsx:401 UnauthedClientsQuery
tests/lib/ApolloTestProvider.test.jsx:13 ApolloTestProviderQuery
tests/lib/ApolloTestProvider.test.jsx:49 ApolloTestProviderUsernameQuery
R E C A P : W H AT W E U S E D
• graphql-config to get the schema
• graphql-tag to identify queries
• Babel to extract queries from code
• GraphQL.js to find fields in queries
See the code at bit.ly/graphql-field-finder
Building custom GraphQL tooling for your team
Sashko Stubailo
@stubailo, sashko@stripe.com
We're hiring at Stripe in Dublin, SF, Singapore,
Seattle, and remote in North America!
Go forth and build your own GraphQL tools to make product
development better at your company!
Get this presentation: bit.ly/custom-graphql-tooling

More Related Content

Recently uploaded

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 

Recently uploaded (20)

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 

Featured

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

Featured (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

Building custom GraphQL tooling for your team

  • 1. Building custom GraphQL tooling for your team Sashko Stubailo Engineering Manager, Dashboard Discovery @stubailo, sashko@stripe.com
  • 2. 1. What has made GraphQL impactful in the Stripe Dashboard 2. Novel tools we've built internally 3. How you can build your own GraphQL tooling
  • 3. Everything I'm about to present has been a team effort at Stripe! It takes a village to create a great development environment.
  • 4. Developing in the Stripe Dashboard • Lots of product teams contributing at once • Needs to work together as a unified whole
  • 5. S T R I P E D A S H B O A R D S TA C K • React • Flow • Jest • Webpack • Ruby • GraphQL and Apollo
  • 6. PA R T 1 What does it take to make product development better at scale?
  • 7. P R O D U C T D E V E L O P M E N T Frontend API Backend
  • 8. P R O D U C T D E V E L O P M E N T Components API Backend State management Tests Backend Component explorer Editor CI Monitoring Type generation
  • 9. P R O D U C T D E V E L O P M E N T Components GraphQL API Backend Apollo State Management Tests Backend Component explorer Editor CI Monitoring Type generation
  • 10. P R O D U C T D E V E L O P M E N T Components GraphQL API Backend Apollo State Management Tests Backend Component explorer Editor CI Monitoring Type generation GQL GQL GQL GQL GQL GQL GQL
  • 12. Main benefit of GraphQL for us: The wealth of community tools and content
  • 13. T O O L S W E U S E M O S T LY O F F T H E S H E L F : • Apollo Client: Simplifies data fetching and management in React • GraphQL Ruby: Makes it easy to build a typed API • Apollo CLI: Static type generation • graphql-tools: Easy data mocking
  • 14. Content and documentation Less content to maintain, easier to onboard new engineers
  • 15. Why does GraphQL have such a big impact? The schema defines capabilities type Author { id: Int! firstName: String lastName: String posts: [Post] } type Post { id: Int! title: String author: Author votes: Int } type Query { posts: [Post] author(id: ID!): Author } query PostsForAuthor { author(id: "1") { firstName posts { title votes } } } Query describes requirements
  • 16. What makes it possible to build great tools? • Tooling integrates between frontend and backend • Can rely on schema being present and correct • Stable spec and ecosystem means you can build tools once and they work for a long time The last point is why it actually makes sense to have internal tooling around GraphQL!
  • 17. PA R T 2 Tools at Stripe
  • 18. Tools at Stripe: Mocking Write unit tests and examples without having to call a real API • Faster, more resilient tests • Possible to develop components before backend is built • Easy to generate edge case states Frontend Fake API
  • 19. GraphQL enables automatic mocking Because GraphQL is strongly typed, libraries like graphql-tools can generate correctly-shaped mock results automatically for any query. Any valid query Schema + mocks for each type Result of the correct shape
  • 20. What about edge cases? A single globally mocked schema is convenient, but isn't well suited to test specific pathological cases: • Error states • Loading states • Rendering specific values
  • 21. Per-request mocking? Allows you to specify edge cases, but a lot of boilerplate for each test. Example from the Apollo docs →
  • 22. Best of both worlds: Global mocking with overrides const mocks = { Todo: () => ({ text: () => faker.sentence(), completed: () => faker.boolean(), }), User: () => ({ name: () => faker.findName() }) } const customResolvers = { Query: () => ({ todoItems: [ { completed: true }, { completed: false }, ] }) }; G L O B A L M O C K S O V E R R I D E S Now, results are automatically filled in from global mocks, but we can override specific values for individual tests. type Todo { text: String completed: Boolean user: User } type User { name: String } type Query { todoItems: [Todo] } S C H E M A
  • 23. Example: default mocks In this example, we're just trying to check if the component renders correctly. The specific data isn't important, so we don't need to specify anything. const wrapper = mount( <ApolloTestProvider> <ConnectOverviewPage /> </ApolloTestProvider>, ); expect(wrapper.find('ConnectLandingPage')) .toHaveLength(1);
  • 24. Example: Overriding fields We want to assert for specific values in the rendered component. We don't want to rely on values in the global mocks, so we specify them in the test. it('renders populated state', async () => { const customResolvers = { Merchant: () => ({ balanceSummaries: () => [{ currency: 'usd', available: 1000, pending: 2000, }], defaultCurrency: () => 'usd', }), }; const wrapper = mount( <ApolloTestProvider customResolvers={customResolvers}> <ApolloExample /> </ApolloTestProvider>, ); await jestHelpers.asyncWait(); const text = wrapper.text(); expect(text).toMatch(/Default currency: usd/); expect(text).toMatch(/Currency.*Available.*Pending/); expect(text).toMatch(/$10.*$20/); });
  • 25. Mock for loading/error states We've also added helpers for a very common type of edge case: Errors and loading state. it('renders loading state', async () => { const wrapper = mount( <LoadingProvider> <ApolloExample /> </LoadingProvider>, ); await jestHelpers.asyncWait(); expect(wrapper.text()) .toBe('Loading...'); }); it('renders error state', async () => { const wrapper = mount( <ErrorProvider> <ApolloExample /> </ErrorProvider>, ); await jestHelpers.asyncWait(); expect(wrapper.text()) .toBe('Error! Oh no!'); });
  • 26. GraphQL mocks for prototyping Designers and developers can combine our component system with fake data with no additional effort.
  • 27. Mocking overview ✅ Automatic global mocks ✅ Specific overrides to test edge cases ✅ Error states ✅ Loading states ✅ Built in mocks for prototypes Read the blog post at bit.ly/graphql-mocking
  • 28. Tools at Stripe: Schema management • There's one GraphQL schema for the Dashboard • Anyone at Stripe should be able to independently make changes • We want to rely on tooling to prevent breakages
  • 29. Our schema.graphql file encodes the current state of the schema It's automatically generated from the API code and checked in to Git
  • 30. Detecting breaking changes in CI Frontend builds stay in the wild for a while, so we need to be carefun about backwards compatibility.
  • 31. Custom GraphQL tools • Stable: Built on a standard spec • Convenient: Leverage community tools like GraphQL.js, Apollo Codegen, and Babel • Tailored: Uniquely designed for our team, codebase, and development environment
  • 32. PA R T 3 Building our own tooling
  • 33. Let's build a GraphQL field usage finder together How would we build a tool that searches our codebase for usage of a specific GraphQL field? .jsx .jsx .jsx User.name ? GraphQL Schema
  • 34. Let's build a GraphQL field usage finder together How would we build a tool that searches our codebase for usage of a specific GraphQL field? 1. Get the GraphQL schema 2. Find queries in our codebase 3. Search those queries for usage of the desired field
  • 35. Getting our schema Super easy using graphql-config. With a .graphqlconfig in your repo: const { getGraphQLProjectConfig } = require("graphql-config"); const schema = getGraphQLProjectConfig().getSchema(); Accessing it is as easy as: { "schemaPath": "src/graphql/schema.graphql" }
  • 36. Finding GraphQL queries in the codebase If we're using graphql-tag, we can look for gql template literals: github.com/apollographql/graphql-tag const ExampleQuery = gql` query ExampleQuery { currentMerchant { id, defaultCurrency balanceSummaries { currency, available, pending } } } `;
  • 37. Finding GraphQL queries in the codebase const fs = require("fs"); const { parse } = require("@babel/parser"); // Read a file const fileContents = fs.readFileSync(filename, { encoding: "utf-8" }); // Create an AST by parsing the file using Babel const ast = parse(fileContents); Using Babel to create an Abstract Syntax Tree (AST):
  • 38. Finding GraphQL queries in the codebase const traverse = require("@babel/traverse").default; const graphqlStrings = []; traverse(ast, { TaggedTemplateExpression: function(path) { if (path.node.tag.name === "gql") { graphqlStrings.push(path.node.quasi.quasis[0]); } } }); Looking for TaggedTemplateExpressions named "gql":
  • 39. Useful tool: AST Explorer
  • 40. Searching for fields in each query const { parse } = require("graphql"); const ast = parse(jsNode.value.raw); Parsing the GraphQL query:
  • 41. Searching for fields in each query const { visit, visitWithTypeInfo, TypeInfo } = require("graphql"); const typeInfo = new TypeInfo(schema); visit(ast, visitWithTypeInfo(typeInfo, { Field(graphqlNode) { const fieldName = typeInfo.getParentType().name + "." + graphqlNode.name.value; // Now, check if it's the field we're looking for } })); Looking through all the fields:
  • 42. Searching for fields in each query if (fieldName === fieldWeAreLookingFor) { const operationName = ast.definitions[0].name.value, const line = jsNode.loc.start.line; console.log(`${filename}:${line} ${operationName}`); } Compare to the field we're looking for and print results:
  • 43. Searching for fields in each query const { parse, visit, visitWithTypeInfo, TypeInfo } = require("graphql"); const ast = parse(jsNode.value.raw); const typeInfo = new TypeInfo(schema); visit(ast, visitWithTypeInfo(typeInfo, { Field(graphqlNode) { const fieldName = typeInfo.getParentType().name + "." + graphqlNode.name.value; if (fieldName === fieldWeAreLookingFor) { const operationName = ast.definitions[0].name.value, const line = jsNode.loc.start.line; console.log(`${filename}:${line} ${operationName}`); } } })); The whole GraphQL part:
  • 44. Putting it all together Once we add some plumbing to read in files and accept an argument, it looks like this: $ node graphql-field-finder.js Query.user src/components/customers/CardsSection.js:40 AllCardsQuery src/graphql/queries/UnauthedClientsQuery.js:13 UnauthedClientsQuery src/user_settings/TwoFactorAuthenticationSettings.js:46 TwoFactorSettingsQuery tests/functional/full_flows_test.jsx:401 UnauthedClientsQuery tests/lib/ApolloTestProvider.test.jsx:13 ApolloTestProviderQuery tests/lib/ApolloTestProvider.test.jsx:49 ApolloTestProviderUsernameQuery
  • 45. R E C A P : W H AT W E U S E D • graphql-config to get the schema • graphql-tag to identify queries • Babel to extract queries from code • GraphQL.js to find fields in queries See the code at bit.ly/graphql-field-finder
  • 46. Building custom GraphQL tooling for your team Sashko Stubailo @stubailo, sashko@stripe.com We're hiring at Stripe in Dublin, SF, Singapore, Seattle, and remote in North America! Go forth and build your own GraphQL tools to make product development better at your company! Get this presentation: bit.ly/custom-graphql-tooling