Git Product home page Git Product logo

app-sdk's Issues

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
    }
  ]
}

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[]

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.

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

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

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

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

🚀 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

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

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.

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)

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

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 🎉)

Add APL caching

To avoid too frequent db hits, caching must be introduced

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

Implement basic REST APL

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

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

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)

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

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

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.

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.