Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

e_plat

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

e_plat

  • 1.0.0.pre.rc.1
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

EPlat

EPlat (E-commerce Platform)
A single interface for interacting with E-commerce platform APIs.

Goals:

  • Make it easy to use and request API resources from different platforms.
  • Offer a universal alias interface for interacting with common natured attributes. e.g. Shopify's product.body_html and BigCommerce's product.description.
  • Have a simple, easy-to-understand project structure.
  • The e_plat alias interface mimics Shopify's API schema names and types.

EPlat Platypus


Installation

Install the gem and add to the application's Gemfile by executing:

$ gem "e_plat"

To your gemfile and then run

$ bundle

Config

You can configure which platform APIs are used by updating the EPlat config:

#initializers/e_plat.rb
EPlat.config.shopify_api_version = "2024-07"
EPlat.config.bigcommerce_api_version = "v3"

# EPlat.api_display_name.shopify #=> "2024-07" # presents as the platform would display in URL paths
# EPlat.config.shopify_api_version #=> "2024_07" # coerced interally for creating constants
# EPlat.config.print_graphql_requests #=> false # prints out Shopify graphql queries/mutations to the console

Testing

To run the test for the default versions of all supported platforms:

  bundle exec rails test

To run with specific api versions, you can set globals inline

  EPLAT_SHOPIFY_API_VERSION=2024_07 EPLAT_BIGCOMMERCE_API_VERSION=v3 rails test

To print out Shopify GraphQL queries/mutations

EPLAT_PRINT_GRAPHQL_REQUESTS=true rails test

Releasing a new version

https://dev.to/doctolib/release-a-new-gem-version-je0



Usage

  1. To make requests, first initialize a session like so:
EPlat::Session.new(
  platform: :shopify, 
  store_url: "test-store.myshopify.com", 
  api_token:  "123",
  # store_hash: "optional BigCommerce store hash"
)
  1. You can then make requests to the platform via a singleton call on the Resource class:
EPlat::Product.find(id: 123)
  1. Which will return a platform resource instance that inherits from:
EPlat::Product

EPlat is designed to let you mostly use it's universal interface, but then easily interact with non supported platform attributes when needed.

  tag = EPlat::ScriptTag.new(
    display_scope: :online_store,
    event: :onload,
    src: "https://preproduct.io/mini-script.js"
  )
  tag.name = "mini script" if EPlat::Current.e_plat_session.bigcommerce?
  tag.save 

  # ...when session is a Shopify store
  # POST https://preproduct-test.myshopify.com/admin/api/2024-07/script_tags.json 
  # body: '{"script_tag":{"display_scope":"online_store","event":"onload","src":"https://preproduct.io/mini-script.js"}}'
  # 
  # ...when session is a BigCommerce store
  # POST https://api.bigcommerce.com/stores/d0kmq3bory/v3/content/scripts
  # body: {"location":"head","auto_uninstall":true,"kind":"src","load_method":"async","name":"mini script","enabled":true,"visibility":"storefront","event":"onload","src":"https://preproduct.io/mini-script.js"}

Under The Hood

  1. Request/Resources follow this format: EPlat::ResourceName. Requests are called on the class, which then return an instance.
  2. EPlat resources will return their platform's native attributes, alongside a universal alias interface for viewing/editing via the EPlat schema.
    • EPlat aliases can always be safely called, but aren't always successfully mapped to underlying platform attributes.
    • Whilst the EPlat alias interface and methods often mean you can treat resources the same regardless of platform, you can also ignore this interface and interact with the platform native attributes like regular active resource/record object.
    • The EPlat alias interface is just a set of dynamically created getter/setter/predicate methods with types that control the native attributes of the resource. You can check if an attribute has been mapped by calling `resource.mapped? "attribute_name"`

EPlat Alias Interface

Shop

EPlat::Shop

AliasTypeShopifyBigCommerceEtc
idinteger*nilnil
namestring*namenil
emailstring*admin_emailnil
domainstring*domainnil
provincestring*nilnil
countrystring*countrynil
address1string*nilnil
zipstring*nilnil
citystring*nilnil
sourcestring*nilnil
phonestring*nilnil
latitudefloat*nilnil
longitudefloat*nilnil
primary_localestring*nilnil
address2string*nilnil
created_atdatetime*nilnil
updated_atdatetime*nilnil
country_codestring*country_codenil
country_namestring*nilnil
currencystring*currencynil
customer_emailstring*nilnil
timezonestring*nilnil
iana_timezonestring*nilnil
shop_ownerstring*nilnil
money_formatstring*nilnil
money_with_currency_formatstring*nilnil
weight_unitstring*weight_unitsnil
province_codestring*nilnil
taxes_includedboolean*nilnil
auto_configure_tax_inclusivityboolean*nilnil
tax_shippingboolean*nilnil
county_taxesboolean*nilnil
plan_display_namestring*nilnil
plan_namestring*plan_namenil
has_discountsboolean*nilnil
has_gift_cardsboolean*nilnil
myshopify_domainstring*control_panel_base_urlnil
google_apps_domainstring*nilnil
google_apps_login_enabledboolean*nilnil
money_in_emails_formatstring*nilnil
money_with_currency_in_emails_formatstring*nilnil
eligible_for_paymentsboolean*nilnil
requires_extra_payments_agreementboolean*nilnil
password_enabledboolean*nilnil
has_storefrontboolean*nilnil
eligible_for_card_reader_giveawayboolean*nilnil
financesboolean*nilnil
primary_location_idinteger*nilnil
cookie_consent_levelstring*nilnil
visitor_tracking_consent_preferencestring*nilnil
checkout_api_supportedboolean*nilnil
multi_location_enabledboolean*nilnil
setup_requiredboolean*nilnil
pre_launch_enabledboolean*nilnil
enabled_presentment_currenciesarray*nilnil
transactional_sms_disabledboolean*nilnil
marketing_sms_consent_enabled_at_checkoutboolean*nilnil
  # Bigcommerce translation. myshopify_domain is a permanent 
  shop.myshopify_domain #"store-#{ store_hash }.mybigcommerce.com"
  shop.domain # custom_domain.com
Product

EPlat::Product

AliasTypeShopifyBigCommerceEtc
body_htmlstring*descriptionnil
created_atdatetime*date_creatednil
handlestring*namenil
idinteger*idnil
imagesarray**nil
optionsarray**nil
product_typestring*typenil
published_atdatetime*nilnil
statusstring*availabilitynil
tagsstring*nilnil
template_suffixstring*nilnil
titlestring*namenil
updated_atdatetime*date_modifiednil
variantsarray**nil
vendorstring*nilnil

EPlat::Product::Variant

AliasTypeShopifyBigCommerceEtc
idinteger*idnil
titlestring*option_values&.map(&:label)&.join(' ')nil
pricestring*pricenil
skustring*skunil
positioninteger*nilnil
inventory_policystring*nilnil
compare_at_pricestring*retail_pricenil
inventory_managementbooleaninventoryItem[tracked]nilnil
created_atdatetime*nilnil
updated_atdatetime*nilnil
taxableboolean*nilnil
barcodestring*nilnil
gramsintegergetter only: converted node.inventoryItem[measurement][weight][value]nilnil
weightfloatgetter only: node.inventoryItem[measurement][weight][value]weight
weight_unitstringgetter only: node.inventoryItem[measurement][weight][unit]nil
inventory_item_idintegergetter only: node.inventoryItem[id]nilnil
inventory_quantityintegergetter only: node.inventoryQuantityinventory_levelnil
tax_codestring*nilnil
requires_shippingbooleanInventoryItem[requiresShipping]nilnil

helper methods:
image_src => String | nil, platforms supported: Shopify, Bigcommerce

*Bigcommerce variant.title= setter is not supported

EPlat::Product::Option

AliasTypeShopifyBigCommerceEtc
idinteger*idnil
namestring*display_namenil
positioninteger*sort_ordernil
valuesarray*option_values[i][label]nil

EPlat::Product::Image

AliasTypeShopifyBigCommerceEtc
idinteger*idnil
positioninteger*nilnil
altstring*nilnil
widthinteger*nilnil
heightinteger*nilnil
srcstring*url_standardnil

EPlat::Product::Variant::OptionValue

(not supported for Shopify API v2024_01)

AliasTypeShopifyBigCommerceEtc
idinteger[selected_options][option_value][id]idnil
namestring[selected_options][name]option_display_namenil
valuestring[selected_options][value]labelnil
Order

EPlat::Order

attribute_nametypeShopifyBigCommerceEtc
idinteger*idnil
app_idinteger*nilnil
billing_address_address1string*nilnil
billing_address_address2string*nilnil
billing_address_citystring*nilnil
billing_address_companystring*nilnil
billing_address_countrystring*nilnil
billing_address_first_namestring*nilnil
billing_address_last_namestring*nilnil
billing_address_phonestring*nilnil
billing_address_provincestring*nilnil
billing_address_zipstring*nilnil
billing_address_namestring*nilnil
billing_address_province_codestring*nilnil
billing_address_country_codestring*nilnil
billing_address_latitudestring*nilnil
billing_address_longitudestring*nilnil
browser_ipstring*nilnil
buyer_accepts_marketingboolean*nilnil
cancel_reasonstring*nilnil
cancelled_atdatetime*nilnil
cart_tokenstring*nilnil
checkout_tokenstring*nilnil
client_detailshash*nilnil
closed_atdatetime*nilnil
created_atdatetime*date_creatednil
currencystring*currency_codenil
current_total_discountsstring*discount_amountnil
current_total_discounts_sethash*nilnil
current_total_duties_sethash*nilnil
current_total_pricestring*nilnil
current_total_price_sethash*nilnil
current_subtotal_pricestring*nilnil
current_subtotal_price_sethash*nilnil
current_total_taxstring*nilnil
current_total_tax_sethash*nilnil
customer_localestring*customer_localenil
device_idinteger*nilnil
discount_codesarray*nilnil
emailstring*billing_address[email]nil
estimated_taxesboolean*nilnil
financial_statusstring*status_idnil
fulfillment_statusstring*nilnil
gatewaystring*nilnil
landing_sitestring*nilnil
landing_site_refstring*nilnil
location_idinteger*nilnil
merchant_of_record_app_idinteger*nilnil
namestring*nilnil
notestring*staff_notesnil
note_attributesarray*nilnil
numberinteger*nilnil
order_numberinteger*idnil
order_status_urlstring*nilnil
original_total_duties_sethash*nilnil
payment_gateway_namesarray*nilnil
phonestring*nilnil
presentment_currencystring*nilnil
processed_atstring*nilnil
processing_methodstring*nilnil
referencestring*nilnil
referring_sitestring*nilnil
source_identifierstring*nilnil
source_namestring*nilnil
source_urlstring*nilnil
subtotal_pricestring*subtotal_ex_taxnil
subtotal_price_sethash*nilnil
tagsstring*nilnil
tax_linesarray*nilnil
taxes_includedboolean*nilnil
testboolean*nilnil
tokenstring*nilnil
total_discountsstring*nilnil
total_discounts_sethash*nilnil
total_line_items_pricestring*nilnil
total_line_items_price_sethash*nilnil
total_outstandingstring*nilnil
total_pricestring*total_inc_taxnil
total_price_sethash*nilnil
total_shipping_price_sethash*nilnil
total_taxstring*total_taxnil
total_tax_sethash*nilnil
total_tip_receivedstring*nilnil
total_weightinteger*nilnil
updated_atdatetime*date_modifiednil
billing_addresshash*billing_addressnil
customerhash*nilnil
discount_applicationsarray*nilnil
fulfillmentsarray*nilnil
line_itemsarray*nilnil
payment_detailshash*nilnil
payment_termshash*nilnil
refundsarray*nilnil
shipping_addresshash*nilnil
shipping_linesarray*nilnil

EPlat::Order::ShippingAddress

AliasTypeShopifyBigCommerceEtc
address1string*street_1nil
address2string*street_2nil
citystring*citynil
companystring*companynil
countrystring*countrynil
first_namestring*first_namenil
last_namestring*last_namenil
phonestring*phonenil
provincestring*statenil
zipstring*zipnil
country_codestring*country_iso2nil
province_codestring*nilnil
latitudefloat*nilnil
longitudefloat*nilnil

EPlat::Order::BillingAddress

AliasTypeShopifyBigCommerceEtc
address1string*street_1nil
address2string*street_2nil
citystring*citynil
companystring*companynil
countrystring*countrynil
first_namestring*first_namenil
last_namestring*last_namenil
phonestring*phonenil
provincestring*statenil
zipstring*zipnil
country_codestring*country_iso2nil
province_codestring*nilnil
latitudefloat*nilnil
longitudefloat*nilnil

EPlat::Order::LineItem

AttributeTypeShopifyBigCommerceEtc
idinteger*order[consignments][0][shipping][0][line_items][#{i}][id]nil
admin_graphql_api_idstring*nilnil
fulfillable_quantityinteger*nilnil
fulfillment_servicestring*nilnil
fulfillment_statusstring*nilnil
gift_cardboolean*nilnil
gramsinteger*nilnil
namestring*order[consignments][0][shipping][0][line_items][#{i}][name]nil
pricestring*order[consignments][0][shipping][0][line_items][#{i}][price]nil
price_sethash*nilnil
product_existsboolean*nilnil
product_idinteger*order[consignments][0][shipping][0][line_items][#{i}][product_id]nil
propertiesarray*nilnil
quantityinteger*order[consignments][0][shipping][0][line_items][#{i}][quantity]nil
requires_shippingboolean*nilnil
skustring*order[consignments][0][shipping][0][line_items][#{i}][sku]nil
taxableboolean*nilnil
titlestring*nilnil
total_discountstring*nilnil
total_discount_sethash*nilnil
variant_idinteger*order[consignments][0][shipping][0][line_items][#{i}][variant_id]nil
variant_inventory_managementstring*nilnil
variant_titlestring*nilnil
vendorstring*nilnil
tax_linesarray*nilnil
dutiesarray*nilnil
discount_allocationsarray*nilnil

*line_item uses a virtual collection for BigCommerce, this allows us to present with the correct nesting position, whilst updating the native much deeper nested set below

Metafield

EPlat::Metafield

AliasTypeShopifyBigCommerceEtc
created_atdatetime*date_creatednil
descriptionstring*descriptionnil
idinteger*idnil
keystring*keynil
namespacestring*namespacenil
owner_idinteger*resource_idnil
owner_resourcestring*resource_typenil
updated_atdatetime*date_modifiednil
valuestring*valuenil
typestring*nilnil

*Note: Bigcommerce always assumes a type of String and a native attribute permission_set of "read_and_sf_access"

ScriptTag

EPlat::ScriptTag

AliasTypeShopifyBigCommerceEtc
idinteger/stringiduuid
srcstringsrcsrc
created_atdatetimecreated_atdate_created
updated_atdatetimeupdated_atdate_modified
display_scopestringdisplay_scopevisibility
eventstringeventnil
cachebooleancachenil

*display_scope available options: online_store, order_status, all

**Bigcommerce has some native attribute defaults set, which can be overwritten if needed: location: "head", auto_uninstall: true, kind: "src", load_method: "async", name: "app-script", enabled: true

Webhook

EPlat::Webhook

AliasTypeShopifyBigCommerceEtc
addressstringaddressdestination
api_versionstringapi_versionnil
created_atdatetime/Intcreated_atcreated_at
fieldsarrayfieldsnil
formatstringformatnil
idintegeridid
metafield_namespacesarraymetafield_namespacesnil
private_metafield_namespacesarrayprivate_metafield_namespacesnil
topicstringtopicscope
updated_atdatetime/Intupdated_atupdated_at

*EPlat doesn't make any attemps to alias the varias topic/scope values between platforms. **Notice that BigCommerce uses updated_at and created_at for this resource. Unfortunately it's in a Time Integer format. Haven't yet got dynamic conversion so just tread carefully.




API Coverage

Base / Config
MethodShopifyAPI Gem equivalentShopify - testedBigCom - tested
EPlat::Session.new()::Session.new**
EPlat::Session.new()::Base.activate_session**
EPlat::Session.new()::Session.setup()**
EPlat.config.values[:shopify_api_version]::Baseapi_version*
EPlat.config.values[:bigcommerce_api_version]::Baseapi_version*
Shop
MethodShopify - testedBigCom - testedEtc
::Shop.current**
shop.attribute**
Product
MethodShopify - testedBigCom - testedEtc
::Product.last**
::Product.all**
::Product.attribute**
::Product.find(id)**
::Product.where(attr: '')**
::Product.find_by(attr: '')**
::Product.create(attr:)**
::Product.save**
.save saves nested resourcesonly variants
::Product.delete(id)**
::Product.count**
product.dup**
product.variants**
product.load_all_variants**
product.find_variant(id)**
product.images**
products.next_page?**
products.previous_page?**
products.fetch_next_page**
products.fetch_previous_page**
products.previous_page_info**
products.next_page_info**
 # The 2024 increased Shopify variants limit
 @product.load_all_variants #returns all variants. In Shopify's case it will keep on requesting in batches until it has the full amount (capped at 10x requests of 200 currently i.e. 2,000 variants)

 ### Pagination
 # ...How you might handle pagination.

 # Add pagination cursors to your link's params. This is available on any EPlat::Collection instance
 <%= link_to "previous products", "/", forward_page_info:  products.previous_page_info %>
 <%= link_to "Next products",     "/", backward_page_info: products.next_page_info %>

 # Then on the server, let EPlat handle the correct platform specific arguments to request with.
 EPlat::Product.find(:all, params: {
   EPlat::Current.e_plat_session.pagination_param(:forward) => params['forward_page_info'] 
 })
 EPlat::Product.find(:all, params: {
   EPlat::Current.e_plat_session.pagination_param(:backward) => params['backward_page_info'] 
 })

Product::Variant

MethodShopify - testedBigCom - testedEtc
product.variants**
product.find_variant**
variants.attribute**
variant.attributes.delete**
variant.save**
  • Nested resources currently need to be saved on their own instance. product.variants.first.save, as opposed to product.save
  • Also bear in mind that for platforms like BigCommerce, product and variant IDs are only unique within that store's context
  • so if storing these IDs locally, remember to query via the shop i.e. shop.listings.where(platform_product_id: 123)
Order
MethodShopify - testedBigCom - testedEtc
::Order.last**
::Order.all**
::Order.attribute**
::Order.find(id)**
::Order.where(title: '')**
::Order.find_by(title: '')**
::Order.create(attr: '', )**
::Order.new(attr: '', )**
::Order.save**
::Order.count**
order.cancel**
orders.next_page?*nil
orders.previous_page?*nil
orders.fetch_next_page*nil
orders.fetch_previous_page*nil

*included nested resources: can update non-resource nested hashes like shipping_address, but not proper resources like customer

Metafield
MethodShopify - testedBigCom - testedEtc
product.metafields**
order.metafields**
product.find_metafield(id)**
order.find_metafield(id)**
order.find_metafield(id)**
product.add_metafield(EPlat::Metafield.new {})**
order.add_metafield(EPlat::Metafield.new {})**
.attribute**
.save**
.destroy**
::Metafield.create(attr: '')**
::Metafield.new(attr: '')**
ScriptTag
MethodShopify - testedBigCom - testedEtc
::ScriptTag.new({})**
::ScriptTag.create({})**
::ScriptTag.last**
::ScriptTag.all**
::ScriptTag.find**
.attribute**
.save**
.destroy**

*note that Bigcommerce uses UUID instead of ID for script tags. This should mostly be handled by EPlat, apart from when passing the value to .find

Webhook
MethodShopify - testedBigCom - testedEtc
::Webhook.new({})**
::Webhook.create({})**
::Webhook.last**
::Webhook.all**
::Webhook.find**
.attribute**
.save**
.destroy**
Shopify only

These areas of the API will just support Shopify.

RecurringApplicationCharge

MethodShopify - tested
::RecurringApplicationCharge.current*
::RecurringApplicationCharge.new({})*
::RecurringApplicationCharge.create({})*
::RecurringApplicationCharge.last*
::RecurringApplicationCharge.all*
::RecurringApplicationCharge.find*
.attribute*
.save*
.cancel*
.destroy*
.usage_charges*

*The .current charge is the active charge for the app with the session's store. Only one charge can be active at any time.


RecurringApplicationCharge::UsageCharge

MethodShopify - tested
::UsageCharge.last(params: {recurring_application_charge: r.id})*
::UsageCharge.all(params: {recurring_application_charge: r.id})*
::UsageCharge.find(id, params: {recurring_application_charge: r.id})*
::UsageCharge.new({recurring_application_charge_id: r.id, ...})*
::UsageCharge.create({recurring_application_charge_id: r.id, ...})*
.save*
.attribute*

*Note no :update or :delete options supported. ** the recurring_application_charge_id has to be passed to any requests called on the class.


Outside of the scope of EPlat
  • ShopifyAPI::Asset is depricated. (check_for_store_two_pont_o in main app code.)
  • ShopifyAPI::AccessScope doesn't have other platform API equivilents. (although should be kept track of locally)

    [!NOTE] For all resources, we also have a EPlat::ShopifyWebhook::{resource} class. These use the old REST API mappings that the webhooks still use. At PreProduct we interact with cached webhook hashes using these classes, e.g. EPlat::ShopifyWebhook::Product.new({...}). Meaning we can safely call getter methods and access the usual EPlat schema.



    Request Syntax

    ### activate session
    EPlat::Session.new(
    	platform: :shopify, 
    	store_url: "hi.myshopify.com", 
    	api_token: 11223344
    )
    
    ### create new record
    product = EPlat::Product.new(title: 't-shirt')
    product.save
    # or... 
    EPlat::Product.create(title: 't-shirt')
    new_product = product.dup #duplicates entry without saving
    
    ### delete record
    EPlat::Product.delete(params[:id])
    # or... 
    EPlat::Product.find(my_id).destroy
    
    ### save record
    product = EPlat::Product.new(title: 't-shirt')
    product.save # true or false
    product.errors # active record like errors if .save returned false
    product.formatted_id #returns the resource ID in the platform's format. i.e. Shopify Product would be "gid://shopify/Product/xxx", Shopify Order would be 123, BC order: 123
    
    product.full_response # <Net::HTTPOK>
    product.headers # { "date"=>"Fri, 17 Nov 2023 14:25:53 GMT", ...}
    JSON.parse(product.full_response.body) # "{...}"
    
    
    ### get records
    EPlat::Product.find(101) # GET EPlat::Product.first(args)) (or EPlat::Product.last(args))
    EPlat::Product.all 
    EPlat::Product.last 
    EPlat::Product.where(title: "tshirt") # GET ?title=tshirt
    EPlat::Product.find_by(title: "tshirt") # GET ?title=tshirt &.first
    EPlat::Product.find(:all, params: {title: "tshirt"}) # ?title=tshirt
    
    EPlat::Product.find(99, from: :leader) # GET /platforms_resource_path/leader.json
    EPlat::Product.find(99, from: "/product/1/specific_url.json") #GET /product/1/specific_url.json
    
    ### count records
    EPlat::Product.count # 2
    
    # Nested resources - pass in the parent resource's ID to the params hash
    EPlat::Product::Variant.find(variant_id, params: {product: product.id}) # /admin/api/2024-07/products/{{ product.id }}/variants/{{ variant_id }}.json 
    EPlat::Product::Variant.collection_path(product: 5) # /admin/api/2024-07/products/5/variants.json
    
    
    
    

    Attribute info

    
    # Attributes
    product.attributes  #return all native platform attributes
    product.mapped_attributes.entries #return all mapped e_plat attributes for a resource
    
    # Attribute keys
    product.native_keys #An array of the native attribute keys
    product.mapped_attributes. #An array of the e_plat attribute keys
    
    # look up mapping
    product.mapping.aliases # a hash of the mapped aliases. {native_attribute => e_plat_attribute, ...}
    product.mapped? "body_html" #check if a platforms resource is mapped to a specific EPlat alias
    
    # In the context of a Bigcommerce product that has aliases:
    product.changed_attributes # {}
    product.title = "oi"
    product.changed_attributes # {"name"=>"oi", "title"=>"oi"}  
    #title is the e_plat key which won't be included in requests to the server. The native key 'name' has automatically been updated and will be sent in requests.
    
    product.as_json # hash of any updated attributes
    product.as_full_json # hash of all attributes, regardless of if they've been updated or not
    product.to_json # JSON string of any updated_attributes
    product.to_full_json # JSON string of all attributes. regardless of if they've been updated or not
    product.as_eplat_json # hash of all resource's EPlat attributes, values as EPlat getters produce
    product.to_eplat_json # JSON of all resource's EPlat attributes, values as EPlat getters produce
    
    

    FAQs

    Package last updated on 17 Oct 2024

    Did you know?

    Socket

    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.

    Install

    Related posts

    SocketSocket SOC 2 Logo

    Product

    • Package Alerts
    • Integrations
    • Docs
    • Pricing
    • FAQ
    • Roadmap
    • Changelog

    Packages

    npm

    Stay in touch

    Get open source security insights delivered straight into your inbox.


    • Terms
    • Privacy
    • Security

    Made with ⚡️ by Socket Inc