saleor / app-sdk Goto Github PK
View Code? Open in Web Editor NEWSDK for building great Saleor Apps
License: Other
SDK for building great Saleor Apps
License: Other
As long as ISS is not provided by saleor in token, this check should not happen. ISS field is cloud addon
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
}
]
}
withSaleorApp(appInstance)(handler)
isVercel: saleorApp.apl instanceof VercelAPL
validateEnv: () => {
return rpocess.env.SOMETHING.lenth > 1
} | string[]
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.
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.
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 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 APIapp-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.
app-sdk
is not tested, which is not acceptable considering this is a public API
app-sdk
doesn't have explicit checks and logging, which is required in dev mode to early show problems
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 */);
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.
Every piece of SDK must be deeply tested. Every bug found must be proven be reproduction test and fixed.
We will have a little more sophisticated logger that will:
NODE_ENV !== 'production'
show explicit error messages, links to docs and guides.NODE+ENV === 'production'
hide error messagesWe can use DEBUG package or something similar to allow users to choose logs scope
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:
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).
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.
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)
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.
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 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
To test JWT middleware, we'll need PollyJS for mocking external calls
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
To protect app from being attacked (re-register with wrong token) - check if token is valid during installation (before setting it to APL)
Check App ID if possible
Now, the app needs to fetch metadata to work (settings, config). This can be received within the subscription payload
This can be supported in SDK
Caveat - if the webhook is retried, metadata can be stale.
SDK will likely need monorepo, because:
We can introduce monorepo with example packages:
etc
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:
https://docs.saleor.io/docs/3.x/developer/extending/apps/manifest
ATM creating the app manifest is done manually by the app developer. Having a typed schema + helper function for creating one would be a handy thing that would minimize potential errors during the app install.
Partially implemented here https://github.com/saleor/saleor-dashboard/pull/2550/files
iframe loader should exchange token and use POST to securely send it to the app server.
Right now, I can't control the main browser history. If I have a more extensive app with internal routing, users can't share links (the app contains only iframe history API).
Is there a plan to implement solutions like:
https://shopify.dev/apps/tools/app-bridge/getting-started/using-react#component
or for start an action?
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
})
SaleorEventRequest<PayloadGraphqlDocument>
(moved from ClickUp)
Mostly done, to be discussed with @magul and @krzysztofwolski
TBH node-fetch should be a peerDependency
Originally posted by @mmiszy in #85 (comment)
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.
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)
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
Saleor app template has the function for verifying the JWT token(https://github.com/saleor/saleor-app-template/blob/main/lib/middlewares.ts#L37).
This is something directly related to the communication App <-> Saleor. Maybe it would be worth having implementation for this in app-sdk.
The dashboard can use extensions to e.g. prefill forms. For example - the extension can fetch product data from PIM. AppBridge should provide an interface to send these data and the dashboard should be able to set form state.
We would like to have a common validation approach with atomic, reusable functions.
To avoid too frequent db hits, caching must be introduced
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
Proposal by @zaiste - introduce a Manifest that builds a Local App. RFC needed
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
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
)
Extend APL AuthData to include App ID and full graphql API url, this will allow additional security checks and improve perf
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
Rel saleor/saleor-dashboard#2550
Add new extension mounting points that can statically render iframe in dashboard pages (not in modals)
Toolbar (React Component) with development tools
Features:
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
Applications usually have endpoints to fetch/update app configuration used by the App interface inside of the Dashboard.
The factory should return handler validating incoming requests and their tokens.
Ref #94
Ref saleor/storefront#592
Replace domain
parameter in APL with a full Saleor GraphQL API URL. The new parameter could be named saleorApiUrl
.
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.
DEBUG feature (DEBUG=*
) for verbose logging
https://github.com/saleor/saleor-app-sdk/blob/main/docs/apl.md#vercelapl
It was reported by @mmiszy that this docs can be confusing
We should make clear the difference between:
Use handler factory to protect handlers for configuration and other internal ones
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.