Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Provides an executor for the graphql
gem which allows queries to be batched.
Add this line to your application's Gemfile:
gem 'graphql-batch'
And then execute:
$ bundle
Or install it yourself as:
$ gem install graphql-batch
Require the library
require 'graphql/batch'
Define a custom loader, which is initialized with arguments that are used for grouping and a perform method for performing the batch load.
class RecordLoader < GraphQL::Batch::Loader
def initialize(model)
@model = model
end
def perform(ids)
@model.where(id: ids).each { |record| fulfill(record.id, record) }
ids.each { |id| fulfill(id, nil) unless fulfilled?(id) }
end
end
Use GraphQL::Batch
as a plugin in your schema after specifying the mutation
so that GraphQL::Batch
can extend the mutation fields to clear the cache after
they are resolved.
class MySchema < GraphQL::Schema
query MyQueryType
mutation MyMutationType
use GraphQL::Batch
end
The loader class can be used from the resolver for a graphql field by calling .for
with the grouping arguments to get a loader instance, then call .load
on that instance with the key to load.
field :product, Types::Product, null: true do
argument :id, ID, required: true
end
def product(id:)
RecordLoader.for(Product).load(id)
end
The loader also supports batch loading an array of records instead of just a single record, via load_many
. For example:
field :products, [Types::Product, null: true], null: false do
argument :ids, [ID], required: true
end
def products(ids:)
RecordLoader.for(Product).load_many(ids)
end
Although this library doesn't have a dependency on active record, the examples directory has record and association loaders for active record which handles edge cases like type casting ids and overriding GraphQL::Batch::Loader#cache_key to load associations on records with the same id.
GraphQL::Batch::Loader#load returns a Promise using the promise.rb gem to provide a promise based API, so you can transform the query results using .then
def product_title(id:)
RecordLoader.for(Product).load(id).then do |product|
product.title
end
end
You may also need to do another query that depends on the first one to get the result, in which case the query block can return another query.
def product_image(id:)
RecordLoader.for(Product).load(id).then do |product|
RecordLoader.for(Image).load(product.image_id)
end
end
If the second query doesn't depend on the first one, then you can use Promise.all, which allows each query in the group to be batched with other queries.
def all_collections
Promise.all([
CountLoader.for(Shop, :smart_collections).load(context.shop_id),
CountLoader.for(Shop, :custom_collections).load(context.shop_id),
]).then(&:sum)
end
.then
can optionally take two lambda arguments, the first of which is equivalent to passing a block to .then
, and the second one handles exceptions. This can be used to provide a fallback
def product(id:)
# Try the cache first ...
CacheLoader.for(Product).load(id).then(nil, lambda do |exc|
# But if there's a connection error, go to the underlying database
raise exc unless exc.is_a?(Redis::BaseConnectionError)
logger.warn err.message
RecordLoader.for(Product).load(id)
end)
end
You can prime the loader cache with a specific value, which can be useful in certain situations.
def liked_products
liked_products = Product.where(liked: true).load
liked_products.each do |product|
RecordLoader.for(Product).prime(product.id, product)
end
end
Priming will add key/value to the loader cache only if it didn't exist before.
Your loaders can be tested outside of a GraphQL query by doing the
batch loads in a block passed to GraphQL::Batch.batch
. That method
will set up thread-local state to store the loaders, batch load any
promise returned from the block then clear the thread-local state
to avoid leaking state between tests.
def test_single_query
product = products(:snowboard)
title = GraphQL::Batch.batch do
RecordLoader.for(Product).load(product.id).then(&:title)
end
assert_equal product.title, title
end
After checking out the repo, run bin/setup
to install dependencies. Then, run rake test
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
See our contributing guidelines for more information.
The gem is available as open source under the terms of the MIT License.
FAQs
Unknown package
We found that graphql-batch demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.