mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
Update SDK dependencies to latest version and handle the breaking changes (#1100)
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
DB migrations are backwards-compatible with main branch / Check if migrations changed (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E API Tests with external source of truth / build (22.x) (push) Has been cancelled
Lint & build / lint_and_build (latest) (push) Has been cancelled
Dev Environment Test With Custom Base Port / restart-dev-and-test-with-custom-base-port (push) Has been cancelled
Dev Environment Test / restart-dev-and-test (push) Has been cancelled
Run setup tests with custom base port / setup-tests-with-custom-base-port (push) Has been cancelled
Run setup tests / setup-tests (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
DB migrations are backwards-compatible with main branch / Test migrations with main branch code (push) Has been cancelled
DB migrations are backwards-compatible with main branch / No migration changes (skipped) (push) Has been cancelled
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
DB migrations are backwards-compatible with main branch / Check if migrations changed (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E API Tests with external source of truth / build (22.x) (push) Has been cancelled
Lint & build / lint_and_build (latest) (push) Has been cancelled
Dev Environment Test With Custom Base Port / restart-dev-and-test-with-custom-base-port (push) Has been cancelled
Dev Environment Test / restart-dev-and-test (push) Has been cancelled
Run setup tests with custom base port / setup-tests-with-custom-base-port (push) Has been cancelled
Run setup tests / setup-tests (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
DB migrations are backwards-compatible with main branch / Test migrations with main branch code (push) Has been cancelled
DB migrations are backwards-compatible with main branch / No migration changes (skipped) (push) Has been cancelled
We update the sdk dependencies (the ones present in `package-template.json`) to the latest versions. Since several packages have major version bumps, this results in a variety of breaking changes that have been handled here. Incidentally, when possible, we update similar dependencies across the codebase. We decide to defer the tailwind update to another PR owing to its scale. The rest of the updates and changes have been catalogued below: 1. [Bumping](https://github.com/panva/oauth4webapi/blob/v3.x/CHANGELOG.md) `oauth4webapi` to 3.8.3: this was a major version changed. While there were no compatibility issues in the sdk, there were several breaking changes in `stack-shared`. Namely: a. The removal of `isOauth2Error`. We used this to check if the results of our `oauth4webapi` api invocations had issues. The functions were changed to explicitly throw either `ResponseBodyErrors` or `AuthorizationResponseErrors`, so the code was reworked to account for that with no loss in error handling. b. Dropping of support for http broadly: `oauth4webapi` now only accepts https. This is desired, but I add a carve out for our test environments only. c. `refreshTokenGrantRequest` and `authorizationCodeGrantRequest` now require `clientAuthentication` to be passed explicitly to them. d. Changes in how we handle our `MultiFactorAuthenticationRequired` error: This is an error that we created and is passed to the `oauth4webapi` API if there are MFA issues. Since the `processAuthorizationCodeResponse` now explicitly throws a `ResponseBodyError`, we access the error cause from the body of the error instead. 2. [Bumping](https://github.com/Qix-/color/releases) `color` to 5.0.4: this was a major version bump. Simple type checking change, I checked the API for the correct interface. 3. [Bumping](https://github.com/MasterKale/SimpleWebAuthn/blob/master/CHANGELOG.md) `simplewebauthn` to 13.2.2: two major version bumps, but no incompatibilities surprisingly 4. [Bumping](https://github.com/jshttp/cookie/releases) `cookie` to 1.1.1: this was a major version bump. a. Changing `parse` to `parseCookie`. In the most recent version, `parse` is still maintained as an alias for `parseCookie` for backwards compatibility, but I thought it would be best to change it over now. No change in functionality. b. Typing is now strongly enforced. A cookie can be `string | undefined`, and the `Cookies` are now `Record<string, string | undefined>`. We already have code to handle if a cookie is returned as undefined/ null, so the changes here were more to ensure type compatibility rather than big changes in functionality. 5. [Bumping ](https://github.com/isaacs/rimraf#readme)`rimraf` to 6.1.2: No breaking changes, mostly just bug fixes. 6. [Bumping](https://github.com/panva/jose/releases?page=1) `jose` to 6.1.3: This is another major version bump. We update it across the codebase to ensure compatibility. We use this for importing and processing jwk tokens. There are a few big changes in the version bump, but the only one that applies to us is that `importJwk` now yields a `CryptoKey` instead of a `KeyObject` in Node.js. However, this doesn't appear to break our code. We use `importJwk` in `stack-auth/packages/stack-shared/src/utils/jwt.tsx`. 7. [Bumping](https://github.com/react-hook-form/resolvers/releases) `hookform/resolvers` to 5.2.2 (two major version jumps), and consequently bumping `react-hook-form` to 7.70.0: We already use the patterns that `hookform/resolvers`' latest versions seem to be enforcing. The only other breaking change is that it requires version 7.55.0+ of `react-hook-form`. Though we should pay attention to any interactions with zod and `hookform/resolvers`, some people have reported compatibility issues if they aren't using the latest compatible versions of both. 8. [Bumping](https://github.com/jquense/yup/blob/master/CHANGELOG.md) `yup` to 1.7.1: this was a minor version change, but we had incompatibility issues with this change. Versions 1.4.1 and 1.7.1 cannot exist in the same codebase due to incompatibility, so we bumped it up across the codebase, including in peer dependencies. 9. Some minor version changes for some packages, but these were mostly bug fixes. 10. **Edited to add**: Bumping freestyle to 0.1.6, and reworking the freestyle mock server. In 0.1.6, freestyle changed their API in two ways: a. We're now supposed to hit their `execute/v2/...` endpoint and b. They've flattened the `config` argument to `serverless.runs.create`. These changes are minor, but are important. As part of a general suite of dependency bumps, this was judged to fit here. We have linked the changelogs for the packages on each line.
This commit is contained in:
parent
01c890db99
commit
091d3f2a26
@ -83,8 +83,8 @@
|
||||
"chokidar-cli": "^3.0.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"dotenv-cli": "^7.3.0",
|
||||
"freestyle-sandboxes": "^0.1.5",
|
||||
"jose": "^5.2.2",
|
||||
"freestyle-sandboxes": "^0.1.6",
|
||||
"jose": "^6.1.3",
|
||||
"json-diff": "^1.0.6",
|
||||
"next": "16.1.1",
|
||||
"nodemailer": "^6.9.10",
|
||||
@ -102,7 +102,7 @@
|
||||
"svix": "^1.25.0",
|
||||
"vite": "^6.1.0",
|
||||
"yaml": "^2.4.5",
|
||||
"yup": "^1.4.0",
|
||||
"yup": "^1.7.1",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -38,9 +38,7 @@ function createFreestyleEngine(): JsEngine {
|
||||
|
||||
const response = await freestyle.serverless.runs.create({
|
||||
code,
|
||||
config: {
|
||||
nodeModules: options.nodeModules ?? {},
|
||||
},
|
||||
nodeModules: options.nodeModules ?? {},
|
||||
});
|
||||
|
||||
if (response.result === undefined) {
|
||||
|
||||
@ -77,7 +77,7 @@
|
||||
"export-to-csv": "^1.4.0",
|
||||
"geist": "^1",
|
||||
"input-otp": "^1.4.1",
|
||||
"jose": "^5.2.2",
|
||||
"jose": "^6.1.3",
|
||||
"lodash": "^4.17.21",
|
||||
"next": "16.1.1",
|
||||
"next-themes": "^0.2.1",
|
||||
@ -99,7 +99,7 @@
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"three": "^0.169.0",
|
||||
"use-debounce": "^10.0.5",
|
||||
"yup": "^1.4.0"
|
||||
"yup": "^1.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/canvas-confetti": "^1.6.4",
|
||||
|
||||
@ -39,7 +39,8 @@ serve({
|
||||
port: 8080,
|
||||
async fetch(req) {
|
||||
const url = new URL(req.url);
|
||||
if (!(req.method === "POST" && url.pathname === "/execute/v1/script")) {
|
||||
const isValidEndpoint = req.method === "POST" && (url.pathname === "/execute/v1/script" || url.pathname === "/execute/v2/script");
|
||||
if (!isValidEndpoint) {
|
||||
return new Response("Not found", { status: 404 });
|
||||
}
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
"fumadocs-openapi": "^8.1.12",
|
||||
"fumadocs-typescript": "^4.0.5",
|
||||
"fumadocs-ui": "15.3.3",
|
||||
"jose": "^6.1.0",
|
||||
"jose": "^6.1.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lucide-react": "^0.511.0",
|
||||
"mermaid": "^11.6.0",
|
||||
|
||||
@ -50,20 +50,20 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@simplewebauthn/browser": "^11.0.0",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@simplewebauthn/browser": "^13.2.2",
|
||||
"@stackframe/stack-shared": "workspace:*",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"color": "^4.2.3",
|
||||
"cookie": "^0.6.0",
|
||||
"jose": "^5.2.2",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"color": "^5.0.3",
|
||||
"cookie": "^1.1.1",
|
||||
"jose": "^6.1.3",
|
||||
"js-cookie": "^3.0.5",
|
||||
"oauth4webapi": "^2.10.3",
|
||||
"oauth4webapi": "^3.8.3",
|
||||
"@oslojs/otp": "^1.1.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"rimraf": "^5.0.5",
|
||||
"tsx": "^4.7.2",
|
||||
"yup": "^1.4.0"
|
||||
"rimraf": "^6.1.2",
|
||||
"tsx": "^4.21.0",
|
||||
"yup": "^1.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@quetzallabs/i18n": "^0.1.19",
|
||||
|
||||
@ -58,28 +58,28 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@stripe/react-stripe-js": "^3.8.1",
|
||||
"@stripe/stripe-js": "^7.7.0",
|
||||
"@simplewebauthn/browser": "^11.0.0",
|
||||
"@simplewebauthn/browser": "^13.2.2",
|
||||
"@stackframe/stack-shared": "workspace:*",
|
||||
"@stackframe/stack-ui": "workspace:*",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
"color": "^4.2.3",
|
||||
"cookie": "^0.6.0",
|
||||
"jose": "^5.2.2",
|
||||
"color": "^5.0.3",
|
||||
"cookie": "^1.1.1",
|
||||
"jose": "^6.1.3",
|
||||
"js-cookie": "^3.0.5",
|
||||
"lucide-react": "^0.378.0",
|
||||
"oauth4webapi": "^2.10.3",
|
||||
"oauth4webapi": "^3.8.3",
|
||||
"@oslojs/otp": "^1.1.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"react-easy-crop": "^5.4.1",
|
||||
"react-hook-form": "^7.51.4",
|
||||
"rimraf": "^5.0.5",
|
||||
"react-easy-crop": "^5.5.6",
|
||||
"react-hook-form": "^7.70.0",
|
||||
"rimraf": "^6.1.2",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tsx": "^4.7.2",
|
||||
"yup": "^1.4.0"
|
||||
"tsx": "^4.21.0",
|
||||
"yup": "^1.7.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": ">=18.3.0",
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
"@types/react-dom": ">=19.0.0",
|
||||
"react": ">=19.0.0",
|
||||
"react-dom": ">=19.0.0",
|
||||
"yup": "^1.4.0"
|
||||
"yup": "^1.7.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
@ -64,8 +64,8 @@
|
||||
"elliptic": "^6.5.7",
|
||||
"esbuild-wasm": "^0.20.2",
|
||||
"ip-regex": "^5.0.0",
|
||||
"jose": "^5.2.2",
|
||||
"oauth4webapi": "^2.10.3",
|
||||
"jose": "^6.1.3",
|
||||
"oauth4webapi": "^3.8.3",
|
||||
"semver": "^7.6.3",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
|
||||
@ -5,6 +5,7 @@ import { KnownError, KnownErrors } from '../known-errors';
|
||||
import { inlineProductSchema } from '../schema-fields';
|
||||
import { AccessToken, InternalSession, RefreshToken } from '../sessions';
|
||||
import { generateSecureRandomString } from '../utils/crypto';
|
||||
import { getNodeEnvironment } from '../utils/env';
|
||||
import { StackAssertionError, throwErr } from '../utils/errors';
|
||||
import { globalVar } from '../utils/globals';
|
||||
import { HTTP_METHODS, HttpMethod } from '../utils/http';
|
||||
@ -153,22 +154,27 @@ export class StackClientInterface {
|
||||
throw new Error("Admin session token is currently not supported for fetching new access token. Did you try to log in on a StackApp initiated with the admin session?");
|
||||
}
|
||||
|
||||
const tokenEndpoint = this.getApiUrl() + '/auth/oauth/token';
|
||||
const as = {
|
||||
issuer: this.options.getBaseUrl(),
|
||||
algorithm: 'oauth2',
|
||||
token_endpoint: this.getApiUrl() + '/auth/oauth/token',
|
||||
token_endpoint: tokenEndpoint,
|
||||
};
|
||||
const client: oauth.Client = {
|
||||
client_id: this.projectId,
|
||||
client_secret: this.options.publishableClientKey,
|
||||
token_endpoint_auth_method: 'client_secret_post',
|
||||
};
|
||||
|
||||
const clientAuthentication = oauth.ClientSecretPost(this.options.publishableClientKey);
|
||||
const allowInsecure = getNodeEnvironment() === 'test' && tokenEndpoint.startsWith('http://');
|
||||
|
||||
const response = await this._networkRetryException(async () => {
|
||||
const rawResponse = await oauth.refreshTokenGrantRequest(
|
||||
as,
|
||||
client,
|
||||
clientAuthentication,
|
||||
refreshToken.token,
|
||||
allowInsecure ? { [oauth.allowInsecureRequests]: true } : undefined,
|
||||
);
|
||||
|
||||
const response = await this._processResponse(rawResponse);
|
||||
@ -190,10 +196,18 @@ export class StackClientInterface {
|
||||
});
|
||||
if (!response) return null;
|
||||
|
||||
const result = await oauth.processRefreshTokenResponse(as, client, response);
|
||||
if (oauth.isOAuth2Error(result)) {
|
||||
// TODO Handle OAuth 2.0 response body error
|
||||
throw new StackAssertionError("OAuth error", { result });
|
||||
let result: oauth.TokenEndpointResponse;
|
||||
try {
|
||||
result = await oauth.processRefreshTokenResponse(as, client, response);
|
||||
} catch (e){
|
||||
if (e instanceof oauth.ResponseBodyError) {
|
||||
throw new StackAssertionError("ResponseBodyError when processing refresh token response", {
|
||||
cause: e.cause,
|
||||
code: e.code,
|
||||
error: e.error,
|
||||
});
|
||||
}
|
||||
throw new StackAssertionError("Unexpected error when processing refresh token response", { cause: e });
|
||||
}
|
||||
|
||||
if (!result.access_token) {
|
||||
@ -201,6 +215,7 @@ export class StackClientInterface {
|
||||
}
|
||||
|
||||
return AccessToken.createIfValid(result.access_token) ?? throwErr("Access token in fetchNewAccessToken is invalid, looks like the backend is returning an invalid token!", { result });
|
||||
|
||||
}
|
||||
|
||||
public async sendClientRequest(
|
||||
@ -1015,37 +1030,60 @@ export class StackClientInterface {
|
||||
// TODO fix
|
||||
throw new Error("Admin session token is currently not supported for OAuth");
|
||||
}
|
||||
const tokenEndpoint = this.getApiUrl() + '/auth/oauth/token';
|
||||
const as = {
|
||||
issuer: this.options.getBaseUrl(),
|
||||
algorithm: 'oauth2',
|
||||
token_endpoint: this.getApiUrl() + '/auth/oauth/token',
|
||||
token_endpoint: tokenEndpoint,
|
||||
};
|
||||
const client: oauth.Client = {
|
||||
client_id: this.projectId,
|
||||
client_secret: this.options.publishableClientKey,
|
||||
token_endpoint_auth_method: 'client_secret_post',
|
||||
};
|
||||
const params = await this._networkRetryException(
|
||||
async () => oauth.validateAuthResponse(as, client, options.oauthParams, options.state),
|
||||
);
|
||||
if (oauth.isOAuth2Error(params)) {
|
||||
throw new StackAssertionError("Error validating outer OAuth response", { params }); // Handle OAuth 2.0 redirect error
|
||||
const clientAuthentication = oauth.ClientSecretPost(this.options.publishableClientKey);
|
||||
// Allow insecure HTTP requests only in test environment (for localhost testing)
|
||||
const allowInsecure = getNodeEnvironment() === 'test' && tokenEndpoint.startsWith('http://');
|
||||
|
||||
let params: URLSearchParams;
|
||||
try {
|
||||
params = oauth.validateAuthResponse(as, client, options.oauthParams, options.state);
|
||||
} catch (e) {
|
||||
if (e instanceof oauth.AuthorizationResponseError) {
|
||||
throw new StackAssertionError("Authorization response error when validating outer OAuth response", {
|
||||
//cause is a URLSearchParams object for this error, so we need to serialize it better
|
||||
cause: Object.fromEntries(e.cause),
|
||||
code: e.code,
|
||||
error: e.error,
|
||||
});
|
||||
}
|
||||
throw new StackAssertionError("Unexpected error when validating outer OAuth response", { cause: e });
|
||||
}
|
||||
const response = await oauth.authorizationCodeGrantRequest(
|
||||
as,
|
||||
client,
|
||||
clientAuthentication,
|
||||
params,
|
||||
options.redirectUri,
|
||||
options.codeVerifier,
|
||||
allowInsecure ? { [oauth.allowInsecureRequests]: true } : undefined,
|
||||
);
|
||||
|
||||
const result = await oauth.processAuthorizationCodeOAuth2Response(as, client, response);
|
||||
if (oauth.isOAuth2Error(result)) {
|
||||
if ("code" in result && result.code === "MULTI_FACTOR_AUTHENTICATION_REQUIRED") {
|
||||
throw new KnownErrors.MultiFactorAuthenticationRequired((result as any).details.attempt_code);
|
||||
let result;
|
||||
try {
|
||||
result = await oauth.processAuthorizationCodeResponse(as, client, response);
|
||||
} catch (e) {
|
||||
if (e instanceof oauth.ResponseBodyError) {
|
||||
if ((e.cause as any).code === "MULTI_FACTOR_AUTHENTICATION_REQUIRED") {
|
||||
throw new KnownErrors.MultiFactorAuthenticationRequired((e.cause as any).details.attempt_code);
|
||||
}
|
||||
// TODO Handle OAuth 2.0 response body error
|
||||
throw new StackAssertionError("Outer OAuth error during authorization code response", {
|
||||
cause: e.cause,
|
||||
code: e.code,
|
||||
error: e.error,
|
||||
});
|
||||
}
|
||||
// TODO Handle OAuth 2.0 response body error
|
||||
throw new StackAssertionError("Outer OAuth error during authorization code response", { result });
|
||||
throw new StackAssertionError("Unexpected error when processing authorization code response", { cause: e });
|
||||
}
|
||||
return {
|
||||
newUser: result.is_new_user as boolean,
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
"@types/react-dom": ">=19.0.0",
|
||||
"react": ">=19.0.0",
|
||||
"react-dom": ">=19.0.0",
|
||||
"yup": "^1.4.0"
|
||||
"yup": "^1.7.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
|
||||
@ -58,29 +58,29 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@stripe/react-stripe-js": "^3.8.1",
|
||||
"@stripe/stripe-js": "^7.7.0",
|
||||
"@simplewebauthn/browser": "^11.0.0",
|
||||
"@simplewebauthn/browser": "^13.2.2",
|
||||
"@stackframe/stack-sc": "workspace:*",
|
||||
"@stackframe/stack-shared": "workspace:*",
|
||||
"@stackframe/stack-ui": "workspace:*",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
"color": "^4.2.3",
|
||||
"cookie": "^0.6.0",
|
||||
"jose": "^5.2.2",
|
||||
"color": "^5.0.3",
|
||||
"cookie": "^1.1.1",
|
||||
"jose": "^6.1.3",
|
||||
"js-cookie": "^3.0.5",
|
||||
"lucide-react": "^0.378.0",
|
||||
"oauth4webapi": "^2.10.3",
|
||||
"oauth4webapi": "^3.8.3",
|
||||
"@oslojs/otp": "^1.1.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"react-easy-crop": "^5.4.1",
|
||||
"react-hook-form": "^7.51.4",
|
||||
"rimraf": "^5.0.5",
|
||||
"react-easy-crop": "^5.5.6",
|
||||
"react-hook-form": "^7.70.0",
|
||||
"rimraf": "^6.1.2",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tsx": "^4.7.2",
|
||||
"yup": "^1.4.0"
|
||||
"tsx": "^4.21.0",
|
||||
"yup": "^1.7.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": ">=18.3.0",
|
||||
|
||||
@ -86,38 +86,38 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"//": "NEXT_LINE_PLATFORM react-like",
|
||||
"@stripe/react-stripe-js": "^3.8.1",
|
||||
"//": "NEXT_LINE_PLATFORM react-like",
|
||||
"@stripe/stripe-js": "^7.7.0",
|
||||
"@simplewebauthn/browser": "^11.0.0",
|
||||
"@simplewebauthn/browser": "^13.2.2",
|
||||
"//": "NEXT_LINE_PLATFORM next",
|
||||
"@stackframe/stack-sc": "workspace:*",
|
||||
"@stackframe/stack-shared": "workspace:*",
|
||||
"//": "NEXT_LINE_PLATFORM react-like",
|
||||
"@stackframe/stack-ui": "workspace:*",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"//": "NEXT_LINE_PLATFORM react-like",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
"color": "^4.2.3",
|
||||
"cookie": "^0.6.0",
|
||||
"jose": "^5.2.2",
|
||||
"color": "^5.0.3",
|
||||
"cookie": "^1.1.1",
|
||||
"jose": "^6.1.3",
|
||||
"js-cookie": "^3.0.5",
|
||||
"//": "NEXT_LINE_PLATFORM react-like",
|
||||
"lucide-react": "^0.378.0",
|
||||
"oauth4webapi": "^2.10.3",
|
||||
"oauth4webapi": "^3.8.3",
|
||||
"@oslojs/otp": "^1.1.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"//": "NEXT_LINE_PLATFORM react-like",
|
||||
"react-easy-crop": "^5.4.1",
|
||||
"react-easy-crop": "^5.5.6",
|
||||
"//": "NEXT_LINE_PLATFORM react-like",
|
||||
"react-hook-form": "^7.51.4",
|
||||
"rimraf": "^5.0.5",
|
||||
"react-hook-form": "^7.70.0",
|
||||
"rimraf": "^6.1.2",
|
||||
"//": "NEXT_LINE_PLATFORM react-like",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tsx": "^4.7.2",
|
||||
"yup": "^1.4.0"
|
||||
"tsx": "^4.21.0",
|
||||
"yup": "^1.7.1"
|
||||
},
|
||||
"//": "IF_PLATFORM react-like",
|
||||
"peerDependencies": {
|
||||
|
||||
@ -63,29 +63,29 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@stripe/react-stripe-js": "^3.8.1",
|
||||
"@stripe/stripe-js": "^7.7.0",
|
||||
"@simplewebauthn/browser": "^11.0.0",
|
||||
"@simplewebauthn/browser": "^13.2.2",
|
||||
"@stackframe/stack-sc": "workspace:*",
|
||||
"@stackframe/stack-shared": "workspace:*",
|
||||
"@stackframe/stack-ui": "workspace:*",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
"color": "^4.2.3",
|
||||
"cookie": "^0.6.0",
|
||||
"jose": "^5.2.2",
|
||||
"color": "^5.0.3",
|
||||
"cookie": "^1.1.1",
|
||||
"jose": "^6.1.3",
|
||||
"js-cookie": "^3.0.5",
|
||||
"lucide-react": "^0.378.0",
|
||||
"oauth4webapi": "^2.10.3",
|
||||
"oauth4webapi": "^3.8.3",
|
||||
"@oslojs/otp": "^1.1.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"react-easy-crop": "^5.4.1",
|
||||
"react-hook-form": "^7.51.4",
|
||||
"rimraf": "^5.0.5",
|
||||
"react-easy-crop": "^5.5.6",
|
||||
"react-hook-form": "^7.70.0",
|
||||
"rimraf": "^6.1.2",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tsx": "^4.7.2",
|
||||
"yup": "^1.4.0"
|
||||
"tsx": "^4.21.0",
|
||||
"yup": "^1.7.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": ">=18.3.0",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { BrandIcons, Button, SimpleTooltip } from '@stackframe/stack-ui';
|
||||
import Color from 'color';
|
||||
import Color, { ColorInstance } from 'color';
|
||||
import { useEffect, useId, useState } from 'react';
|
||||
import { useStackApp } from '..';
|
||||
import { useTranslation } from '../lib/translations';
|
||||
@ -9,7 +9,7 @@ import { useInIframe } from './use-in-iframe';
|
||||
|
||||
const iconSize = 22;
|
||||
|
||||
const changeColor = (c: Color, value: number) => {
|
||||
const changeColor = (c: ColorInstance, value: number) => {
|
||||
if (c.isLight()) {
|
||||
value = -value;
|
||||
}
|
||||
|
||||
@ -467,7 +467,7 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
|
||||
private _formatAccessCookieValue(refreshToken: string | null, accessToken: string | null): string | null {
|
||||
return refreshToken && accessToken ? JSON.stringify([refreshToken, accessToken]) : null;
|
||||
}
|
||||
private _parseStructuredRefreshCookie(value: string | null): { refreshToken: string, updatedAt: number | null } | null {
|
||||
private _parseStructuredRefreshCookie(value: string | undefined): { refreshToken: string, updatedAt: number | null } | null {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
@ -489,7 +489,7 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
|
||||
};
|
||||
|
||||
}
|
||||
private _extractRefreshTokenFromCookieMap(cookies: Record<string, string>): { refreshToken: string | null, updatedAt: number | null } {
|
||||
private _extractRefreshTokenFromCookieMap(cookies: cookie.Cookies): { refreshToken: string | null, updatedAt: number | null } {
|
||||
const { legacyNames, structuredPrefixes } = this._getRefreshTokenCookieNamePatterns();
|
||||
for (const name of legacyNames) {
|
||||
const value = cookies[name];
|
||||
@ -519,7 +519,7 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
|
||||
updatedAt: selected.updatedAt ?? null,
|
||||
};
|
||||
}
|
||||
protected _getTokensFromCookies(cookies: Record<string, string>): TokenObject {
|
||||
protected _getTokensFromCookies(cookies: cookie.Cookies): TokenObject {
|
||||
const { refreshToken } = this._extractRefreshTokenFromCookieMap(cookies);
|
||||
const accessTokenCookie = cookies[this._accessTokenCookieName] ?? null;
|
||||
let accessToken: string | null = null;
|
||||
@ -553,11 +553,11 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
|
||||
// the access token on page reload.
|
||||
return `stack-access`;
|
||||
}
|
||||
private _getAllBrowserCookies(): Record<string, string> {
|
||||
private _getAllBrowserCookies(): cookie.Cookies {
|
||||
if (!isBrowserLike()) {
|
||||
throw new StackAssertionError("Cannot get browser cookies on the server!");
|
||||
}
|
||||
return cookie.parse(document.cookie || "");
|
||||
return cookie.parseCookie(document.cookie || "");
|
||||
}
|
||||
private _getRefreshTokenCookieNamePatterns(): { legacyNames: string[], structuredPrefixes: string[] } {
|
||||
return {
|
||||
@ -568,7 +568,7 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
|
||||
],
|
||||
};
|
||||
}
|
||||
private _collectRefreshTokenCookieNames(cookies: Record<string, string>): Set<string> {
|
||||
private _collectRefreshTokenCookieNames(cookies: cookie.Cookies): Set<string> {
|
||||
const { legacyNames, structuredPrefixes } = this._getRefreshTokenCookieNamePatterns();
|
||||
const names = new Set<string>();
|
||||
for (const name of legacyNames) {
|
||||
@ -584,7 +584,7 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
|
||||
return names;
|
||||
}
|
||||
private _prepareRefreshCookieUpdate(
|
||||
existingCookies: Record<string, string>,
|
||||
existingCookies: cookie.Cookies,
|
||||
refreshToken: string | null,
|
||||
accessToken: string | null,
|
||||
defaultCookieName: string,
|
||||
@ -789,7 +789,7 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
|
||||
|
||||
// read from cookies
|
||||
const cookieHeader = tokenStoreInit.headers.get("cookie");
|
||||
const parsed = cookie.parse(cookieHeader || "");
|
||||
const parsed = cookie.parseCookie(cookieHeader || "");
|
||||
const res = new Store<TokenObject>(this._getTokensFromCookies(parsed));
|
||||
this._requestTokenStores.set(tokenStoreInit, res);
|
||||
return res;
|
||||
|
||||
890
pnpm-lock.yaml
890
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user