mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
Upgrade backend to Next.js 15 (#360)
This commit is contained in:
parent
b8a7e911ea
commit
0413706c39
113
.github/workflows/check-codegen.yaml
vendored
Normal file
113
.github/workflows/check-codegen.yaml
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
name: Ensure up-to-date codegen
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
- main
|
||||
|
||||
jobs:
|
||||
check_codegen:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [22.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9.1.2
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Create .env.production.local file for apps/backend
|
||||
run: cp apps/backend/.env.development apps/backend/.env.production.local
|
||||
|
||||
- name: Create .env.production.local file for apps/dashboard
|
||||
run: cp apps/dashboard/.env.development apps/dashboard/.env.production.local
|
||||
|
||||
- name: Create .env.production.local file for apps/e2e
|
||||
run: cp apps/e2e/.env.development apps/e2e/.env.production.local
|
||||
|
||||
- name: Create .env.production.local file for examples/cjs-test
|
||||
run: cp examples/cjs-test/.env.development examples/cjs-test/.env.production.local
|
||||
|
||||
- name: Create .env.production.local file for examples/demo
|
||||
run: cp examples/demo/.env.development examples/demo/.env.production.local
|
||||
|
||||
- name: Create .env.production.local file for examples/docs-examples
|
||||
run: cp examples/docs-examples/.env.development examples/docs-examples/.env.production.local
|
||||
|
||||
- name: Create .env.production.local file for examples/e-commerce
|
||||
run: cp examples/e-commerce/.env.development examples/e-commerce/.env.production.local
|
||||
|
||||
- name: Create .env.production.local file for examples/middleware
|
||||
run: cp examples/middleware/.env.development examples/middleware/.env.production.local
|
||||
|
||||
- name: Create .env.production.local file for examples/partial-prerendering
|
||||
run: cp examples/partial-prerendering/.env.development examples/partial-prerendering/.env.production.local
|
||||
|
||||
- name: Create .env.production.local file for examples/supabase
|
||||
run: cp examples/supabase/.env.development examples/supabase/.env.production.local
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
|
||||
- name: Store Quetzal API key in packages/stack/.env.local
|
||||
run: echo "QUETZAL_API_KEY=${{ secrets.QUETZAL_API_KEY }}" > packages/stack/.env.local
|
||||
|
||||
- name: Run code gen
|
||||
run: pnpm codegen
|
||||
|
||||
- name: Check for uncommitted changes
|
||||
run: |
|
||||
if [[ -n $(git status --porcelain) ]]; then
|
||||
echo "Error: There are uncommitted changes after build/lint/typecheck."
|
||||
echo "Please commit all changes before pushing."
|
||||
git status
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
check_prisma_migrations:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [22.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9.1.2
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Start Postgres shadow DB
|
||||
run: docker run -d --name postgres-prisma-diff-shadow -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=PLACEHOLDER-PASSWORD--dfaBC1hm1v -e POSTGRES_DB=postgres -p 5432:5432 postgres:latest
|
||||
|
||||
- name: Check for differences in Prisma schema and migrations
|
||||
run: pnpm run prisma migrate diff --from-migrations ./prisma/migrations --to-schema-datamodel ./prisma/schema.prisma --shadow-database-url postgres://postgres:PLACEHOLDER-PASSWORD--dfaBC1hm1v@localhost:5432/postgres --exit-code
|
||||
2
.github/workflows/e2e-api-tests.yaml
vendored
2
.github/workflows/e2e-api-tests.yaml
vendored
@ -69,8 +69,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
env:
|
||||
QUETZAL_API_KEY: ${{ secrets.QUETZAL_API_KEY }}
|
||||
|
||||
- name: Start Docker Compose
|
||||
run: docker compose -f dependencies.compose.yaml up -d
|
||||
|
||||
5
.github/workflows/lint-and-build.yaml
vendored
5
.github/workflows/lint-and-build.yaml
vendored
@ -66,11 +66,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
env:
|
||||
QUETZAL_API_KEY: ${{ secrets.QUETZAL_API_KEY }}
|
||||
|
||||
- name: Run code gen
|
||||
run: pnpm codegen
|
||||
|
||||
- name: Lint
|
||||
run: pnpm lint
|
||||
|
||||
2
.github/workflows/preview-docs.yaml
vendored
2
.github/workflows/preview-docs.yaml
vendored
@ -56,8 +56,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
env:
|
||||
QUETZAL_API_KEY: ${{ secrets.QUETZAL_API_KEY }}
|
||||
|
||||
- name: Check API is valid
|
||||
run: pnpm run fern check
|
||||
|
||||
2
.github/workflows/publish-docs.yaml
vendored
2
.github/workflows/publish-docs.yaml
vendored
@ -74,8 +74,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
env:
|
||||
QUETZAL_API_KEY: ${{ secrets.QUETZAL_API_KEY }}
|
||||
|
||||
- name: Check API is valid
|
||||
run: pnpm run fern check
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
"seed": "pnpm run with-env tsx prisma/seed.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@next/bundle-analyzer": "^14.0.3",
|
||||
"@next/bundle-analyzer": "15.0.3",
|
||||
"@node-oauth/oauth2-server": "^5.1.0",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@opentelemetry/api-logs": "^0.53.0",
|
||||
@ -55,15 +55,15 @@
|
||||
"bcrypt": "^5.1.1",
|
||||
"dotenv-cli": "^7.3.0",
|
||||
"jose": "^5.2.2",
|
||||
"next": "^14.2.5",
|
||||
"next": "15.0.3",
|
||||
"nodemailer": "^6.9.10",
|
||||
"oidc-provider": "^8.5.1",
|
||||
"openid-client": "^5.6.4",
|
||||
"oslo": "^1.2.1",
|
||||
"pg": "^8.11.3",
|
||||
"posthog-node": "^4.1.0",
|
||||
"react": "^18.2",
|
||||
"react-dom": "^18.2",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"semver": "^7.6.3",
|
||||
"server-only": "^0.0.1",
|
||||
"sharp": "^0.32.6",
|
||||
@ -76,7 +76,8 @@
|
||||
"@types/node": "^20.8.10",
|
||||
"@types/nodemailer": "^6.4.14",
|
||||
"@types/oidc-provider": "^8.5.1",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react": "link:@types/react@18.3.12",
|
||||
"@types/react-dom": "^19.0.0",
|
||||
"@types/semver": "^7.5.8",
|
||||
"concurrently": "^8.2.2",
|
||||
"glob": "^10.4.1",
|
||||
|
||||
@ -61,7 +61,7 @@ export const GET = createSmartRouteHandler({
|
||||
throw new KnownErrors.InvalidOAuthClientIdOrSecret(query.client_id);
|
||||
}
|
||||
|
||||
if (!await checkApiKeySet(query.client_id, { publishableClientKey: query.client_secret })) {
|
||||
if (!(await checkApiKeySet(query.client_id, { publishableClientKey: query.client_secret }))) {
|
||||
throw new KnownErrors.InvalidPublishableClientKey(query.client_id);
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ export const GET = createSmartRouteHandler({
|
||||
|
||||
// prevent CSRF by keeping track of the inner state in cookies
|
||||
// the callback route must ensure that the inner state cookie is set
|
||||
cookies().set(
|
||||
(await cookies()).set(
|
||||
"stack-oauth-inner-" + innerState,
|
||||
"true",
|
||||
{
|
||||
|
||||
@ -47,8 +47,8 @@ const handler = createSmartRouteHandler({
|
||||
}),
|
||||
async handler({ params, query, body }, fullReq) {
|
||||
const innerState = query.state ?? (body as any)?.state ?? "";
|
||||
const cookieInfo = cookies().get("stack-oauth-inner-" + innerState);
|
||||
cookies().delete("stack-oauth-inner-" + innerState);
|
||||
const cookieInfo = (await cookies()).get("stack-oauth-inner-" + innerState);
|
||||
(await cookies()).delete("stack-oauth-inner-" + innerState);
|
||||
|
||||
if (cookieInfo?.value !== 'true') {
|
||||
throw new StatusError(StatusError.BadRequest, "OAuth cookie not found. This is likely because you refreshed the page during the OAuth sign in process. Please try signing in again");
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { StackAssertionError } from "@stackframe/stack-shared/dist/utils/errors";
|
||||
import { assertIpAddress, isIpAddress } from "@stackframe/stack-shared/dist/utils/ips";
|
||||
import { isIpAddress } from "@stackframe/stack-shared/dist/utils/ips";
|
||||
import { pick } from "@stackframe/stack-shared/dist/utils/objects";
|
||||
import { headers } from "next/headers";
|
||||
|
||||
@ -66,7 +66,7 @@ export async function getEndUserInfo(): Promise<
|
||||
| { maybeSpoofed: false, exactInfo: EndUserInfoInner }
|
||||
| null
|
||||
> {
|
||||
const allHeaders = headers();
|
||||
const allHeaders = await headers();
|
||||
|
||||
// note that this is just the requester claiming to be a browser; we can't trust them as they could just fake the
|
||||
// headers
|
||||
@ -84,7 +84,6 @@ export async function getEndUserInfo(): Promise<
|
||||
?? allHeaders.get("x-vercel-forwarded-for")
|
||||
?? allHeaders.get("x-real-ip")
|
||||
?? allHeaders.get("x-forwarded-for")?.split(",").at(0)
|
||||
?? allHeaders.get("x-stack-direct-requester-or-proxy-ip")
|
||||
?? undefined;
|
||||
if (!ip || !isIpAddress(ip)) {
|
||||
console.warn("getEndUserIp() found IP address in headers, but is invalid. This is most likely a misconfigured client", { ip, headers: Object.fromEntries(allHeaders) });
|
||||
|
||||
@ -54,8 +54,7 @@ export async function middleware(request: NextRequest) {
|
||||
const isApiRequest = url.pathname.startsWith('/api/');
|
||||
|
||||
const newRequestHeaders = new Headers(request.headers);
|
||||
// store the direct IP address of the requester or proxy so we can read it with `headers()` later
|
||||
newRequestHeaders.set("x-stack-direct-requester-or-proxy-ip", request.ip ?? '');
|
||||
// here we could update the request headers (currently we don't)
|
||||
|
||||
const responseInit = isApiRequest ? {
|
||||
request: {
|
||||
|
||||
@ -257,7 +257,7 @@ async function parseAuth(req: NextRequest): Promise<SmartRequestAuth | null> {
|
||||
};
|
||||
}
|
||||
|
||||
export async function createSmartRequest(req: NextRequest, bodyBuffer: ArrayBuffer, options?: { params: Record<string, string> }): Promise<SmartRequest> {
|
||||
export async function createSmartRequest(req: NextRequest, bodyBuffer: ArrayBuffer, options?: { params: Promise<Record<string, string>> }): Promise<SmartRequest> {
|
||||
const urlObject = new URL(req.url);
|
||||
const clientVersionMatch = req.headers.get("x-stack-client-version")?.match(/^(\w+)\s+(@[\w\/]+)@([\d.]+)$/);
|
||||
|
||||
@ -270,7 +270,7 @@ export async function createSmartRequest(req: NextRequest, bodyBuffer: ArrayBuff
|
||||
.map(([key, values]) => [key, values.map(([_, value]) => value)]),
|
||||
),
|
||||
query: Object.fromEntries(urlObject.searchParams.entries()),
|
||||
params: options?.params ?? {},
|
||||
params: await options?.params ?? {},
|
||||
auth: await parseAuth(req),
|
||||
clientVersion: clientVersionMatch ? {
|
||||
platform: clientVersionMatch[1],
|
||||
|
||||
@ -98,7 +98,9 @@ export function handleApiRequest(handler: (req: NextRequest, options: any, reque
|
||||
|
||||
console.log(`[ ERR] [${requestId}] ${req.method} ${req.url}: ${statusError.message}`);
|
||||
if (!commonErrors.some(e => statusError instanceof e)) {
|
||||
console.debug(`For the error above with request ID ${requestId}, the full error is:`, statusError);
|
||||
// HACK: Log statusError.stack instead of statusError to get around buggy Next.js pretty-printing
|
||||
// https://www.reddit.com/r/nextjs/comments/1gkxdqe/comment/m19kxgn/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
|
||||
console.debug(`For the error above with request ID ${requestId}, the full error is:`, statusError.stack);
|
||||
}
|
||||
|
||||
const res = await createResponse(req, requestId, {
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
"@types/canvas-confetti": "^1.6.4",
|
||||
"@types/node": "^20.8.10",
|
||||
"@types/nodemailer": "^6.4.14",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react": "link:@types/react@18.3.12",
|
||||
"@types/react-dom": "^18",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"glob": "^10.4.1",
|
||||
|
||||
1
apps/dashboard/src/globals.d.ts
vendored
1
apps/dashboard/src/globals.d.ts
vendored
@ -2,6 +2,7 @@ declare module 'remark-heading-id';
|
||||
|
||||
declare namespace React {
|
||||
// inert doesn't exist in React.HTMLAttributes, so we need to extend it
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
interface HTMLAttributes<T> {
|
||||
inert?: '',
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import { encodeBase64 } from "@stackframe/stack-shared/dist/utils/bytes";
|
||||
import { generateSecureRandomString } from "@stackframe/stack-shared/dist/utils/crypto";
|
||||
import { StackAssertionError, throwErr } from "@stackframe/stack-shared/dist/utils/errors";
|
||||
import { filterUndefined } from "@stackframe/stack-shared/dist/utils/objects";
|
||||
import { nicify } from "@stackframe/stack-shared/dist/utils/strings";
|
||||
import * as jose from "jose";
|
||||
import { expect } from "vitest";
|
||||
import { Context, Mailbox, NiceRequestInit, NiceResponse, STACK_BACKEND_BASE_URL, STACK_INTERNAL_PROJECT_ADMIN_KEY, STACK_INTERNAL_PROJECT_CLIENT_KEY, STACK_INTERNAL_PROJECT_ID, STACK_INTERNAL_PROJECT_SERVER_KEY, createMailbox, localRedirectUrl, niceFetch, updateCookiesFromResponse } from "../helpers";
|
||||
@ -100,7 +101,7 @@ export async function niceBackendFetch(url: string | URL, options?: Omit<NiceReq
|
||||
}),
|
||||
});
|
||||
if (res.status >= 500 && res.status < 600) {
|
||||
throw new StackAssertionError(`Unexpected internal server error: ${res.status} ${res.body}`);
|
||||
throw new StackAssertionError(`Unexpected internal server error: ${res.status} ${typeof res.body === "string" ? res.body : nicify(res.body)}`);
|
||||
}
|
||||
if (res.headers.has("x-stack-known-error")) {
|
||||
expect(res.status).toBeGreaterThanOrEqual(400);
|
||||
|
||||
3
apps/e2e/tests/globals.d.ts
vendored
3
apps/e2e/tests/globals.d.ts
vendored
@ -1,10 +1,13 @@
|
||||
import 'vitest';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
interface CustomMatchers<R = unknown> {
|
||||
toSatisfy: (predicate: (value: string) => boolean) => R,
|
||||
}
|
||||
|
||||
declare module 'vitest' {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
interface Assertion<T = any> extends CustomMatchers<T> {}
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
interface AsymmetricMatchersContaining extends CustomMatchers {}
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ services:
|
||||
image: svix/svix-server
|
||||
environment:
|
||||
WAIT_FOR: 'true'
|
||||
SVIX_REDIS_DSN: redis://placeholder-username:PASSWORD-PLACEHOLDER--oVn8GSD6b9@svix-redis:6379
|
||||
SVIX_REDIS_DSN: redis://:PASSWORD-PLACEHOLDER--oVn8GSD6b9@svix-redis:6379
|
||||
SVIX_DB_DSN: postgres://postgres:PASSWORD-PLACEHOLDER--KsoIMcchtp@svix-db:5432/svix
|
||||
SVIX_CACHE_TYPE: memory
|
||||
SVIX_JWT_SECRET: secret
|
||||
|
||||
@ -10,14 +10,14 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stackframe/stack": "workspace:*",
|
||||
"next": "^14.1",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"@stackframe/stack": "workspace:*"
|
||||
"react-dom": "^18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react": "link:@types/react@18.3.12",
|
||||
"@types/react-dom": "^18",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.3",
|
||||
|
||||
@ -24,17 +24,11 @@
|
||||
"react-icons": "^5.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "npm:types-react@19.0.0-rc.1",
|
||||
"@types/react": "link:@types/react@18.3.12",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"postcss": "^8.4.47",
|
||||
"rimraf": "^5.0.10",
|
||||
"tailwindcss": "^3.4.14"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"@types/react": "npm:types-react@19.0.0-rc.1\n",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,11 +24,11 @@
|
||||
"react-icons": "^5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^5.0.5",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react": "link:@types/react@18.3.12",
|
||||
"@types/react-dom": "^18",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"postcss": "^8.4.35",
|
||||
"rimraf": "^5.0.5",
|
||||
"tailwindcss": "^3.4.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,12 +17,12 @@
|
||||
"react-dom": "^18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^5.0.5",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react": "link:@types/react@18.3.12",
|
||||
"@types/react-dom": "^18",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.5",
|
||||
"rimraf": "^5.0.5",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,14 +10,14 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stackframe/stack": "workspace:*",
|
||||
"next": "^14.2",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"@stackframe/stack": "workspace:*"
|
||||
"react-dom": "^18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react": "link:@types/react@18.3.12",
|
||||
"@types/react-dom": "^18",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.3",
|
||||
|
||||
@ -10,14 +10,14 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stackframe/stack": "workspace:*",
|
||||
"next": "14.3.0-canary.26",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"@stackframe/stack": "workspace:*"
|
||||
"react-dom": "^18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react": "link:@types/react@18.3.12",
|
||||
"@types/react-dom": "^18",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.3",
|
||||
|
||||
@ -13,14 +13,14 @@
|
||||
"@supabase/ssr": "latest",
|
||||
"@supabase/supabase-js": "latest",
|
||||
"jose": "^5.2.2",
|
||||
"next": "^15.0.3",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"next": "^14.2.5",
|
||||
"react": "^18.3.0",
|
||||
"react-dom": "^18.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.10.6",
|
||||
"@types/react": "18.2.46",
|
||||
"@types/react-dom": "18.2.18",
|
||||
"@types/react": "link:@types/react@18.3.12",
|
||||
"@types/react-dom": "^18.3.12",
|
||||
"typescript": "5.3.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +63,10 @@
|
||||
"wait-on": "^8.0.1"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {}
|
||||
"overrides": {
|
||||
"@types/react": "^18.2.0",
|
||||
"@types/react-dom": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"npm": ">=10.0.0",
|
||||
|
||||
@ -9,6 +9,7 @@ import { isValidUrl } from "./utils/urls";
|
||||
import { isUuid } from "./utils/uuids";
|
||||
|
||||
declare module "yup" {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
interface StringSchema<TType, TContext, TDefault, TFlags> {
|
||||
nonEmpty(message?: string): StringSchema<TType, TContext, TDefault, TFlags>,
|
||||
}
|
||||
|
||||
@ -89,6 +89,8 @@
|
||||
"rimraf": "^5.0.10",
|
||||
"react": "^18.2",
|
||||
"react-dom": "^18.2",
|
||||
"@types/react": "^18.2.12",
|
||||
"@types/react-dom": "^18.2.12",
|
||||
"next": "^14.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,10 +3,10 @@ import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMe
|
||||
import { Column } from "@tanstack/react-table";
|
||||
import { LucideIcon, EyeOff, ArrowUp, ArrowDown } from "lucide-react";
|
||||
|
||||
interface DataTableColumnHeaderProps<TData, TValue> extends React.HTMLAttributes<HTMLDivElement> {
|
||||
type DataTableColumnHeaderProps<TData, TValue> = {
|
||||
column: Column<TData, TValue>,
|
||||
columnTitle: React.ReactNode,
|
||||
}
|
||||
} & React.HTMLAttributes<HTMLDivElement>
|
||||
|
||||
function Item(props: { icon: LucideIcon, onClick: () => void, children: React.ReactNode }) {
|
||||
return (
|
||||
|
||||
@ -15,7 +15,7 @@ import { Column } from "@tanstack/react-table";
|
||||
import { ListFilter } from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
interface DataTableFacetedFilterProps<TData, TValue> {
|
||||
type DataTableFacetedFilterProps<TData, TValue> = {
|
||||
column?: Column<TData, TValue>,
|
||||
title?: string,
|
||||
options: {
|
||||
|
||||
@ -8,7 +8,7 @@ import {
|
||||
} from "@stackframe/stack-ui";
|
||||
import { Table } from "@tanstack/react-table";
|
||||
|
||||
interface DataTablePaginationProps<TData> {
|
||||
type DataTablePaginationProps<TData> = {
|
||||
table: Table<TData>,
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ import { download, generateCsv, mkConfig } from 'export-to-csv';
|
||||
import { DownloadIcon } from "lucide-react";
|
||||
import { DataTableViewOptions } from "./view-options";
|
||||
|
||||
interface DataTableToolbarProps<TData> {
|
||||
type DataTableToolbarProps<TData> = {
|
||||
table: Table<TData>,
|
||||
toolbarRender?: (table: Table<TData>) => React.ReactNode,
|
||||
showDefaultToolbar?: boolean,
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
} from "@stackframe/stack-ui";
|
||||
import { Table } from "@tanstack/react-table";
|
||||
|
||||
interface DataTableViewOptionsProps<TData> {
|
||||
type DataTableViewOptionsProps<TData> = {
|
||||
table: Table<TData>,
|
||||
}
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ const Command: React.FC<React.ComponentPropsWithoutRef<typeof CommandPrimitive>>
|
||||
));
|
||||
Command.displayName = CommandPrimitive.displayName;
|
||||
|
||||
interface CommandDialogProps extends DialogProps {}
|
||||
type CommandDialogProps = {} & DialogProps
|
||||
|
||||
const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
|
||||
return (
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { forwardRefIfNeeded } from "@stackframe/stack-shared/dist/utils/react";
|
||||
import { CheckIcon } from "@radix-ui/react-icons";
|
||||
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
|
||||
import { forwardRefIfNeeded } from "@stackframe/stack-shared/dist/utils/react";
|
||||
import React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
|
||||
|
||||
@ -50,9 +50,7 @@ const sheetVariants = cva(
|
||||
}
|
||||
);
|
||||
|
||||
interface SheetContentProps
|
||||
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
||||
VariantProps<typeof sheetVariants> { hasCloseButton?: boolean }
|
||||
type SheetContentProps = { hasCloseButton?: boolean } & React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content> & VariantProps<typeof sheetVariants>
|
||||
|
||||
const SheetContent = forwardRefIfNeeded<
|
||||
React.ElementRef<typeof SheetPrimitive.Content>,
|
||||
|
||||
@ -9,7 +9,7 @@ import { runAsynchronouslyWithAlert } from "@stackframe/stack-shared/dist/utils/
|
||||
import { useAsyncCallback } from "@stackframe/stack-shared/dist/hooks/use-async-callback";
|
||||
import { Spinner } from "./spinner";
|
||||
|
||||
interface OriginalSwitchProps extends React.ComponentProps<typeof SwitchPrimitives.Root> {}
|
||||
type OriginalSwitchProps = {} & React.ComponentProps<typeof SwitchPrimitives.Root>
|
||||
|
||||
const OriginalSwitch = forwardRefIfNeeded<
|
||||
React.ElementRef<typeof SwitchPrimitives.Root>,
|
||||
@ -31,11 +31,11 @@ const OriginalSwitch = forwardRefIfNeeded<
|
||||
</SwitchPrimitives.Root>
|
||||
));
|
||||
OriginalSwitch.displayName = SwitchPrimitives.Root.displayName;
|
||||
interface AsyncSwitchProps extends OriginalSwitchProps {
|
||||
type AsyncSwitchProps = {
|
||||
onCheckedChange?: (checked: boolean) => Promise<void> | void,
|
||||
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => Promise<void> | void,
|
||||
loading?: boolean,
|
||||
}
|
||||
} & OriginalSwitchProps
|
||||
|
||||
const Switch = forwardRefIfNeeded<
|
||||
React.ElementRef<typeof SwitchPrimitives.Root>,
|
||||
|
||||
@ -27,9 +27,7 @@ const typographyVariants = cva("text-md", {
|
||||
},
|
||||
});
|
||||
|
||||
interface TypographyProps
|
||||
extends React.HTMLAttributes<HTMLHeadingElement>,
|
||||
VariantProps<typeof typographyVariants> {}
|
||||
type TypographyProps = {} & React.HTMLAttributes<HTMLHeadingElement> & VariantProps<typeof typographyVariants>
|
||||
|
||||
const Typography = forwardRefIfNeeded<HTMLHeadingElement, TypographyProps>(
|
||||
({ className, type, variant, ...props }, ref) => {
|
||||
|
||||
@ -52,7 +52,7 @@ type Action =
|
||||
toastId?: ToasterToast["id"],
|
||||
}
|
||||
|
||||
interface State {
|
||||
type State = {
|
||||
toasts: ToasterToast[],
|
||||
}
|
||||
|
||||
|
||||
1724
pnpm-lock.yaml
1724
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user