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 22 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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)

## [16.2.2] - 2023-10-09

### Changes

- Using built-in fetch whenever available instead of cross-fetch

## [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"));
104 changes: 104 additions & 0 deletions lib/build/framework/custom/framework.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// @ts-nocheck
import type { HTTPMethod } from "../../types";
import { BaseRequest } from "../request";
import { BaseResponse } from "../response";
declare type RequestInfo = {
url: string;
method: HTTPMethod;
headers: Headers;
cookies: Record<string, string>;
query: Record<string, string>;
getJSONBody: () => Promise<any>;
getFormBody: () => Promise<any>;
};
export declare class PreParsedRequest extends BaseRequest {
private request;
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