Git Product home page Git Product logo

app-sdk's Introduction

saleor-commerce-logo
Commerce that works with your language and stack
GraphQL native, API-only platform for scalable composable commerce.

Join our community:
Website | Twitter | GitHub Discussions | Discord

Table of Contents

What makes Saleor special?

  • Technology-agnostic - no monolithic plugin architecture or technology lock-in.

  • GraphQL only - Not afterthought API design or fragmentation across different styles of API.

  • Headless and API only - APIs are the only way to interact, configure, or extend the backend.

  • Open source - a single version of Saleor without feature fragmentation or commercial limitations.

  • Cloud native - battle tested on global brands.

  • Native-multichannel - Per channel control of pricing, currencies, stock, product, and more.

Why API-only Architecture?

Saleor's API-first extensibility provides powerful tools for developers to extend backend using webhooks, attributes, metadata, apps, subscription queries, API extensions, dashboard iframes.

Compared to traditional plugin architectures (monoliths) it provides the following benefits:

  • There is less downtime as apps are deployed independently.
  • Reliability and performance - custom logic is separated from the core.
  • Simplified upgrade paths - eliminates incompatibility conflicts between extensions.
  • Technology-agnostic - works with any technology, stack, or language.
  • Parallel development - easier to collaborate than with a monolithic core.
  • Simplified debugging - easier to narrow down bugs in independent services.
  • Scalability - extensions and apps can be scaled independently.

What are the tradeoffs?

If you are a single developer working with a small business that doesn't have high traffic or a critical need for 24/7 availability, using a service-oriented approach might feel more complex compared to the traditional WordPress or Magento approach that provides a language-specific framework, runtime, database schema, aspect-oriented programming, and other tools to a quick start.

However, if you deploy on a daily basis, reliability and uptime is critical, you need to collaborate with other developers, or you have non-trivial requirements you might be in the right place.

Features

  • Enterprise ready: Secure, scalable, and stable. Battle-tested by big brands
  • Dashboard: User-friendly, fast, and productive. (Decoupled project repo )
  • Global by design Multi-currency, multi-language, multi-warehouse, tutti multi!
  • CMS: Manage product or marketing content.
  • Product management: A rich content model for large and complex catalogs.
  • Orders: Flexible order model, split payments, multi-warehouse, returns, and more.
  • Customers: Order history and preferences.
  • Promotion engine: Sales, vouchers, cart rules, giftcards.
  • Payment orchestration: multi-gateway, extensible payment API, flexible flows.
  • Cart: Advanced payment and tax options, with full control over discounts and promotions.
  • Payments: Flexible API architecture allows integration of any payment method.
  • Translations: Fully translatable catalog.
  • SEO: Unlimited SEO freedom with headless architecture.
  • Apps: Extend dashboard via iframe with any web stack.

Saleor Dashboard - Modern UI for managing your e-commerce

Installation

See the Saleor docs for step-by-step installation and deployment instructions.

Note: The main branch is the development version of Saleor and it may be unstable. To use the latest stable version, download it from the Releases page or switch to a release tag.

The current production-ready version is 3.x and you should use this version for all three components:

Saleor Cloud

The fastest way to develop with Saleor is by using developer accounts in Saleor Cloud.

Register here or install our CLI tool:

npm i -g @saleor/cli

and run the following command:

saleor register

Bootstrap your first storefront with:

saleor storefront create --url {your-saleor-graphql-endpoint}

Documentation

Saleor documentation is available here: docs.saleor.io

To contribute, please see the saleor/saleor-docs repository.

Saleor Platform

The easiest way to run all components of Saleor (API, storefront, and dashboard) together on your local machine is to use the saleor-platform project. Go to that repository for instructions on how to use it.

View saleor-platform

Storefront

An open-source storefront example built with Next.js App Router, React.js, TypeScript, GraphQL, and Tailwind CSS.

React Storefront Repository

View Storefront Example

Dashboard

For the dashboard, go to the saleor-dashboard repository.

Contributing

We love your contributions and do our best to provide you with mentorship and support. If you are looking for an issue to tackle, take a look at issues labeled Good first issue

If nothing grabs your attention, check our roadmap or come up with your feature. Just drop us a line or open an issue and we’ll work out how to handle it.

Get more details in our Contributing Guide.

License

Disclaimer: Everything you see here is open and free to use as long as you comply with the license. There are no hidden charges. We promise to do our best to fix bugs and improve the code.

Crafted with ❤️ by Saleor Commerce

[email protected]

app-sdk's People

Contributors

dependabot[bot] avatar github-actions[bot] avatar hazemkhaled avatar krzysztofwolski avatar krzysztofzuraw avatar lkostrowski avatar magul avatar mirekm avatar peelar avatar przlada avatar timuric avatar typeofweb avatar witoszekdev avatar zaiste avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

app-sdk's Issues

Allow manifest path to be configurable

Some projects like checkout doesnt have hardcoded route /api/manifest. Also, non-next apps will not have exactly this route out of the box

Apps should have freedom where to keep manifest, which means none of Saleor components should require exactly this path

Async webhook factory - error handling

As in #94 :

Wrong requests (eg empty body, wrong method) didn't receive error, error was somewhere silently handled

Errors should be gracefully handled and logged in the handler

Can't open installed application on saleor dashboard

How to reproduce

  1. Login as tester account to staging environment
  2. Go dashboard/apps/ and select app with id QXBwOjI1Mg%3D%3D

Actual result

CleanShot 2022-10-24 at 09 16 11@2x

Expected result

I should be able to see configuration for this application

Create Webhook Handler factory

createSaleorWebhookHandler exported from @saleor/app-sdk/handler/next

// src/pages/api/webhooks/order_created.ts

export default createSaleorWebhookHandler({
  eventType: string | string[] 
  ...
})

// eg:
const handler: SaleorEventHandler<OrderCreatedDocument | OrderFullfilledDocument> = (req, res) => {
  const {apl, payload, domain, eventType} = req.context;

  // logic
}

export default createSaleorWebhookHandler({
  handler: handler
})
  • Check what Saleor event type
  • Inject SaleorApp / APL instance
  • Validate tokens and headers
  • Check payload checksum
  • Type extending Next's request with Saleors metadata, eg SaleorEventRequest<PayloadGraphqlDocument>
  • Allow multiple event types
  • Documentation
  • Example

Missing saleor-signature header produces TypeError

It is probably a small thing, but when an App receives a webhook request without a saleor-signature header, the TypeError is raised (and 500 is returned):
error - TypeError: Cannot read properties of undefined (reading 'split')
It happens when withWebhookSignatureVerified is used.

Add SDK support for private metadata per each domain

For apps, to be able to be cloned with entire env (staging promotion to production or other Saleor multi-tenant approach), apps must somehow persist their config.

In the future, we will have dedicated solution for that

At the moment, apps can be configured to use cross-env private metadata, storing a dictionary (with domains and values) instead a single value.

This will be subject of future migration

Provide factory for building simple configuration forms

To reduce boilerplate, SDK can expose a builder, that will return React component with form.

It should receive a config (field, types, validation, ids) and it will render Macaw form, that will automatically be connected to MetadataManager.

For simple use cases this will reduce a lot of boilerplate code

Add APL caching

To avoid too frequent db hits, caching must be introduced

Fix AppBridge erros during mount

Original Sentry issue below.
Wondering if we can add actionId to the error message below so there's more debugging info.

Aso, I believe setTimeout should be used here instead of setInterval? Otherwise intervalId could never get cleared in some cases and the timer will keep on running.


Sentry Issue: SALEOR-APP-CHECKOUT-A

Error: Action response timed out.
  at apply (webpack://_N_E/../../node_modules/.pnpm/@[email protected]/node_modules/@saleor/app-sdk/chunk-5N4RBDUC.mjs:125:18)
  at r (webpack://_N_E/../../node_modules/.pnpm/registry.npmjs.org+@[email protected]/node_modules/@sentry/browser/esm/helpers.js:88:17)

Parse URL params into AppBridgeState

Dashboard renders app with required params (theme, domain...) but also can add some context data like product id etc.

These params are available in URL when apps loads but can be lost when app gets redirects etc.

AppBridge can ensure its persistence by parsing all params from URL and adding them into state

VercelAPL doesnt allow reinstalls

VercelAPL set auth token only once. When app is tried to be reinstalled, VercelAPL doesn't allow to set new token, because it exists

This makes VercelAPL quite poor to use.

This should be changed or at least documented well

Supabase APL

https://supabase.com/

Supabase can have 1st class APL

Consider 2 ways of creating it - by creating supabase instance by APL/SDK, and/or to inject supabase to APL

Implement basic REST APL

  • URLs for the endpoints should be configurable
  • consider caching
  • custom headers for authentication

🚀 app-sdk monorepo

SDK will likely need monorepo, because:

  1. It provides code both for node and browser, having them in single package causes errors already (index file exposes fs, causing broken imports in browser)
  2. It will likely expand with many connections to 3rd party and frameworks - Next.js specific, Remix specific, React specific

We can introduce monorepo with example packages:

  1. sdk/core - typings and some basic symbols
  2. sdk/next - Next adapters for handers
  3. sdk/remix - like Next but for Remix
  4. sdk/react - UI helpers
  5. sdk/app-bridge - App bridge

etc

RFC - vision of app-template and app-sdk

Context

app-sdk project started as a target of refactoring, that moved reusable logic from app-template, so other apps can use it. Some apps, like checkout, are not based on app-template, but they still need to implement some app's interface.

Ongoing problems

app-template without clear boundaries

saleor-app-template is growing. We don't have a clear line what it should look like and what do we want to end up with.

We do want to explore more areas of apps (like queues integrations), but it's not possible to put everything in one project. It will no longer be a template but, rather a huge example project.

app-template doesn't have a line between app code and Saleor details

Saleor provides an interface that must be met when developing apps. There are specific endpoints (eg /register), manifests, etc. This is a subject of documentation and architecture diagrams and must be minimalistic.

Currently, app template mixes Saleor implementation details with example code. As a user, it's really hard to understand what code can be deleted and what is required for the app to be working.

app-template updates

app-template is a boilerplate code, that doesn't work well with updates. It requires a back-merging the original boilerplate, which is very fragile. Not only will limit git history and cause conflicts, but also lock us from introducing app-template with breaking changes.

The community moved from boilerplate solutions and tools like Yeoman aren't so popular anymore for end users

app-sdk doesn't have a release plan and focuses on API

app-sdk is now the target of refactoring, so we have only reusability in our mind, moving code there. It's risky, because this is a public SDK, meaning we can't export too many symbols, otherwise they will be used and we can't introduce breaking changes soon.

app-sdk requires a clear plan as an application toolkit used by Saleor internally but also - in the community.

lack of tests

app-sdk is not tested, which is not acceptable considering this is a public API

low debugability

app-sdk doesn't have explicit checks and logging, which is required in dev mode to early show problems

Proposed solutions

app-sdk vision

Implementation details hidden in SDK

We should aim to hide Saleor implementation details in app-sdk. We shouldn't require people to understand deep logic and details of how Saleor works. Basic docs with architecture diagrams should be enough to write app. Rest is SDK.

Example:

// pages/register.ts

import {createRegisterHandler} from '@saleor/app-sdk/nextjs';

export default createRegisterHandler(/* options */);

Frozen API from v1

Before v1.0.0 we can focus on extracting logic from app-template to SDK, but before official v1 release we must decide which APIs are exported and which are hidden. Only exported ones are subject of freezing.

Further releases can be classic Semver. Breaking changes introduces v2 release, most likely with updated app-templates by Saleor.

Heavily tested

Every piece of SDK must be deeply tested. Every bug found must be proven be reproduction test and fixed.

Debuggability

We will have a little more sophisticated logger that will:

  1. In NODE_ENV !== 'production' show explicit error messages, links to docs and guides.
  2. In NODE+ENV === 'production' hide error messages

We can use DEBUG package or something similar to allow users to choose logs scope

Explicit targets

app-sdk can work with Node, Next, Browser and later in other environments. We can think of having specific packages for that (eg @saleor/app-sdk-remix) but also we can have then scoped (@saleor/app-sdk/remix). It's important to have a clear line of targets, so:

  • Browser code doesn't break Node, etc.
  • Code is tree-shakable

app-template vision

Library of templates

Having a rich app-sdk, we can maintain not one, but a set of app-templates. They can be inspired by Remix Stacks, but also Next Examples.

Each template can be a part of Marketplace to be spawned from UI, or run via CLI (saleor app create sqs --template saleor-app-template-sqs).

Example templates can by literally anything and they can be created by the community.

They can be based on the business problems (app template that subscribes on some webhook) but also tech stack (example of db connection, example with Remix or Deno etc).

Lean templates

While all Saleor logic is moved to SDK, we no longer have bloated code. The template will literally be "hello world" apps and it will be very explicit that code is an example that can be deleted. In JSDOC comments we can mark usage of critical parts, that can't be removed or app breaks.

CLI app doctor

We can create a script (can be part of saleor-cli) that will validate if the app meets Saleor's interface (check for endpoints existence etc)

Template updates with SDK

The template will be versioned/tagged and it will require (in package.json) a specific SDK version range. We can ship bug fixes with patch/minor updates with simple package updates.

When SDK gets updated, we will write a migration guide (one day maybe code gens) to update stale APIs.

Templates maintained by Saleor will be version-locked with SDK, so when SDK enters v3, our templates will be released with the v3 tag.

inferWebhooks should have a possibility to pass list of events

The current implementation of inferWebhooks (src) assumes that event name will be taken from subscription filename. It is ok for basic usage but it would be usefull if we could explicitly provide a list of event names.
With this feature we will have a possibility to create single subscription to support multiple events. Like: I want to have single subscription for all order events.
Manifest:

{
  ...
  "webhooks": [
    {
      "name": "Multiple order's events",
      "events": ["ORDER_CREATED", "ORDER_UPDATED", "ORDER_FULLY_PAID"],
      "query": "subscription { event { ... on OrderCreated { order { id }} ... on OrderFullyPaid { order { id }}}}",
      "targetUrl": "https://example.com/api/webhooks/order-event",
      "isActive": true
    }
  ]
}

app-bridge scope and improvement ideas

This issue aims to aggregate ideas for app-bridge improvement based on its usage in apps.

In saleor/saleor-app-template#38 it was suggested that:

  • app-bridge should have a method for decoding the JWT token
  • should export type ‘DashboardTokenPayload’
  • (either app-bridge or sdk) check if token’s iss is valid and matches the domain passed

Don't export raw retes middlewares

Export handler factories. Dont export middlewares, because they need next adapter and they need coupling with rates. Retes can stay as private detail of SDK.

Middlewares can be exported with toNextHandler from dedicated path (middleware/next)

Encrypt private metadata

Apps should encrypt & decrypt data stored in private metadata (zero trust).

Possibly MetadataManager can use encryption logic. SDK can provide default one, but optional implementation should be possible to provide

Add data flow diagram for the Vercel APL

  • during app deployment on Vercel we are using an additional microservice to setup environment variables
  • create a data flow that explains the whole process
  • describe used env variables, required setup by the CLI
  • use mermaid (can be displayed in the GH interface 🎉)

Upstash APL

Upstash is serverless friendly Redis Saas with a good free tier for developers.

Implementation can use REST API to avoid adding dependencies to the SDK package.

Improve APL and early app validation

  1. Introduce SaleorApp class
  2. Add middleware withSaleorApp(appInstance)(handler)
  3. SaleorApp has APL field
isVercel: saleorApp.apl instanceof VercelAPL

validateEnv: () => {
return rpocess.env.SOMETHING.lenth > 1
}  | string[]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.