-
Notifications
You must be signed in to change notification settings - Fork 21
Add new Adapter and Action interfaces, add new Next.js handler implementation, remove middlewares #401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new Adapter and Action interfaces, add new Next.js handler implementation, remove middlewares #401
Changes from 43 commits
09ed14b
3dc2417
e1b4a7e
9ba5562
0d7d3c6
d0bf8b1
6aa3e56
56a404d
a70c440
ab24ad3
238ed0e
7586dc4
4a3743c
5529ec6
3067970
5a3682a
d4e2a8b
6354c56
2744e5b
07ace44
b3aac1b
e959a73
b79b8da
2c0adce
e6e3d6a
7e1a180
3bca89d
e5c8cfe
af80f55
1c66ca9
4d9ebfe
6f922eb
a3c50b2
602971b
922e3e8
4ace1e0
7e70deb
f9ddb84
8c2f4a5
fdeea53
418c4a2
d88bc88
32a31e7
1d1ff8f
6565ca4
2e0b09d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@saleor/app-sdk": patch | ||
| --- | ||
|
|
||
| Removed `/middlewares`, you should use `/handlers` instead. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| --- | ||
| "@saleor/app-sdk": major | ||
| --- | ||
|
|
||
| Removed deprecated fields fields and methods in `/handlers`: | ||
|
|
||
| - `SaleorAsyncWebhook` and `SaleorSyncWebhook` - removed `asyncEvent` and `subscriptionQueryAst` | ||
| - Removed `processSaleorWebhook` and `processProtectedHandler` methods | ||
| - Some types were moved from `/next` to `/shared` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| "@saleor/app-sdk": patch | ||
| --- | ||
|
|
||
| Added abstract `PlatformAdapterInterface` and `ActionHandlerInterface` to enable cross-framework handler implementations. | ||
|
|
||
| Next.js handlers were rewritten to use the new interface. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,7 +41,6 @@ | |
| "debug": "4.3.4", | ||
| "jose": "4.14.4", | ||
| "raw-body": "2.5.2", | ||
| "retes": "0.33.0", | ||
| "uuid": "9.0.0" | ||
| }, | ||
| "devDependencies": { | ||
|
|
@@ -126,11 +125,6 @@ | |
| "import": "./settings-manager/index.mjs", | ||
| "require": "./settings-manager/index.js" | ||
| }, | ||
| "./middleware": { | ||
| "types": "./middleware/index.d.ts", | ||
| "import": "./middleware/index.mjs", | ||
| "require": "./middleware/index.js" | ||
| }, | ||
| "./urls": { | ||
| "types": "./urls.d.ts", | ||
| "import": "./urls.mjs", | ||
|
|
@@ -156,6 +150,11 @@ | |
| "import": "./handlers/shared/index.mjs", | ||
| "require": "./handlers/shared/index.js" | ||
| }, | ||
| "./handlers/actions": { | ||
| "types": "./handlers/actions/index.d.ts", | ||
| "import": "./handlers/actions/index.mjs", | ||
| "require": "./handlers/actions/index.js" | ||
| }, | ||
|
||
| "./saleor-app": { | ||
| "types": "./saleor-app.d.ts", | ||
| "import": "./saleor-app.mjs", | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export * from "./manifest-action-handler" | ||
| export * from "./register-action-handler"; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| import { beforeEach, describe, expect, it, vi } from "vitest"; | ||
|
|
||
| import { SALEOR_SCHEMA_VERSION } from "@/const"; | ||
| import { MockAdapter } from "@/test-utils/mock-adapter"; | ||
| import { AppManifest } from "@/types"; | ||
|
|
||
| import { ManifestActionHandler } from "./manifest-action-handler"; | ||
|
|
||
| describe("ManifestActionHandler", () => { | ||
| const mockManifest: AppManifest = { | ||
| id: "test-app", | ||
| name: "Test Application", | ||
| version: "1.0.0", | ||
| appUrl: "http://example.com", | ||
| permissions: [], | ||
| tokenTargetUrl: "http://example.com/token", | ||
| }; | ||
|
|
||
| let adapter: MockAdapter; | ||
|
|
||
| beforeEach(() => { | ||
| adapter = new MockAdapter({ | ||
| mockHeaders: { | ||
| [SALEOR_SCHEMA_VERSION]: "3.20", | ||
| }, | ||
| baseUrl: "http://example.com", | ||
| }); | ||
| adapter.method = "GET"; | ||
| }); | ||
|
|
||
| it("should call manifest factory and return 200 status when it resolves", async () => { | ||
| const handler = new ManifestActionHandler(adapter); | ||
| const manifestFactory = vi.fn().mockResolvedValue(mockManifest); | ||
|
|
||
| const result = await handler.handleAction({ manifestFactory }); | ||
|
|
||
| expect(result.status).toBe(200); | ||
| expect(result.body).toEqual(mockManifest); | ||
| expect(manifestFactory).toHaveBeenCalledWith({ | ||
| appBaseUrl: "http://example.com", | ||
| request: {}, | ||
| schemaVersion: 3.20, | ||
| }); | ||
| }); | ||
|
|
||
| it("should call manifest factory and return 500 when it throws an error", async () => { | ||
| const handler = new ManifestActionHandler(adapter); | ||
| const manifestFactory = vi.fn().mockRejectedValue(new Error("Test error")); | ||
|
|
||
| const result = await handler.handleAction({ manifestFactory }); | ||
|
|
||
| expect(result.status).toBe(500); | ||
| expect(result.body).toBe("Error resolving manifest file."); | ||
| }); | ||
|
|
||
| it("should return 405 when not called using HTTP GET method", async () => { | ||
| adapter.method = "POST"; | ||
| const handler = new ManifestActionHandler(adapter); | ||
|
|
||
| const manifestFactory = vi.fn().mockResolvedValue(mockManifest); | ||
|
|
||
| const result = await handler.handleAction({ manifestFactory }); | ||
|
|
||
| expect(result.status).toBe(405); | ||
| expect(result.body).toBe("Method not allowed"); | ||
| expect(manifestFactory).not.toHaveBeenCalled(); | ||
| }) | ||
|
|
||
| it("should return 400 when receives null schema version header from unsupported legacy Saleor version", async () => { | ||
| adapter.getHeader = vi.fn().mockReturnValue(null); | ||
| const handler = new ManifestActionHandler(adapter); | ||
|
|
||
| const manifestFactory = vi.fn().mockResolvedValue(mockManifest); | ||
|
|
||
| const result = await handler.handleAction({ manifestFactory }); | ||
|
|
||
| expect(result.status).toBe(400); | ||
| expect(result.body).toBe("Missing schema version header"); | ||
| expect(manifestFactory).not.toHaveBeenCalled(); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| import { createDebug } from "@/debug"; | ||
| import { AppManifest } from "@/types"; | ||
|
|
||
| import { | ||
| ActionHandlerInterface, | ||
| ActionHandlerResult, | ||
| PlatformAdapterInterface, | ||
| } from "../shared/generic-adapter-use-case-types"; | ||
| import { SaleorRequestProcessor } from "../shared/saleor-request-processor"; | ||
|
|
||
| const debug = createDebug("create-manifest-handler"); | ||
|
|
||
| export type CreateManifestHandlerOptions<T> = { | ||
| manifestFactory(context: { | ||
| appBaseUrl: string; | ||
| request: T; | ||
| /** Added in Saleor 3.15 */ | ||
| schemaVersion: number; | ||
| }): AppManifest | Promise<AppManifest>; | ||
| }; | ||
|
|
||
| export class ManifestActionHandler<I> implements ActionHandlerInterface { | ||
| constructor(private adapter: PlatformAdapterInterface<I>) {} | ||
|
|
||
| private requestProcessor = new SaleorRequestProcessor(this.adapter); | ||
|
|
||
| async handleAction(options: CreateManifestHandlerOptions<I>): Promise<ActionHandlerResult> { | ||
| const { schemaVersion } = this.requestProcessor.getSaleorHeaders(); | ||
| const baseURL = this.adapter.getBaseUrl(); | ||
|
|
||
| debug("Received request with schema version \"%s\" and base URL \"%s\"", schemaVersion, baseURL); | ||
|
|
||
| const invalidMethodResponse = this.requestProcessor.withMethod(["GET"]); | ||
|
|
||
| if (invalidMethodResponse) { | ||
| return invalidMethodResponse; | ||
| } | ||
|
|
||
| if (!schemaVersion) { | ||
| return { | ||
| status: 400, | ||
| bodyType: "string", | ||
| body: "Missing schema version header", | ||
| }; | ||
| } | ||
|
|
||
| try { | ||
| const manifest = await options.manifestFactory({ | ||
| appBaseUrl: baseURL, | ||
| request: this.adapter.request, | ||
| schemaVersion, | ||
| }); | ||
|
|
||
| debug("Executed manifest file"); | ||
|
|
||
| return { | ||
| status: 200, | ||
| bodyType: "json", | ||
| body: manifest, | ||
| }; | ||
| } catch (e) { | ||
| debug("Error while resolving manifest: %O", e); | ||
|
|
||
| return { | ||
| status: 500, | ||
| bodyType: "string", | ||
| body: "Error resolving manifest file.", | ||
| }; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't have to write that, I want SDK 1.x to drop support below 3.20