Svix concurrency workaround (#167)
Some checks are pending
Runs E2E API Tests / build (20.x) (push) Waiting to run
Runs E2E API Tests / build (22.x) (push) Waiting to run
Lint & build / lint_and_build (20.x) (push) Waiting to run
Lint & build / lint_and_build (22.x) (push) Waiting to run
TOC Generator / TOC Generator (push) Waiting to run

This commit is contained in:
Konsti Wohlwend 2024-08-03 21:05:24 -07:00 committed by GitHub
parent a86788d924
commit 94a3edd77d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 65 additions and 17 deletions

View File

@ -18,7 +18,7 @@ jobs:
strategy:
matrix:
node-version: [20.x]
node-version: [20.x, 22.x]
steps:
- uses: actions/checkout@v3
@ -36,17 +36,35 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Create .env.test.local file for stack-backend
- name: Create .env.test.local file for apps/backend
run: cp apps/backend/.env.development apps/backend/.env.test.local
- name: Create .env.test.local file for stack-dashboard
- name: Create .env.test.local file for apps/dashboard
run: cp apps/dashboard/.env.development apps/dashboard/.env.test.local
- name: Create .env.test.local file for apps/e2e
run: cp apps/e2e/.env.development apps/e2e/.env.test.local
- name: Build stack-backend
run: pnpm build:backend
- name: Create .env.test.local file for examples/cjs-test
run: cp examples/cjs-test/.env.development examples/cjs-test/.env.test.local
- name: Create .env.test.local file for examples/demo
run: cp examples/demo/.env.development examples/demo/.env.test.local
- name: Build stack-dashboard
run: pnpm build:dashboard
- name: Create .env.test.local file for examples/docs-examples
run: cp examples/docs-examples/.env.development examples/docs-examples/.env.test.local
- name: Create .env.test.local file for examples/e-commerce
run: cp examples/e-commerce/.env.development examples/e-commerce/.env.test.local
- name: Create .env.test.local file for examples/middleware
run: cp examples/middleware/.env.development examples/middleware/.env.test.local
- name: Create .env.test.local file for examples/partial-prerendering
run: cp examples/partial-prerendering/.env.development examples/partial-prerendering/.env.test.local
- name: Build
run: pnpm build
- name: Start Docker Compose
run: docker compose -f dependencies.compose.yaml up -d
@ -57,6 +75,9 @@ jobs:
- name: Wait on Inbucket
run: npx wait-on tcp:localhost:2500
- name: Wait on Svix
run: npx wait-on tcp:localhost:8113
- name: Initialize database
run: pnpm run prisma -- migrate reset --force

View File

@ -16,7 +16,7 @@ jobs:
strategy:
matrix:
node-version: [18.x, 20.x]
node-version: [20.x, 22.x]
steps:
- uses: actions/checkout@v3
@ -66,3 +66,6 @@ jobs:
- name: Lint
run: pnpm lint
- name: Typecheck
run: pnpm typecheck

View File

@ -14,7 +14,16 @@ async function sendWebhooks(options: {
const server = getEnvVariable("STACK_SVIX_SERVER_URL", "") || undefined;
const svix = new Svix(apiKey, { serverUrl: server });
await svix.application.getOrCreate({ uid: options.projectId, name: options.projectId });
try {
await svix.application.getOrCreate({ uid: options.projectId, name: options.projectId });
} catch (e: any) {
if (e.message.includes("409")) {
// This is a Svix bug; they are working on fixing it
// TODO next-release: remove this
console.warn("[no action required] Svix bug: 409 error when creating application. Remove this warning when Svix fixes this.");
}
console.warn("Error creating application in Svix", e);
}
await svix.message.create(options.projectId, {
eventType: options.type,
payload: {
@ -41,4 +50,4 @@ export const sendUserUpdatedWebhook = createWebhookSender(userUpdatedWebhookEven
export const sendUserDeletedWebhook = createWebhookSender(userDeletedWebhookEvent);
export const sendTeamCreatedWebhook = createWebhookSender(teamCreatedWebhookEvent);
export const sendTeamUpdatedWebhook = createWebhookSender(teamUpdatedWebhookEvent);
export const sendTeamDeletedWebhook = createWebhookSender(teamDeletedWebhookEvent);
export const sendTeamDeletedWebhook = createWebhookSender(teamDeletedWebhookEvent);

View File

@ -10,5 +10,5 @@ describe.todo("`pnpm run lint`", () => {
});
});
expect(error, `Expected no error to be thrown!\n\n\n\nstdout: ${stdout}\n\n\n\nstderr: ${stderr}`).toBeNull();
}, 60_000);
}, 120_000);
});

View File

@ -10,5 +10,5 @@ describe.todo("`pnpm run typecheck`", () => {
});
});
expect(error, `Expected no error to be thrown!\n\n\n\nstdout: ${stdout}\n\n\n\nstderr: ${stderr}`).toBeNull();
}, 60_000);
}, 120_000);
});

View File

@ -0,0 +1,2 @@
declare const Handler: (props: any) => JSX.Element;
export default Handler;

View File

@ -1,7 +1,7 @@
import { StackHandler } from "@stackframe/stack";
const { StackHandler } = require("@stackframe/stack");
const { stackServerApp } = require("../../../stack");
function Handler(props: any) {
function Handler(props) {
return <StackHandler fullPage app={stackServerApp} {...props} />;
}

2
examples/cjs-test/app/page.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
declare const Home: (props: any) => JSX.Element;
export default Home;

View File

@ -1,6 +1,17 @@
import { encodeBase32 } from "./bytes";
import { StackAssertionError } from "./errors";
import { globalVar } from "./globals";
export function generateRandomValues(array: Uint8Array) {
if (!globalVar.crypto) {
throw new StackAssertionError("Crypto API is not available in this environment. Are you using an old browser?");
}
if (!globalVar.crypto.getRandomValues) {
throw new StackAssertionError("crypto.getRandomValues is not available in this environment. Are you using an old browser?");
}
return globalVar.crypto.getRandomValues(array);
}
/**
* Generates a secure alphanumeric string using the system's cryptographically secure
* random number generator.
@ -8,7 +19,7 @@ import { globalVar } from "./globals";
export function generateSecureRandomString(minBitsOfEntropy: number = 224) {
const base32CharactersCount = Math.ceil(minBitsOfEntropy / 5);
const bytesCount = Math.ceil(base32CharactersCount * 5 / 8);
const randomBytes = globalVar.crypto.getRandomValues(new Uint8Array(bytesCount));
const randomBytes = generateRandomValues(new Uint8Array(bytesCount));
const str = encodeBase32(randomBytes);
return str.slice(str.length - base32CharactersCount).toLowerCase();
}

View File

@ -1,9 +1,9 @@
import { globalVar } from "./globals";
import { generateRandomValues } from "./crypto";
export function generateUuid() {
// crypto.randomUuid is not supported in all browsers, so this is a polyfill
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
(+c ^ globalVar.crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
(+c ^ generateRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
);
}