diff --git a/.vscode/settings.json b/.vscode/settings.json index ce64a3d29..dd3deb6ff 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -30,6 +30,9 @@ "nicify", "oidc", "openapi", + "opentelemetry", + "otel", + "otlp", "pageleave", "pageview", "posthog", diff --git a/apps/backend/.env b/apps/backend/.env index 6d8a2e313..cc8644f7a 100644 --- a/apps/backend/.env +++ b/apps/backend/.env @@ -3,7 +3,7 @@ STACK_BASE_URL=# enter the URL of the backend here. For local development, use ` STACK_SERVER_SECRET=# enter a secret key generated by `pnpm generate-keys` here. This is used to sign the JWT tokens. # OAuth mock provider settings -STACK_OAUTH_MOCK_URL=# enter the URL of the mock OAuth provider here. For local development, use `http://localhost:8107`. +STACK_OAUTH_MOCK_URL=# enter the URL of the mock OAuth provider here. For local development, use `http://localhost:8114`. # OAuth shared keys # Can be set to MOCK to use mock OAuth providers diff --git a/apps/backend/.env.development b/apps/backend/.env.development index 0839b9c71..d14c2f147 100644 --- a/apps/backend/.env.development +++ b/apps/backend/.env.development @@ -1,7 +1,7 @@ STACK_BASE_URL=http://localhost:8102 STACK_SERVER_SECRET=23-wuNpik0gIW4mruTz25rbIvhuuvZFrLOLtL7J4tyo -STACK_OAUTH_MOCK_URL=http://localhost:8107 +STACK_OAUTH_MOCK_URL=http://localhost:8114 STACK_GITHUB_CLIENT_ID=MOCK STACK_GITHUB_CLIENT_SECRET=MOCK diff --git a/apps/backend/package.json b/apps/backend/package.json index 50b608c2f..6f530de91 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -27,7 +27,17 @@ "dependencies": { "@next/bundle-analyzer": "^14.0.3", "@node-oauth/oauth2-server": "^5.1.0", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.26.0", + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.53.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/resources": "^1.26.0", + "@opentelemetry/sdk-trace-base": "^1.26.0", + "@opentelemetry/sdk-trace-node": "^1.26.0", + "@opentelemetry/semantic-conventions": "^1.27.0", "@prisma/client": "^5.9.1", + "@prisma/instrumentation": "^5.19.1", "@sentry/nextjs": "^7.105.0", "@stackframe/stack-emails": "workspace:*", "@stackframe/stack-shared": "workspace:*", diff --git a/apps/backend/prisma/schema.prisma b/apps/backend/prisma/schema.prisma index c0ff76ea6..c19ad4c52 100644 --- a/apps/backend/prisma/schema.prisma +++ b/apps/backend/prisma/schema.prisma @@ -2,7 +2,8 @@ // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" + previewFeatures = ["metrics", "tracing", "relationJoins"] } datasource db { diff --git a/apps/backend/src/app/api/v1/auth/oauth/authorize/[provider_id]/route.tsx b/apps/backend/src/app/api/v1/auth/oauth/authorize/[provider_id]/route.tsx index 81c2cd3ef..51ddf774a 100644 --- a/apps/backend/src/app/api/v1/auth/oauth/authorize/[provider_id]/route.tsx +++ b/apps/backend/src/app/api/v1/auth/oauth/authorize/[provider_id]/route.tsx @@ -73,8 +73,11 @@ export const GET = createSmartRouteHandler({ // If the authorization token is present, we are adding new scopes to the user instead of sign-in/sign-up let projectUserId: string | undefined; if (query.type === "link") { - const decodedAccessToken = await decodeAccessToken(query.token); - const { userId, projectId: accessTokenProjectId } = decodedAccessToken; + const result = await decodeAccessToken(query.token); + if (result.status === "error") { + throw result.error; + } + const { userId, projectId: accessTokenProjectId } = result.data; if (accessTokenProjectId !== query.client_id) { throw new StatusError(StatusError.Forbidden, "The access token is not valid for this project"); diff --git a/apps/backend/src/app/api/v1/projects/current/crud.tsx b/apps/backend/src/app/api/v1/projects/current/crud.tsx index 29a5274fa..27072bff8 100644 --- a/apps/backend/src/app/api/v1/projects/current/crud.tsx +++ b/apps/backend/src/app/api/v1/projects/current/crud.tsx @@ -307,7 +307,7 @@ export const projectsCrudHandlers = createLazyProxy(() => createCrudHandlers(pro await tx.connectedAccountConfig.create({ data: { projectConfigId: oldProject.config.id, - enabled: enabled, + enabled, oauthProviderConfig: { connect: { projectConfigId_id: { diff --git a/apps/backend/src/app/api/v1/users/crud.tsx b/apps/backend/src/app/api/v1/users/crud.tsx index 751d72d4d..354726615 100644 --- a/apps/backend/src/app/api/v1/users/crud.tsx +++ b/apps/backend/src/app/api/v1/users/crud.tsx @@ -300,6 +300,27 @@ export const getUsersLastActiveAtMillis = async (userIds: string[], fallbackTo: }); }; +export async function getUser(options: { projectId: string, userId: string }) { + const [db, lastActiveAtMillis] = await Promise.all([ + prismaClient.projectUser.findUnique({ + where: { + projectId_projectUserId: { + projectId: options.projectId, + projectUserId: options.userId, + }, + }, + include: userFullInclude, + }), + getUserLastActiveAtMillis(options.userId, new Date()), + ]); + + if (!db) { + return null; + } + + return userPrismaToCrud(db, lastActiveAtMillis); +} + export const usersCrudHandlers = createLazyProxy(() => createCrudHandlers(usersCrud, { querySchema: yupObject({ team_id: yupString().uuid().optional().meta({ openapiField: { onlyShowInOperations: [ 'List' ] }}) @@ -308,21 +329,11 @@ export const usersCrudHandlers = createLazyProxy(() => createCrudHandlers(usersC user_id: userIdOrMeSchema.required(), }), onRead: async ({ auth, params }) => { - const db = await prismaClient.projectUser.findUnique({ - where: { - projectId_projectUserId: { - projectId: auth.project.id, - projectUserId: params.user_id, - }, - }, - include: userFullInclude, - }); - - if (!db) { + const user = await getUser({ projectId: auth.project.id, userId: params.user_id }); + if (!user) { throw new KnownErrors.UserNotFound(); } - - return userPrismaToCrud(db, await getUserLastActiveAtMillis(params.user_id, db.createdAt)); + return user; }, onList: async ({ auth, query }) => { const db = await prismaClient.projectUser.findMany({ @@ -891,11 +902,10 @@ export const usersCrudHandlers = createLazyProxy(() => createCrudHandlers(usersC export const currentUserCrudHandlers = createLazyProxy(() => createCrudHandlers(currentUserCrud, { paramsSchema: yupObject({} as const), async onRead({ auth }) { - return await usersCrudHandlers.adminRead({ - project: auth.project, - user_id: auth.user?.id ?? throwErr(new KnownErrors.CannotGetOwnUserWithoutUser()), - allowedErrorTypes: [StatusError] - }); + if (!auth.user) { + throw new KnownErrors.CannotGetOwnUserWithoutUser(); + } + return auth.user; }, async onUpdate({ auth, data }) { if (auth.type === 'client' && data.profile_image_url && !validateBase64Image(data.profile_image_url)) { diff --git a/apps/backend/src/lib/projects.tsx b/apps/backend/src/lib/projects.tsx index c07f47dc6..c51aaab61 100644 --- a/apps/backend/src/lib/projects.tsx +++ b/apps/backend/src/lib/projects.tsx @@ -1,11 +1,9 @@ -import { usersCrudHandlers } from "@/app/api/v1/users/crud"; import { prismaClient } from "@/prisma-client"; -import { CrudHandlerInvocationError } from "@/route-handlers/crud-handler"; import { Prisma } from "@prisma/client"; import { KnownErrors } from "@stackframe/stack-shared"; import { ProjectsCrud } from "@stackframe/stack-shared/dist/interface/crud/projects"; import { UsersCrud } from "@stackframe/stack-shared/dist/interface/crud/users"; -import { StackAssertionError, throwErr } from "@stackframe/stack-shared/dist/utils/errors"; +import { StackAssertionError, captureError } from "@stackframe/stack-shared/dist/utils/errors"; import { typedToLowercase } from "@stackframe/stack-shared/dist/utils/strings"; import { fullPermissionInclude, teamPermissionDefinitionJsonFromDbType, teamPermissionDefinitionJsonFromTeamSystemDbType } from "./permissions"; import { decodeAccessToken } from "./tokens"; @@ -173,58 +171,6 @@ export function projectPrismaToCrud( }; } -export async function whyNotProjectAdmin(projectId: string, adminAccessToken: string): Promise<"unparsable-access-token" | "access-token-expired" | "wrong-token-project-id" | "not-admin" | null> { - if (!adminAccessToken) { - return "unparsable-access-token"; - } - - let decoded; - try { - decoded = await decodeAccessToken(adminAccessToken); - } catch (error) { - if (error instanceof KnownErrors.AccessTokenExpired) { - return "access-token-expired"; - } - console.warn("Failed to decode a user-provided admin access token. This may not be an error (for example, it could happen if the client changed Stack app hosts), but could indicate one.", error); - return "unparsable-access-token"; - } - const { userId, projectId: accessTokenProjectId } = decoded; - if (accessTokenProjectId !== "internal") { - return "wrong-token-project-id"; - } - - let user; - try { - user = await usersCrudHandlers.adminRead({ - project: await getProject("internal") ?? throwErr("Can't find internal project??"), - user_id: userId, - }); - } catch (e) { - if (e instanceof CrudHandlerInvocationError && e.cause instanceof KnownErrors.UserNotFound) { - // this may happen eg. if the user has a valid access token but has since been deleted - return "not-admin"; - } - throw e; - } - - const allProjects = listManagedProjectIds(user); - if (!allProjects.includes(projectId)) { - return "not-admin"; - } - - const project = await getProject(projectId); - if (!project) { - // this happens if the project is still in the user's managedProjectIds, but has since been deleted - return "not-admin"; - } - - return null; -} - -export async function isProjectAdmin(projectId: string, adminAccessToken: string) { - return !await whyNotProjectAdmin(projectId, adminAccessToken); -} - function isStringArray(value: any): value is string[] { return Array.isArray(value) && value.every((id) => typeof id === "string"); } diff --git a/apps/backend/src/lib/tokens.tsx b/apps/backend/src/lib/tokens.tsx index 55f1634cc..0552ecc8a 100644 --- a/apps/backend/src/lib/tokens.tsx +++ b/apps/backend/src/lib/tokens.tsx @@ -6,6 +6,7 @@ import { getEnvVariable } from '@stackframe/stack-shared/dist/utils/env'; import { decryptJWE, encryptJWE, signJWT, verifyJWT } from '@stackframe/stack-shared/dist/utils/jwt'; import { JOSEError, JWTExpired } from 'jose/errors'; import { SystemEventTypes, logEvent } from './events'; +import { Result } from '@stackframe/stack-shared/dist/utils/results'; export const authorizationHeaderSchema = yupString().matches(/^StackSession [^ ]+$/); @@ -41,19 +42,21 @@ export async function decodeAccessToken(accessToken: string) { payload = await verifyJWT(jwtIssuer, accessToken); } catch (error) { if (error instanceof JWTExpired) { - throw new KnownErrors.AccessTokenExpired(); + return Result.error(new KnownErrors.AccessTokenExpired()); } else if (error instanceof JOSEError) { - throw new KnownErrors.UnparsableAccessToken(); + return Result.error(new KnownErrors.UnparsableAccessToken()); } throw error; } - return await accessTokenSchema.validate({ + const result = await accessTokenSchema.validate({ projectId: payload.projectId, userId: payload.sub, refreshTokenId: payload.refreshTokenId, exp: payload.exp, }); + + return Result.ok(result); } export async function generateAccessToken({ diff --git a/apps/backend/src/oauth/model.tsx b/apps/backend/src/oauth/model.tsx index ce88079e7..f0be797b7 100644 --- a/apps/backend/src/oauth/model.tsx +++ b/apps/backend/src/oauth/model.tsx @@ -145,13 +145,12 @@ export class OAuthModel implements AuthorizationCodeModel { } async getAccessToken(accessToken: string): Promise { - let decoded; - try { - decoded = await decodeAccessToken(accessToken); - } catch (e) { - captureError("getAccessToken", e); + const result = await decodeAccessToken(accessToken); + if (result.status === "error") { + captureError("unexpected error in getAccessToken", result.error); return false; } + const decoded = result.data; return { accessToken, diff --git a/apps/backend/src/otel.ts b/apps/backend/src/otel.ts new file mode 100644 index 000000000..0d3e7a5ab --- /dev/null +++ b/apps/backend/src/otel.ts @@ -0,0 +1,38 @@ +import * as api from "@opentelemetry/api"; +import { AsyncHooksContextManager } from "@opentelemetry/context-async-hooks"; +import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"; +import { registerInstrumentations } from "@opentelemetry/instrumentation"; +import { Resource } from "@opentelemetry/resources"; +import { BasicTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base"; +import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions"; +import { PrismaInstrumentation } from "@prisma/instrumentation"; +import { getEnvVariable } from "@stackframe/stack-shared/dist/utils/env"; + +export function otelSetup() { + // by default, otel is only enabled in development mode + if (!(getEnvVariable("OTEL_ENABLED", "") || getEnvVariable("NODE_ENV", "") === "development")) { + return; + } + + const contextManager = new AsyncHooksContextManager().enable(); + api.context.setGlobalContextManager(contextManager); + + const otlpTraceExporter = new OTLPTraceExporter(); + + const provider = new BasicTracerProvider({ + // Enable sampling in production for better performance + // sampler: new TraceIdRatioBasedSampler(0.1), + resource: new Resource({ + [SemanticResourceAttributes.SERVICE_NAME]: "stack-auth-backend", + [SemanticResourceAttributes.SERVICE_VERSION]: "1.0.0", + }), + }); + + provider.addSpanProcessor(new SimpleSpanProcessor(otlpTraceExporter)); + + provider.register(); + + registerInstrumentations({ + instrumentations: [new PrismaInstrumentation()], + }); +} \ No newline at end of file diff --git a/apps/backend/src/prisma-client.tsx b/apps/backend/src/prisma-client.tsx index b8729e4a0..8e99eaf7f 100644 --- a/apps/backend/src/prisma-client.tsx +++ b/apps/backend/src/prisma-client.tsx @@ -1,6 +1,8 @@ - import { PrismaClient } from '@prisma/client'; import { getNodeEnvironment } from '@stackframe/stack-shared/dist/utils/env'; +import { otelSetup } from './otel'; + +otelSetup(); // In dev mode, fast refresh causes us to recreate many Prisma clients, eventually overloading the database. // Therefore, only create one Prisma client in dev mode. diff --git a/apps/backend/src/route-handlers/smart-request.tsx b/apps/backend/src/route-handlers/smart-request.tsx index 48bebde67..f03a27762 100644 --- a/apps/backend/src/route-handlers/smart-request.tsx +++ b/apps/backend/src/route-handlers/smart-request.tsx @@ -1,20 +1,19 @@ import "../polyfills"; -import { NextRequest } from "next/server"; -import { StackAssertionError, StatusError, throwErr } from "@stackframe/stack-shared/dist/utils/errors"; -import * as yup from "yup"; -import { deepPlainClone } from "@stackframe/stack-shared/dist/utils/objects"; -import { groupBy, typedIncludes } from "@stackframe/stack-shared/dist/utils/arrays"; -import { KnownErrors } from "@stackframe/stack-shared"; +import { getUser } from "@/app/api/v1/users/crud"; import { checkApiKeySet } from "@/lib/api-keys"; -import { getProject, whyNotProjectAdmin } from "@/lib/projects"; +import { getProject, listManagedProjectIds } from "@/lib/projects"; import { decodeAccessToken } from "@/lib/tokens"; -import { deindent } from "@stackframe/stack-shared/dist/utils/strings"; -import { ReplaceFieldWithOwnUserId, StackAdaptSentinel, yupObject } from "@stackframe/stack-shared/dist/schema-fields"; -import { UsersCrud } from "@stackframe/stack-shared/dist/interface/crud/users"; -import { usersCrudHandlers } from "@/app/api/v1/users/crud"; +import { KnownErrors } from "@stackframe/stack-shared"; import { ProjectsCrud } from "@stackframe/stack-shared/dist/interface/crud/projects"; -import { CrudHandlerInvocationError } from "./crud-handler"; +import { UsersCrud } from "@stackframe/stack-shared/dist/interface/crud/users"; +import { ReplaceFieldWithOwnUserId, StackAdaptSentinel } from "@stackframe/stack-shared/dist/schema-fields"; +import { groupBy, typedIncludes } from "@stackframe/stack-shared/dist/utils/arrays"; +import { StackAssertionError, StatusError, throwErr } from "@stackframe/stack-shared/dist/utils/errors"; +import { deepPlainClone } from "@stackframe/stack-shared/dist/utils/objects"; +import { deindent } from "@stackframe/stack-shared/dist/utils/strings"; +import { NextRequest } from "next/server"; +import * as yup from "yup"; const allowedMethods = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"] as const; @@ -170,6 +169,63 @@ async function parseAuth(req: NextRequest): Promise { const accessToken = req.headers.get("x-stack-access-token"); const refreshToken = req.headers.get("x-stack-refresh-token"); + const extractUserFromAccessToken = async (options: { token: string, projectId: string }) => { + const result = await decodeAccessToken(options.token); + if (result.status === "error") { + throw result.error; + } + + if (result.data.projectId !== options.projectId) { + throw new KnownErrors.InvalidProjectForAccessToken(); + } + + const user = await getUser({ projectId: options.projectId, userId: result.data.userId }); + if (!user) { + // this is the case when access token is still valid, but the user is deleted from the database + throw new KnownErrors.AccessTokenExpired(); + } + + return user; + }; + + const extractUserFromAdminAccessToken = async (options: { token: string, projectId: string }) => { + const result = await decodeAccessToken(options.token); + if (result.status === "error") { + if (result.error instanceof KnownErrors.AccessTokenExpired) { + throw new KnownErrors.AdminAccessTokenExpired(); + } else { + throw new KnownErrors.UnparsableAdminAccessToken(); + } + } + + if (result.data.projectId !== "internal") { + throw new KnownErrors.AdminAccessTokenIsNotAdmin(); + } + + const user = await getUser({ projectId: 'internal', userId: result.data.userId }); + if (!user) { + // this is the case when access token is still valid, but the user is deleted from the database + throw new KnownErrors.AdminAccessTokenExpired(); + } + + const allProjects = listManagedProjectIds(user); + if (!allProjects.includes(options.projectId)) { + throw new KnownErrors.AdminAccessTokenIsNotAdmin(); + } + + return user; + }; + + // Do all the requests in parallel + const queries = { + project: projectId ? getProject(projectId) : Promise.resolve(null), + isClientKeyValid: projectId && publishableClientKey ? checkApiKeySet(projectId, { publishableClientKey }) : Promise.resolve(false), + isServerKeyValid: projectId && secretServerKey ? checkApiKeySet(projectId, { secretServerKey }) : Promise.resolve(false), + isAdminKeyValid: projectId && superSecretAdminKey ? checkApiKeySet(projectId, { superSecretAdminKey }) : Promise.resolve(false), + user: projectId && accessToken ? extractUserFromAccessToken({ token: accessToken, projectId }) : Promise.resolve(null), + internalUser: projectId && adminAccessToken ? extractUserFromAdminAccessToken({ token: adminAccessToken, projectId }) : Promise.resolve(null), + }; + const eitherKeyOrToken = !!(publishableClientKey || secretServerKey || superSecretAdminKey || adminAccessToken); if (!requestType && eitherKeyOrToken) { @@ -179,51 +235,31 @@ async function parseAuth(req: NextRequest): Promise { if (!typedIncludes(["client", "server", "admin"] as const, requestType)) throw new KnownErrors.InvalidAccessType(requestType); if (!projectId) throw new KnownErrors.AccessTypeWithoutProjectId(requestType); - let projectAccessType: "key" | "internal-user-token"; if (adminAccessToken) { - const reason = await whyNotProjectAdmin(projectId, adminAccessToken); - switch (reason) { - case null: { - projectAccessType = "internal-user-token"; - break; - } - case "unparsable-access-token": { - throw new KnownErrors.UnparsableAdminAccessToken(); - } - case "not-admin": { - throw new KnownErrors.AdminAccessTokenIsNotAdmin(); - } - case "wrong-token-project-id": { + if (await queries.internalUser) { + if (!await queries.project) { + // this happens if the project is still in the user's managedProjectIds, but has since been deleted throw new KnownErrors.InvalidProjectForAdminAccessToken(); } - case "access-token-expired": { - throw new KnownErrors.AdminAccessTokenExpired(); - } - default: { - throw new StackAssertionError(`Unexpected reason for lack of project admin: ${reason}`); - } + } else { + // This case should be prevented by checks inside extractUserFromAdminAccessToken, if this happens, something is wrong + throw new StackAssertionError("adminAccessToken exists but no internal user was found"); } } else { switch (requestType) { case "client": { if (!publishableClientKey) throw new KnownErrors.ClientAuthenticationRequired(); - const isValid = await checkApiKeySet(projectId, { publishableClientKey }); - if (!isValid) throw new KnownErrors.InvalidPublishableClientKey(projectId); - projectAccessType = "key"; + if (!await queries.isClientKeyValid) throw new KnownErrors.InvalidPublishableClientKey(projectId); break; } case "server": { if (!secretServerKey) throw new KnownErrors.ServerAuthenticationRequired(); - const isValid = await checkApiKeySet(projectId, { secretServerKey }); - if (!isValid) throw new KnownErrors.InvalidSecretServerKey(projectId); - projectAccessType = "key"; + if (!await queries.isServerKeyValid) throw new KnownErrors.InvalidSecretServerKey(projectId); break; } case "admin": { if (!superSecretAdminKey) throw new KnownErrors.AdminAuthenticationRequired(); - const isValid = await checkApiKeySet(projectId, { superSecretAdminKey }); - if (!isValid) throw new KnownErrors.InvalidSuperSecretAdminKey(projectId); - projectAccessType = "key"; + if (!await queries.isAdminKeyValid) throw new KnownErrors.InvalidSuperSecretAdminKey(projectId); break; } default: { @@ -232,35 +268,14 @@ async function parseAuth(req: NextRequest): Promise { } } - const project = await getProject(projectId); + const project = await queries.project; if (!project) { throw new StackAssertionError("Project not found; this should never happen because passing the checks until here should guarantee that the project exists and that access to it is granted", { projectId }); } - let user = null; - if (accessToken) { - const decodedAccessToken = await decodeAccessToken(accessToken); - const { userId, projectId: accessTokenProjectId } = decodedAccessToken; - - if (accessTokenProjectId !== projectId) { - throw new KnownErrors.InvalidProjectForAccessToken(); - } - - try { - user = await usersCrudHandlers.adminRead({ - project, - user_id: userId, - }); - } catch (e) { - if (e instanceof CrudHandlerInvocationError && e.cause instanceof KnownErrors.UserNotFound) { - user = null; - } - } - } - return { project, - user: user ?? undefined, + user: await queries.user ?? undefined, type: requestType, }; } diff --git a/apps/e2e/tests/backend/backend-helpers.ts b/apps/e2e/tests/backend/backend-helpers.ts index 79736853b..e9d06b86f 100644 --- a/apps/e2e/tests/backend/backend-helpers.ts +++ b/apps/e2e/tests/backend/backend-helpers.ts @@ -414,7 +414,7 @@ export namespace Auth { }, }); expect(response.status).toBe(307); - expect(response.headers.get("location")).toMatch(/^http:\/\/localhost:8107\/auth\?.*$/); + expect(response.headers.get("location")).toMatch(/^http:\/\/localhost:8114\/auth\?.*$/); expect(response.headers.get("set-cookie")).toMatch(/^stack-oauth-inner-[^;]+=[^;]+; Path=\/; Expires=[^;]+; Max-Age=\d+;( Secure;)? HttpOnly$/); return { authorizeResponse: response, diff --git a/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/authorize.test.ts b/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/authorize.test.ts index 9dafc2c5b..ef9773905 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/authorize.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/authorize.test.ts @@ -4,7 +4,7 @@ import { Auth, niceBackendFetch } from "../../../../../backend-helpers"; it("should redirect the user to the OAuth provider with the right arguments", async ({ expect }) => { const response = await Auth.OAuth.authorize(); expect(response.authorizeResponse.status).toBe(307); - expect(response.authorizeResponse.headers.get("location")).toMatch(/^http:\/\/localhost:8107\/auth\?.*$/); + expect(response.authorizeResponse.headers.get("location")).toMatch(/^http:\/\/localhost:8114\/auth\?.*$/); expect(response.authorizeResponse.headers.get("set-cookie")).toMatch(/^stack-oauth-inner-[^;]+=[^;]+; Path=\/; Expires=[^;]+; Max-Age=\d+;( Secure;)? HttpOnly$/); }); diff --git a/apps/oauth-mock-server/src/index.ts b/apps/oauth-mock-server/src/index.ts index 34857ada5..5510654d8 100644 --- a/apps/oauth-mock-server/src/index.ts +++ b/apps/oauth-mock-server/src/index.ts @@ -1,6 +1,6 @@ import Provider, { Configuration } from 'oidc-provider'; -const port = Number.parseInt(process.env.PORT || "8107"); +const port = Number.parseInt(process.env.PORT || "8114"); const mockedProviders = [ "github", diff --git a/dependencies.compose.yaml b/dependencies.compose.yaml index 430ce0430..77d720352 100644 --- a/dependencies.compose.yaml +++ b/dependencies.compose.yaml @@ -7,10 +7,19 @@ services: POSTGRES_USER: postgres POSTGRES_PASSWORD: password POSTGRES_DB: stackframe + POSTGRES_DELAY: ${POSTGRES_DELAY:-0} ports: - 5432:5432 volumes: - postgres-data:/var/lib/postgresql/data + entrypoint: ["sh", "-c", " + if [ $POSTGRES_DELAY -gt 0 ]; then + apt-get update && apt-get install -y iproute2 && \ + tc qdisc add dev eth0 root netem delay ${POSTGRES_DELAY}ms; + fi; + exec docker-entrypoint.sh postgres"] + cap_add: + - NET_ADMIN inbucket: image: inbucket/inbucket:latest @@ -21,6 +30,15 @@ services: volumes: - inbucket-data:/data + jaeger: + image: jaegertracing/all-in-one:latest + environment: + - COLLECTOR_OTLP_ENABLED=true + ports: + - 8107:16686 # Jaeger UI + - 4318:4318 # OTLP Endpoint + restart: always + # ================= svix ================= svix-db: diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 07f448d9c..c275a9c97 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -86,12 +86,42 @@ importers: '@node-oauth/oauth2-server': specifier: ^5.1.0 version: 5.1.0 + '@opentelemetry/api': + specifier: ^1.9.0 + version: 1.9.0 + '@opentelemetry/context-async-hooks': + specifier: ^1.26.0 + version: 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': + specifier: ^1.26.0 + version: 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-http': + specifier: ^0.53.0 + version: 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': + specifier: ^0.53.0 + version: 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': + specifier: ^1.26.0 + version: 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': + specifier: ^1.26.0 + version: 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-node': + specifier: ^1.26.0 + version: 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': + specifier: ^1.27.0 + version: 1.27.0 '@prisma/client': specifier: ^5.9.1 version: 5.15.0(prisma@5.15.0) + '@prisma/instrumentation': + specifier: ^5.19.1 + version: 5.19.1 '@sentry/nextjs': specifier: ^7.105.0 - version: 7.117.0(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.92.0(@swc/core@1.3.101)(esbuild@0.21.5)) + version: 7.117.0(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.92.0(@swc/core@1.3.101)(esbuild@0.21.5)) '@stackframe/stack-emails': specifier: workspace:* version: link:../../packages/stack-emails @@ -100,7 +130,7 @@ importers: version: link:../../packages/stack-shared '@vercel/analytics': specifier: ^1.2.2 - version: 1.3.1(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 1.3.1(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) bcrypt: specifier: ^5.1.1 version: 5.1.1 @@ -112,7 +142,7 @@ importers: version: 5.4.0 next: specifier: ^14.1 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nodemailer: specifier: ^6.9.10 version: 6.9.13 @@ -194,7 +224,7 @@ importers: version: 1.3.0(react@18.3.1) '@sentry/nextjs': specifier: ^7.105.0 - version: 7.117.0(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.92.0(@swc/core@1.3.101)(esbuild@0.21.5)) + version: 7.117.0(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.92.0(@swc/core@1.3.101)(esbuild@0.21.5)) '@stackframe/stack': specifier: workspace:* version: link:../../packages/stack @@ -212,10 +242,10 @@ importers: version: 8.17.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@vercel/analytics': specifier: ^1.2.2 - version: 1.3.1(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 1.3.1(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) '@vercel/speed-insights': specifier: ^1.0.12 - version: 1.0.12(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 1.0.12(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) bcrypt: specifier: ^5.1.1 version: 5.1.1 @@ -233,7 +263,7 @@ importers: version: 1.3.0 geist: specifier: ^1 - version: 1.3.0(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + version: 1.3.0(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) jose: specifier: ^5.2.2 version: 5.4.0 @@ -242,10 +272,10 @@ importers: version: 0.378.0(react@18.3.1) next: specifier: ^14.1 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.2.1(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nodemailer: specifier: ^6.9.10 version: 6.9.13 @@ -383,7 +413,7 @@ importers: version: link:../../packages/stack next: specifier: 14.2.3 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18 version: 18.3.1 @@ -435,10 +465,10 @@ importers: version: link:../../packages/stack-ui next: specifier: ^14.1 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.2.1(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.2 version: 18.3.1 @@ -487,10 +517,10 @@ importers: version: link:../../packages/stack-ui next: specifier: ^14.1 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.2.1(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.2 version: 18.3.1 @@ -527,7 +557,7 @@ importers: version: link:../../packages/stack next: specifier: 14.2.5 - version: 14.2.5(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.5(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18 version: 18.3.1 @@ -564,7 +594,7 @@ importers: version: link:../../packages/stack next: specifier: ^14.2 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18 version: 18.3.1 @@ -598,7 +628,7 @@ importers: version: link:../../packages/stack next: specifier: 14.3.0-canary.26 - version: 14.3.0-canary.26(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.3.0-canary.26(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18 version: 18.3.1 @@ -641,7 +671,7 @@ importers: version: 5.6.3 next: specifier: latest - version: 14.2.7(@babel/core@7.24.7)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.7(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -769,7 +799,7 @@ importers: version: 0.20.2 next: specifier: ^14.1.0 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) postcss: specifier: ^8.4.38 version: 8.4.38 @@ -817,7 +847,7 @@ importers: version: 5.6.1(react-dom@18.2.0(react@18.2.0))(react@18.3.1) react-email: specifier: 2.1.0 - version: 2.1.0(@babel/core@7.24.7)(@swc/helpers@0.5.11)(eslint@8.30.0) + version: 2.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@swc/helpers@0.5.11)(eslint@8.30.0) tailwind-merge: specifier: ^2.3.0 version: 2.3.0 @@ -839,7 +869,7 @@ importers: version: 18.3.3 next: specifier: ^14.1.0 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.2.0(react@18.2.0))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.3.1) react: specifier: ^18.2.0 version: 18.3.1 @@ -854,7 +884,7 @@ importers: version: 18.3.3 next: specifier: ^14.1.0 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.2.0 version: 18.3.1 @@ -900,7 +930,7 @@ importers: version: 9.0.8 next: specifier: ^14.1.0 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.2.0 version: 18.3.1 @@ -1042,7 +1072,7 @@ importers: version: 18.3.3 next: specifier: ^14.1.0 - version: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.2.0 version: 18.3.1 @@ -2520,6 +2550,106 @@ packages: '@one-ini/wasm@0.1.1': resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + '@opentelemetry/api-logs@0.52.1': + resolution: {integrity: sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==} + engines: {node: '>=14'} + + '@opentelemetry/api-logs@0.53.0': + resolution: {integrity: sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==} + engines: {node: '>=14'} + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/context-async-hooks@1.26.0': + resolution: {integrity: sha512-HedpXXYzzbaoutw6DFLWLDket2FwLkLpil4hGCZ1xYEIMTcivdfwEOISgdbLEWyG3HW52gTq2V9mOVJrONgiwg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@1.26.0': + resolution: {integrity: sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/exporter-trace-otlp-http@0.53.0': + resolution: {integrity: sha512-m7F5ZTq+V9mKGWYpX8EnZ7NjoqAU7VemQ1E2HAG+W/u0wpY1x0OmbxAXfGKFHCspdJk8UKlwPGrpcB8nay3P8A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/instrumentation@0.52.1': + resolution: {integrity: sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation@0.53.0': + resolution: {integrity: sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-exporter-base@0.53.0': + resolution: {integrity: sha512-UCWPreGQEhD6FjBaeDuXhiMf6kkBODF0ZQzrk/tuQcaVDJ+dDQ/xhJp192H9yWnKxVpEjFrSSLnpqmX4VwX+eA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/otlp-transformer@0.53.0': + resolution: {integrity: sha512-rM0sDA9HD8dluwuBxLetUmoqGJKSAbWenwD65KY9iZhUxdBHRLrIdrABfNDP7aiTjcgK8XFyTn5fhDz7N+W6DA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/propagator-b3@1.26.0': + resolution: {integrity: sha512-vvVkQLQ/lGGyEy9GT8uFnI047pajSOVnZI2poJqVGD3nJ+B9sFGdlHNnQKophE3lHfnIH0pw2ubrCTjZCgIj+Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/propagator-jaeger@1.26.0': + resolution: {integrity: sha512-DelFGkCdaxA1C/QA0Xilszfr0t4YbGd3DjxiCDPh34lfnFr+VkkrjV9S8ZTJvAzfdKERXhfOxIKBoGPJwoSz7Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/resources@1.26.0': + resolution: {integrity: sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-logs@0.53.0': + resolution: {integrity: sha512-dhSisnEgIj/vJZXZV6f6KcTnyLDx/VuQ6l3ejuZpMpPlh9S1qMHiZU9NMmOkVkwwHkMy3G6mEBwdP23vUZVr4g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.10.0' + + '@opentelemetry/sdk-metrics@1.26.0': + resolution: {integrity: sha512-0SvDXmou/JjzSDOjUmetAAvcKQW6ZrvosU0rkbDGpXvvZN+pQF6JbK/Kd4hNdK4q/22yeruqvukXEJyySTzyTQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-trace-base@1.26.0': + resolution: {integrity: sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-trace-node@1.26.0': + resolution: {integrity: sha512-Fj5IVKrj0yeUwlewCRwzOVcr5avTuNnMHWf7GPc1t6WaT78J6CJyF3saZ/0RkZfdeNO8IcBl/bNcWMVZBMRW8Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/semantic-conventions@1.27.0': + resolution: {integrity: sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==} + engines: {node: '>=14'} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -2551,6 +2681,39 @@ packages: '@prisma/get-platform@5.15.0': resolution: {integrity: sha512-1GULDkW4+/VQb73vihxCBSc4Chc2x88MA+O40tcZFjmBzG4/fF44PaXFxUqKSFltxU9L9GIMLhh0Gfkk/pUbtg==} + '@prisma/instrumentation@5.19.1': + resolution: {integrity: sha512-VLnzMQq7CWroL5AeaW0Py2huiNKeoMfCH3SUxstdzPrlWQi6UQ9UrfcbUkNHlVFqOMacqy8X/8YtE0kuKDpD9w==} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@radix-ui/colors@1.0.1': resolution: {integrity: sha512-xySw8f0ZVsAEP+e7iLl3EvcBXX7gsIlC1Zso/sPBW9gIWerBTgz6axrjU+MZ39wD+WFi5h5zdWpsg3+hwt2Qsg==} @@ -3922,6 +4085,9 @@ packages: '@types/serve-static@1.15.7': resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + '@types/shimmer@1.2.0': + resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} + '@types/superagent@8.1.7': resolution: {integrity: sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==} @@ -4571,6 +4737,9 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} + cjs-module-lexer@1.4.0: + resolution: {integrity: sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g==} + class-variance-authority@0.7.0: resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} @@ -5848,6 +6017,9 @@ packages: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} + import-in-the-middle@1.11.0: + resolution: {integrity: sha512-5DimNQGoe0pLUHbR9qK84iWaWjjbsxiqXnw6Qz64+azRgleqv9k2kTt5fw7QsOpmaGYtuxxursnPPsnTKEx10Q==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -6311,6 +6483,9 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -6678,6 +6853,9 @@ packages: mlly@1.7.1: resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} + module-details-from-path@1.0.3: + resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} + mrmime@2.0.0: resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} engines: {node: '>=10'} @@ -7291,6 +7469,10 @@ packages: proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + protobufjs@7.4.0: + resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} + engines: {node: '>=12.0.0'} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -7524,6 +7706,10 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-in-the-middle@7.4.0: + resolution: {integrity: sha512-X34iHADNbNDfr6OTStIAHWSAvvKQRYgLO6duASaVf7J2VA3lvmNYboAHOuLC2huav1IwgZJtyEcJCKVzFxOSMQ==} + engines: {node: '>=8.6.0'} + require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} @@ -7703,6 +7889,9 @@ packages: engines: {node: '>=4'} hasBin: true + shimmer@1.2.1: + resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} + side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} @@ -10093,6 +10282,123 @@ snapshots: '@one-ini/wasm@0.1.1': {} + '@opentelemetry/api-logs@0.52.1': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/api-logs@0.53.0': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/api@1.9.0': {} + + '@opentelemetry/context-async-hooks@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/exporter-trace-otlp-http@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.11.0 + require-in-the-middle: 7.4.0 + semver: 7.6.2 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.11.0 + require-in-the-middle: 7.4.0 + semver: 7.6.2 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/otlp-exporter-base@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/otlp-transformer@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + protobufjs: 7.4.0 + + '@opentelemetry/propagator-b3@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/propagator-jaeger@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/resources@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/sdk-logs@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/sdk-metrics@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/sdk-trace-node@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-b3': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-jaeger': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + semver: 7.6.2 + + '@opentelemetry/semantic-conventions@1.27.0': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -10123,6 +10429,37 @@ snapshots: dependencies: '@prisma/debug': 5.15.0 + '@prisma/instrumentation@5.19.1': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + '@radix-ui/colors@1.0.1': {} '@radix-ui/number@1.0.1': @@ -11215,7 +11552,7 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@react-email/components@0.0.15(@types/react@18.3.3)(react-email@2.1.0(@babel/core@7.24.7)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0)': + '@react-email/components@0.0.15(@types/react@18.3.3)(react-email@2.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0)': dependencies: '@react-email/body': 0.0.7(react@18.2.0) '@react-email/button': 0.0.14(react@18.2.0) @@ -11230,7 +11567,7 @@ snapshots: '@react-email/html': 0.0.7(react@18.2.0) '@react-email/img': 0.0.7(react@18.2.0) '@react-email/link': 0.0.7(react@18.2.0) - '@react-email/markdown': 0.0.8(react-email@2.1.0(@babel/core@7.24.7)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0) + '@react-email/markdown': 0.0.8(react-email@2.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0) '@react-email/preview': 0.0.8(react@18.2.0) '@react-email/render': 0.0.12 '@react-email/row': 0.0.7(react@18.2.0) @@ -11312,9 +11649,9 @@ snapshots: dependencies: react: 18.3.1 - '@react-email/markdown@0.0.8(react-email@2.1.0(@babel/core@7.24.7)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0)': + '@react-email/markdown@0.0.8(react-email@2.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0)': dependencies: - md-to-react-email: 4.1.0(react-email@2.1.0(@babel/core@7.24.7)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0) + md-to-react-email: 4.1.0(react-email@2.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0) react: 18.2.0 transitivePeerDependencies: - react-email @@ -11494,7 +11831,7 @@ snapshots: '@sentry/utils': 7.117.0 localforage: 1.10.0 - '@sentry/nextjs@7.117.0(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.92.0(@swc/core@1.3.101)(esbuild@0.21.5))': + '@sentry/nextjs@7.117.0(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(webpack@5.92.0(@swc/core@1.3.101)(esbuild@0.21.5))': dependencies: '@rollup/plugin-commonjs': 24.0.0(rollup@2.78.0) '@sentry/core': 7.117.0 @@ -11506,7 +11843,7 @@ snapshots: '@sentry/vercel-edge': 7.117.0 '@sentry/webpack-plugin': 1.21.0 chalk: 3.0.0 - next: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 resolve: 1.22.8 rollup: 2.78.0 @@ -11965,6 +12302,8 @@ snapshots: '@types/node': 20.10.6 '@types/send': 0.17.4 + '@types/shimmer@1.2.0': {} + '@types/superagent@8.1.7': dependencies: '@types/cookiejar': 2.1.5 @@ -12085,16 +12424,16 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vercel/analytics@1.3.1(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': + '@vercel/analytics@1.3.1(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': dependencies: server-only: 0.0.1 optionalDependencies: - next: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 - '@vercel/speed-insights@1.0.12(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': + '@vercel/speed-insights@1.0.12(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': optionalDependencies: - next: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 '@vitejs/plugin-react@4.3.1(vite@5.3.1(@types/node@20.14.2)(terser@5.31.1))': @@ -12737,6 +13076,8 @@ snapshots: ci-info@3.9.0: {} + cjs-module-lexer@1.4.0: {} + class-variance-authority@0.7.0: dependencies: clsx: 2.0.0 @@ -13925,9 +14266,9 @@ snapshots: strip-ansi: 6.0.1 wide-align: 1.1.5 - geist@1.3.0(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)): + geist@1.3.0(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)): dependencies: - next: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) gensync@1.0.0-beta.2: {} @@ -14328,6 +14669,13 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-in-the-middle@1.11.0: + dependencies: + acorn: 8.12.0 + acorn-import-attributes: 1.9.5(acorn@8.12.0) + cjs-module-lexer: 1.4.0 + module-details-from-path: 1.0.3 + imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -14787,6 +15135,8 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + long@5.2.3: {} + longest-streak@3.1.0: {} loose-envify@1.4.0: @@ -14842,11 +15192,11 @@ snapshots: marked@7.0.4: {} - md-to-react-email@4.1.0(react-email@2.1.0(@babel/core@7.24.7)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0): + md-to-react-email@4.1.0(react-email@2.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0): dependencies: marked: 7.0.4 react: 18.2.0 - react-email: 2.1.0(@babel/core@7.24.7)(@swc/helpers@0.5.11)(eslint@8.30.0) + react-email: 2.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@swc/helpers@0.5.11)(eslint@8.30.0) mdast-util-find-and-replace@3.0.1: dependencies: @@ -15428,6 +15778,8 @@ snapshots: pkg-types: 1.1.1 ufo: 1.5.3 + module-details-from-path@1.0.3: {} + mrmime@2.0.0: {} ms@2.1.2: {} @@ -15454,13 +15806,13 @@ snapshots: neo-async@2.6.2: {} - next-themes@0.2.1(next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-themes@0.2.1(next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.1.0(@babel/core@7.24.7)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + next@14.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: '@next/env': 14.1.0 '@swc/helpers': 0.5.2 @@ -15481,11 +15833,12 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.1.0 '@next/swc-win32-ia32-msvc': 14.1.0 '@next/swc-win32-x64-msvc': 14.1.0 + '@opentelemetry/api': 1.9.0 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - next@14.2.3(@babel/core@7.24.7)(react-dom@18.2.0(react@18.2.0))(react@18.3.1): + next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.3.1): dependencies: '@next/env': 14.2.3 '@swc/helpers': 0.5.5 @@ -15506,11 +15859,12 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.3 '@next/swc-win32-ia32-msvc': 14.2.3 '@next/swc-win32-x64-msvc': 14.2.3 + '@opentelemetry/api': 1.9.0 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - next@14.2.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.2.3(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@next/env': 14.2.3 '@swc/helpers': 0.5.5 @@ -15531,11 +15885,12 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.3 '@next/swc-win32-ia32-msvc': 14.2.3 '@next/swc-win32-x64-msvc': 14.2.3 + '@opentelemetry/api': 1.9.0 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - next@14.2.5(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.2.5(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@next/env': 14.2.5 '@swc/helpers': 0.5.5 @@ -15556,11 +15911,12 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.5 '@next/swc-win32-ia32-msvc': 14.2.5 '@next/swc-win32-x64-msvc': 14.2.5 + '@opentelemetry/api': 1.9.0 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - next@14.2.7(@babel/core@7.24.7)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + next@14.2.7(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: '@next/env': 14.2.7 '@swc/helpers': 0.5.5 @@ -15581,11 +15937,12 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.7 '@next/swc-win32-ia32-msvc': 14.2.7 '@next/swc-win32-x64-msvc': 14.2.7 + '@opentelemetry/api': 1.9.0 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - next@14.3.0-canary.26(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.3.0-canary.26(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@next/env': 14.3.0-canary.26 '@swc/helpers': 0.5.11 @@ -15606,6 +15963,7 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.3.0-canary.26 '@next/swc-win32-ia32-msvc': 14.3.0-canary.26 '@next/swc-win32-x64-msvc': 14.3.0-canary.26 + '@opentelemetry/api': 1.9.0 sharp: 0.33.4 transitivePeerDependencies: - '@babel/core' @@ -16102,6 +16460,21 @@ snapshots: proto-list@1.2.4: {} + protobufjs@7.4.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 20.10.6 + long: 5.2.3 + proxy-from-env@1.1.0: {} pseudomap@1.0.2: {} @@ -16194,7 +16567,7 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-email@2.1.0(@babel/core@7.24.7)(@swc/helpers@0.5.11)(eslint@8.30.0): + react-email@2.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@swc/helpers@0.5.11)(eslint@8.30.0): dependencies: '@radix-ui/colors': 1.0.1 '@radix-ui/react-collapsible': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -16202,7 +16575,7 @@ snapshots: '@radix-ui/react-slot': 1.0.2(@types/react@18.3.3)(react@18.2.0) '@radix-ui/react-toggle-group': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@radix-ui/react-tooltip': 1.0.6(@types/react-dom@18.2.18)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@react-email/components': 0.0.15(@types/react@18.3.3)(react-email@2.1.0(@babel/core@7.24.7)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0) + '@react-email/components': 0.0.15(@types/react@18.3.3)(react-email@2.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@swc/helpers@0.5.11)(eslint@8.30.0))(react@18.2.0) '@react-email/render': 0.0.12 '@swc/core': 1.3.101(@swc/helpers@0.5.11) '@types/react': 18.3.3 @@ -16221,7 +16594,7 @@ snapshots: glob: 10.3.4 log-symbols: 4.1.0 mime-types: 2.1.35 - next: 14.1.0(@babel/core@7.24.7)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + next: 14.1.0(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) normalize-path: 3.0.0 ora: 5.4.1 postcss: 8.4.35 @@ -16468,6 +16841,14 @@ snapshots: require-directory@2.1.1: {} + require-in-the-middle@7.4.0: + dependencies: + debug: 4.3.5 + module-details-from-path: 1.0.3 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + require-main-filename@2.0.0: {} requires-port@1.0.0: {} @@ -16682,6 +17063,8 @@ snapshots: interpret: 1.4.0 rechoir: 0.6.2 + shimmer@1.2.1: {} + side-channel@1.0.6: dependencies: call-bind: 1.0.7