Skip to content
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

feat: improved edge function compatibility #702

Merged
merged 30 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
48767ad
feat: use built-in fetch when available
porcellus Sep 22, 2023
b65d084
Merge remote-tracking branch 'origin/16.0' into feat/edge_function_co…
porcellus Sep 25, 2023
ed34bf4
chore: bump version
porcellus Sep 25, 2023
5aad4fe
feat: make it possible to use our middleware in some unsupported fram…
porcellus Sep 28, 2023
16d73e1
Merge branch '16.2' into feat/edge_function_compatibility
porcellus Sep 29, 2023
64111cc
feat: add edge function testing (#704)
porcellus Sep 29, 2023
c4ef7c0
Merge remote-tracking branch 'origin/16.2' into feat/edge_function_co…
porcellus Oct 6, 2023
974d7b5
test: add shebang to utils script
porcellus Oct 6, 2023
ce49df7
test: save the output of the deployment in case of a failure
porcellus Oct 6, 2023
0ee9742
test: save the output of the deployment in case of a failure
porcellus Oct 6, 2023
27d2bd3
test: use netlify_site_id secret
porcellus Oct 6, 2023
2ea171b
test: build before deploying to netlify
porcellus Oct 6, 2023
0098a3a
test: add TEST_DEPLOYED_VERSION flag to the edge function test gh action
porcellus Oct 6, 2023
0cb09e0
test: check if prod deploy in netlify works
porcellus Oct 6, 2023
ea467ad
ci: debug netlify deployment
porcellus Oct 6, 2023
05f5986
ci: fixing netlify test deployment
porcellus Oct 6, 2023
771f6cf
ci: fixing netlify test deployment
porcellus Oct 6, 2023
f4aeedd
ci: remove earlier fix to check if test fails in CI
porcellus Oct 6, 2023
7455e40
Revert "ci: remove earlier fix to check if test fails in CI"
porcellus Oct 6, 2023
fbcf434
feat: move handleCall from nextjs appdir example
porcellus Oct 6, 2023
c8d3d03
fix: getAppDirRequestHandler export
porcellus Oct 6, 2023
89865b0
feat: PartialNextRequest should accept string as method
porcellus Oct 6, 2023
e78c25b
build: ignore new util script when publishing
porcellus Oct 9, 2023
c9448ee
feat: add verifySession for custom frameworks with a new callback to …
porcellus Oct 9, 2023
2370acd
feat: add export for custom framework verifySession
porcellus Oct 10, 2023
ffd51ff
test: add type checking test for getAppDirRequestHandler and custom f…
porcellus Oct 10, 2023
8cf2886
feat: add custom as an option to the framework config
porcellus Oct 10, 2023
efea64d
Merge remote-tracking branch 'origin/16.3' into feat/edge_function_co…
porcellus Oct 10, 2023
5874da6
test: add tests for custom framework
porcellus Oct 10, 2023
f9f4fa8
Merge branch '16.3' into feat/edge_function_compatibility
rishabhpoddar Oct 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/test-edge-function.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: "Test edge function compatibility"
on: push
jobs:
test:
runs-on: ubuntu-latest
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.netlify_auth_token }}
NETLIFY_SITE_ID: ${{ secrets.netlify_site_id }}
TEST_DEPLOYED_VERSION: true
defaults:
run:
working-directory: examples/next/with-emailpassword
steps:
- uses: actions/checkout@v2
- run: echo $GITHUB_REF_NAME
- run: npm install git+https://github.com:supertokens/supertokens-node.git#$GITHUB_SHA
- run: npm install
- run: npm install [email protected] [email protected] puppeteer@^11.0.0 isomorphic-fetch@^3.0.0
- run: netlify deploy --alias 0 --build --json --auth=$NETLIFY_AUTH_TOKEN > deployInfo.json
- run: cat deployInfo.json
- run: |
( \
(echo "=========== Test attempt 1 ===========" && npx mocha --no-config --timeout 80000 test/**/*.test.js) || \
(echo "=========== Test attempt 2 ===========" && npx mocha --no-config --timeout 80000 test/**/*.test.js) || \
(echo "=========== Test attempt 3 ===========" && npx mocha --no-config --timeout 80000 test/**/*.test.js) \
)
- name: The job has failed
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: screenshots
path: |
./**/*screenshot.jpeg
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ coreDriverInterfaceSupported.json
examples/
add-ts-no-check.js
docs/
.prettierignore
.prettierignore
updateLibInExample
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Adds support for configuring multiple frontend domains to be used with the same backend
- Added a new `origin` property to `appInfo`, this can be configured to be a function which allows you to conditionally return the value of the frontend domain. This property will replace `websiteDomain` in a future release of `supertokens-node`
- `websiteDomain` inside `appInfo` is now optional. Using `origin` is recommended over using `websiteDomain`. This is not a breaking change and using `websiteDomain` will continue to work
- Added a "custom" framework you can use in framework normally not supported by our SDK
- Added a next13 app router compatible request handler.

### Fixed

- Fixed an issue where calling signinup for thirdparty recipe would result in a "clone is not a function" error

### Changes

- Using built-in fetch whenever available instead of cross-fetch
- Improved edge-function support

## [16.2.1] - 2023-10-06

- Slight refactors logic to code for social providers to make it consistent across all providers
Expand Down
3 changes: 2 additions & 1 deletion examples/aws/with-emailpassword/test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ describe("SuperTokens Example Basic tests", function () {
]);
await submitForm(page);
await page.waitForNavigation();
const user = await EmailPassword.getUserByEmail("public", email);
const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email });
const user = userList[0];
const callApiBtn = await page.waitForSelector(".sessionButton");
let setAlertContent;
let alertContent = new Promise((res) => (setAlertContent = res));
Expand Down
3 changes: 2 additions & 1 deletion examples/express/with-emailpassword/test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ describe("SuperTokens Example Basic tests", function () {
{ name: "password", value: testPW },
]);
await submitForm(page);
const user = await EmailPassword.getUserByEmail("public", email);
const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email });
const user = userList[0];
const callApiBtn = await page.waitForSelector(".sessionButton");
let setAlertContent;
let alertContent = new Promise((res) => (setAlertContent = res));
Expand Down
3 changes: 2 additions & 1 deletion examples/fastify/with-emailpassword/test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ describe("SuperTokens Example Basic tests", function () {
{ name: "password", value: testPW },
]);
await submitForm(page);
const user = await EmailPassword.getUserByEmail("public", email);
const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email });
const user = userList[0];
const callApiBtn = await page.waitForSelector(".sessionButton");
let setAlertContent;
let alertContent = new Promise((res) => (setAlertContent = res));
Expand Down
3 changes: 2 additions & 1 deletion examples/hapi/with-emailpassword/test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ describe("SuperTokens Example Basic tests", function () {
]);
await submitForm(page);
await page.waitForNavigation();
const user = await EmailPassword.getUserByEmail("public", email);
const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email });
const user = userList[0];
const callApiBtn = await page.waitForSelector(".sessionButton");
let setAlertContent;
let alertContent = new Promise((res) => (setAlertContent = res));
Expand Down
3 changes: 2 additions & 1 deletion examples/koa/with-emailpassword/test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ describe("SuperTokens Example Basic tests", function () {
{ name: "password", value: testPW },
]);
await submitForm(page);
const user = await EmailPassword.getUserByEmail("public", email);
const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email });
const user = userList[0];
const callApiBtn = await page.waitForSelector(".sessionButton");
let setAlertContent;
let alertContent = new Promise((res) => (setAlertContent = res));
Expand Down
3 changes: 2 additions & 1 deletion examples/loopback/with-emailpassword/test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ describe("SuperTokens Example Basic tests", function () {
]);
await submitForm(page);
await page.waitForNavigation();
const user = await EmailPassword.getUserByEmail("public", email);
const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email });
const user = userList[0];
const callApiBtn = await page.waitForSelector(".sessionButton");
let setAlertContent;
let alertContent = new Promise((res) => (setAlertContent = res));
Expand Down
3 changes: 2 additions & 1 deletion examples/nest/with-emailpassword/test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ describe("SuperTokens Example Basic tests", function () {
]);
await submitForm(page);
await page.waitForNavigation();
const user = await EmailPassword.getUserByEmail("public", email);
const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email });
const user = userList[0];
const callApiBtn = await page.waitForSelector(".sessionButton");
let setAlertContent;
let alertContent = new Promise((res) => (setAlertContent = res));
Expand Down
7 changes: 6 additions & 1 deletion examples/next/with-emailpassword/config/appInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ const port = process.env.APP_PORT || 3000;

const apiBasePath = "/api/auth/";

export const websiteDomain = process.env.APP_URL || process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${port}`;
export const websiteDomain =
process.env.APP_URL ||
process.env.NEXT_PUBLIC_APP_URL ||
process.env.DEPLOY_URL ||
process.env.URL ||
`http://localhost:${port}`;

export const appInfo = {
appName: "SuperTokens Demo App",
Expand Down
4 changes: 4 additions & 0 deletions examples/next/with-emailpassword/netlify.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[build]
command = "NEXT_PUBLIC_APP_URL=$DEPLOY_URL npm run build"
functions = "netlify/functions"
publish = ".next"
1 change: 1 addition & 0 deletions examples/next/with-emailpassword/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions examples/next/with-emailpassword/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"private": true,
"scripts": {
"postinstall": "../../../updateLibInExample",
"dev": "next dev",
"build": "next build",
"start": "next start"
Expand Down
28 changes: 25 additions & 3 deletions examples/next/with-emailpassword/test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,19 @@ const EmailPassword = require("supertokens-node/recipe/emailpassword");
// Run the tests in a DOM environment.
require("jsdom-global")();

const apiDomain = "http://localhost:3001";
const websiteDomain = "http://localhost:3000";
let deployInfo;

if (process.env.TEST_DEPLOYED_VERSION) {
deployInfo = require("../deployInfo.json");

if (!deployInfo.deploy_url) {
throw new Error("Deployment failed or json error. " + JSON.stringify(deployInfo));
}
}

const apiDomain = deployInfo?.deploy_url ?? "http://localhost:3000";
const websiteDomain = deployInfo?.deploy_url ?? "http://localhost:3000";

SuperTokensNode.init({
supertokens: {
// We are running these tests without running a local ST instance
Expand Down Expand Up @@ -80,8 +91,19 @@ describe("SuperTokens Example Basic tests", function () {
]);
await submitForm(page);
await page.waitForNavigation();
const user = await EmailPassword.getUserByEmail("public", email);
const userList = await SuperTokensNode.listUsersByAccountInfo("public", { email });
const user = userList[0];
const callApiBtn = await page.waitForSelector(".ProtectedHome_sessionButton__ihFAK");

// we save the cookies..
let originalCookies = (await page._client.send("Network.getAllCookies")).cookies;

// we set the old cookies with invalid access token
originalCookies = originalCookies.map((c) =>
c.name === "sAccessToken" || c.name === "st-access-token" ? { ...c, value: "broken" } : c
);
await page.setCookie(...originalCookies);

let setAlertContent;
let alertContent = new Promise((res) => (setAlertContent = res));
page.on("dialog", async (dialog) => {
Expand Down
3 changes: 3 additions & 0 deletions framework/custom/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "../../lib/build/framework/custom";
import * as _default from "../../lib/build/framework/custom";
export default _default;
6 changes: 6 additions & 0 deletions framework/custom/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
exports.__esModule = true;
__export(require("../../lib/build/framework/custom"));
109 changes: 109 additions & 0 deletions lib/build/framework/custom/framework.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// @ts-nocheck
import type { HTTPMethod } from "../../types";
import { BaseRequest } from "../request";
import { BaseResponse } from "../response";
import { SessionContainerInterface } from "../../recipe/session/types";
declare type RequestInfo = {
url: string;
method: HTTPMethod;
headers: Headers;
cookies: Record<string, string>;
query: Record<string, string>;
getJSONBody: () => Promise<any>;
getFormBody: () => Promise<any>;
setSession?: (session: SessionContainerInterface) => void;
};
export declare class PreParsedRequest extends BaseRequest {
private request;
private _session?;
get session(): SessionContainerInterface | undefined;
set session(value: SessionContainerInterface | undefined);
constructor(request: RequestInfo);
getFormData: () => Promise<any>;
getKeyValueFromQuery: (key: string) => string | undefined;
getJSONBody: () => Promise<any>;
getMethod: () => HTTPMethod;
getCookieValue: (key: string) => string | undefined;
getHeaderValue: (key: string) => string | undefined;
getOriginalURL: () => string;
}
export declare type CookieInfo = {
key: string;
value: string;
domain: string | undefined;
secure: boolean;
httpOnly: boolean;
expires: number;
path: string;
sameSite: "strict" | "lax" | "none";
};
export declare class CollectingResponse extends BaseResponse {
statusCode: number;
readonly headers: Headers;
readonly cookies: CookieInfo[];
body?: string;
constructor();
sendHTMLResponse: (html: string) => void;
setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void;
removeHeader: (key: string) => void;
setCookie: (
key: string,
value: string,
domain: string | undefined,
secure: boolean,
httpOnly: boolean,
expires: number,
path: string,
sameSite: "strict" | "lax" | "none"
) => void;
/**
* @param {number} statusCode
*/
setStatusCode: (statusCode: number) => void;
sendJSONResponse: (content: any) => void;
}
export declare type NextFunction = (err?: any) => void;
export declare const middleware: <OrigReqType = BaseRequest, OrigRespType = BaseResponse>(
wrapRequest?: (req: OrigReqType) => BaseRequest,
wrapResponse?: (req: OrigRespType) => BaseResponse
) => (
request: OrigReqType,
response: OrigRespType,
next?: NextFunction | undefined
) => Promise<
| {
handled: boolean;
error?: undefined;
}
| {
error: any;
handled?: undefined;
}
>;
export declare const errorHandler: () => (
err: any,
request: BaseRequest,
response: BaseResponse,
next: NextFunction
) => Promise<void>;
export declare const CustomFrameworkWrapper: {
middleware: <OrigReqType = BaseRequest, OrigRespType = BaseResponse>(
wrapRequest?: (req: OrigReqType) => BaseRequest,
wrapResponse?: (req: OrigRespType) => BaseResponse
) => (
request: OrigReqType,
response: OrigRespType,
next?: NextFunction | undefined
) => Promise<
| {
handled: boolean;
error?: undefined;
}
| {
error: any;
handled?: undefined;
}
>;
errorHandler: () => (err: any, request: BaseRequest, response: BaseResponse, next: NextFunction) => Promise<void>;
};
export {};
Loading
Loading