Merge branch 'dev' into project-config-to-json

This commit is contained in:
Zai Shi 2025-08-01 01:24:20 +02:00 committed by GitHub
commit eb5a1731a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 59 additions and 16 deletions

View File

@ -7,7 +7,6 @@ import { PrismaTransaction } from "@/lib/types";
import { sendTeamMembershipDeletedWebhook, sendUserCreatedWebhook, sendUserDeletedWebhook, sendUserUpdatedWebhook } from "@/lib/webhooks";
import { RawQuery, getPrismaClientForSourceOfTruth, getPrismaClientForTenancy, getPrismaSchemaForSourceOfTruth, getPrismaSchemaForTenancy, globalPrismaClient, rawQuery, retryTransaction, sqlQuoteIdent } from "@/prisma-client";
import { createCrudHandlers } from "@/route-handlers/crud-handler";
import { log } from "@/utils/telemetry";
import { runAsynchronouslyAndWaitUntil } from "@/utils/vercel";
import { BooleanTrue, Prisma } from "@prisma/client";
import { KnownErrors } from "@stackframe/stack-shared";
@ -20,6 +19,7 @@ import { StackAssertionError, StatusError, captureError, throwErr } from "@stack
import { hashPassword, isPasswordHashValid } from "@stackframe/stack-shared/dist/utils/hashes";
import { has } from "@stackframe/stack-shared/dist/utils/objects";
import { createLazyProxy } from "@stackframe/stack-shared/dist/utils/proxies";
import { log } from "@stackframe/stack-shared/dist/utils/telemetry";
import { isUuid } from "@stackframe/stack-shared/dist/utils/uuids";
import { teamPrismaToCrud, teamsCrudHandlers } from "../teams/crud";

View File

@ -1,4 +1,4 @@
import { TracedFreestyleSandboxes } from '@/lib/freestyle';
import { Freestyle } from '@/lib/freestyle';
import { emptyEmailTheme } from '@stackframe/stack-shared/dist/helpers/emails';
import { getEnvVariable, getNodeEnvironment } from '@stackframe/stack-shared/dist/utils/env';
import { StackAssertionError } from '@stackframe/stack-shared/dist/utils/errors';
@ -122,7 +122,7 @@ export async function renderEmailWithTemplate(
return Result.error(result.error);
}
const freestyle = new TracedFreestyleSandboxes({ apiKey });
const freestyle = new Freestyle({ apiKey });
const nodeModules = {
"@react-email/components": "0.1.1",
"arktype": "2.1.20",

View File

@ -1,5 +1,4 @@
import { getPrismaClientForTenancy } from '@/prisma-client';
import { traceSpan } from '@/utils/telemetry';
import { DEFAULT_TEMPLATE_IDS } from '@stackframe/stack-shared/dist/helpers/emails';
import { UsersCrud } from '@stackframe/stack-shared/dist/interface/crud/users';
import { getEnvVariable } from '@stackframe/stack-shared/dist/utils/env';
@ -7,6 +6,7 @@ import { StackAssertionError, StatusError, captureError } from '@stackframe/stac
import { filterUndefined, omit, pick } from '@stackframe/stack-shared/dist/utils/objects';
import { runAsynchronously, wait } from '@stackframe/stack-shared/dist/utils/promises';
import { Result } from '@stackframe/stack-shared/dist/utils/results';
import { traceSpan } from '@stackframe/stack-shared/dist/utils/telemetry';
import nodemailer from 'nodemailer';
import { getEmailThemeForTemplate, renderEmailWithTemplate } from './email-rendering';
import { Tenancy, getTenancy } from './tenancies';

View File

@ -1,8 +1,8 @@
import { traceSpan } from '@/utils/telemetry';
import { StackAssertionError, captureError, errorToNiceString } from '@stackframe/stack-shared/dist/utils/errors';
import { traceSpan } from '@stackframe/stack-shared/dist/utils/telemetry';
import { FreestyleSandboxes } from 'freestyle-sandboxes';
export class TracedFreestyleSandboxes {
export class Freestyle {
private freestyle: FreestyleSandboxes;
constructor(options: { apiKey: string }) {

View File

@ -1,5 +1,4 @@
import { globalPrismaClient } from '@/prisma-client';
import { traceSpan } from '@/utils/telemetry';
import { Prisma } from '@prisma/client';
import { KnownErrors } from '@stackframe/stack-shared';
import { yupNumber, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields";
@ -8,6 +7,7 @@ import { getEnvVariable } from '@stackframe/stack-shared/dist/utils/env';
import { throwErr } from '@stackframe/stack-shared/dist/utils/errors';
import { signJWT, verifyJWT } from '@stackframe/stack-shared/dist/utils/jwt';
import { Result } from '@stackframe/stack-shared/dist/utils/results';
import { traceSpan } from '@stackframe/stack-shared/dist/utils/telemetry';
import * as jose from 'jose';
import { JOSEError, JWTExpired } from 'jose/errors';
import { SystemEventTypes, logEvent } from './events';

View File

@ -8,10 +8,10 @@ import { globalVar } from "@stackframe/stack-shared/dist/utils/globals";
import { deepPlainEquals, filterUndefined, typedFromEntries, typedKeys } from "@stackframe/stack-shared/dist/utils/objects";
import { concatStacktracesIfRejected, ignoreUnhandledRejection } from "@stackframe/stack-shared/dist/utils/promises";
import { Result } from "@stackframe/stack-shared/dist/utils/results";
import { traceSpan } from "@stackframe/stack-shared/dist/utils/telemetry";
import { isPromise } from "util/types";
import { runMigrationNeeded } from "./auto-migrations";
import { Tenancy } from "./lib/tenancies";
import { traceSpan } from "./utils/telemetry";
export type PrismaClientTransaction = PrismaClient | Parameters<Parameters<PrismaClient['$transaction']>[0]>[0];

View File

@ -1,7 +1,6 @@
import "../polyfills";
import { Tenancy, getSoleTenancyFromProjectBranch, } from "@/lib/tenancies";
import { traceSpan } from "@/utils/telemetry";
import { CrudSchema, CrudTypeOf, CrudlOperation } from "@stackframe/stack-shared/dist/crud";
import { ProjectsCrud } from "@stackframe/stack-shared/dist/interface/crud/projects";
import { UsersCrud } from "@stackframe/stack-shared/dist/interface/crud/users";
@ -10,6 +9,7 @@ import { typedIncludes } from "@stackframe/stack-shared/dist/utils/arrays";
import { StackAssertionError, throwErr } from "@stackframe/stack-shared/dist/utils/errors";
import { FilterUndefined } from "@stackframe/stack-shared/dist/utils/objects";
import { deindent, typedToLowercase } from "@stackframe/stack-shared/dist/utils/strings";
import { traceSpan } from "@stackframe/stack-shared/dist/utils/telemetry";
import * as yup from "yup";
import { SmartRequestAuth } from "./smart-request";
import { SmartRouteHandler, createSmartRouteHandler, routeHandlerTypeHelper } from "./smart-route-handler";

View File

@ -7,7 +7,6 @@ import { getProjectQuery, listManagedProjectIds } from "@/lib/projects";
import { DEFAULT_BRANCH_ID, Tenancy, getSoleTenancyFromProjectBranch } from "@/lib/tenancies";
import { decodeAccessToken } from "@/lib/tokens";
import { globalPrismaClient, rawQueryAll } from "@/prisma-client";
import { traceSpan, withTraceSpan } from "@/utils/telemetry";
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";
@ -16,6 +15,7 @@ import { groupBy, typedIncludes } from "@stackframe/stack-shared/dist/utils/arra
import { getEnvVariable, getNodeEnvironment } from "@stackframe/stack-shared/dist/utils/env";
import { StackAssertionError, StatusError, captureError, throwErr } from "@stackframe/stack-shared/dist/utils/errors";
import { deindent } from "@stackframe/stack-shared/dist/utils/strings";
import { traceSpan, withTraceSpan } from "@stackframe/stack-shared/dist/utils/telemetry";
import { NextRequest } from "next/server";
import * as yup from "yup";

View File

@ -1,8 +1,8 @@
import { traceSpan } from "@/utils/telemetry";
import { yupValidate } from "@stackframe/stack-shared/dist/schema-fields";
import { StackAssertionError } from "@stackframe/stack-shared/dist/utils/errors";
import { Json } from "@stackframe/stack-shared/dist/utils/json";
import { deepPlainEquals } from "@stackframe/stack-shared/dist/utils/objects";
import { traceSpan } from "@stackframe/stack-shared/dist/utils/telemetry";
import { NextRequest } from "next/server";
import * as yup from "yup";
import "../polyfills";

View File

@ -1,6 +1,5 @@
import "../polyfills";
import { traceSpan } from "@/utils/telemetry";
import * as Sentry from "@sentry/nextjs";
import { EndpointDocumentation } from "@stackframe/stack-shared/dist/crud";
import { KnownError, KnownErrors } from "@stackframe/stack-shared/dist/known-errors";
@ -8,6 +7,7 @@ import { generateSecureRandomString } from "@stackframe/stack-shared/dist/utils/
import { getNodeEnvironment } from "@stackframe/stack-shared/dist/utils/env";
import { StackAssertionError, StatusError, captureError, errorToNiceString } from "@stackframe/stack-shared/dist/utils/errors";
import { runAsynchronously, wait } from "@stackframe/stack-shared/dist/utils/promises";
import { traceSpan } from "@stackframe/stack-shared/dist/utils/telemetry";
import { NextRequest } from "next/server";
import * as yup from "yup";
import { DeepPartialSmartRequestWithSentinel, MergeSmartRequest, SmartRequest, createSmartRequest, validateSmartRequest } from "./smart-request";

View File

@ -1,6 +1,7 @@
import { Attributes, AttributeValue, Span, trace } from "@opentelemetry/api";
import { getEnvVariable } from "@stackframe/stack-shared/dist/utils/env";
import { StackAssertionError } from "@stackframe/stack-shared/dist/utils/errors";
const tracer = trace.getTracer('stack-backend');
export function withTraceSpan<P extends any[], T>(optionsOrDescription: string | { description: string, attributes?: Record<string, AttributeValue> }, fn: (...args: P) => Promise<T>): (...args: P) => Promise<T> {

View File

@ -53,6 +53,7 @@
}
},
"dependencies": {
"@opentelemetry/api": "^1.9.0",
"@simplewebauthn/browser": "^11.0.0",
"async-mutex": "^0.5.0",
"bcryptjs": "^3.0.2",

View File

@ -1,8 +1,9 @@
import * as esbuild from 'esbuild-wasm/lib/browser.js';
import { join } from 'path';
import { isBrowserLike } from './env';
import { StackAssertionError, throwErr } from "./errors";
import { Result } from "./results";
import { isBrowserLike } from './env';
import { traceSpan, withTraceSpan } from './telemetry';
let esbuildInitializePromise: Promise<void> | null = null;
// esbuild requires self property to be set, and it is not set by default in nodejs
@ -10,7 +11,7 @@ let esbuildInitializePromise: Promise<void> | null = null;
export async function initializeEsbuild() {
if (!esbuildInitializePromise) {
esbuildInitializePromise = (async () => {
esbuildInitializePromise = withTraceSpan('initializeEsbuild', async () => {
await esbuild.initialize(isBrowserLike() ? {
wasmURL: `https://unpkg.com/esbuild-wasm@${esbuild.version}/esbuild.wasm`,
} : {
@ -48,7 +49,7 @@ export async function bundleJavaScript(sourceFiles: Record<string, string> & { '
]);
let result;
try {
result = await esbuild.build({
result = await traceSpan('bundleJavaScript', async () => await esbuild.build({
entryPoints: ['/entry.js'],
bundle: true,
write: false,
@ -105,7 +106,7 @@ export async function bundleJavaScript(sourceFiles: Record<string, string> & { '
},
},
],
});
}));
} catch (e) {
if (e instanceof Error && e.message.startsWith("Build failed with ")) {
return Result.error(e.message);

View File

@ -0,0 +1,37 @@
import { Attributes, AttributeValue, Span, trace } from "@opentelemetry/api";
import { getEnvVariable } from "./env";
import { StackAssertionError } from "./errors";
const tracer = trace.getTracer('stack-tracer');
export function withTraceSpan<P extends any[], T>(optionsOrDescription: string | { description: string, attributes?: Record<string, AttributeValue> }, fn: (...args: P) => Promise<T>): (...args: P) => Promise<T> {
return async (...args: P) => {
return await traceSpan(optionsOrDescription, (span) => fn(...args));
};
}
export async function traceSpan<T>(optionsOrDescription: string | { description: string, attributes?: Record<string, AttributeValue> }, fn: (span: Span) => Promise<T>): Promise<T> {
let options = typeof optionsOrDescription === 'string' ? { description: optionsOrDescription } : optionsOrDescription;
return await tracer.startActiveSpan(`STACK: ${options.description}`, async (span) => {
if (options.attributes) {
for (const [key, value] of Object.entries(options.attributes)) {
span.setAttribute(key, value);
}
}
try {
return await fn(span);
} finally {
span.end();
}
});
}
export function log(message: string, attributes: Attributes) {
const span = trace.getActiveSpan();
if (span) {
span.addEvent(message, attributes);
// Telemetry is not initialized while seeding, so we don't want to throw an error
} else if (getEnvVariable('STACK_SEED_MODE', 'false') !== 'true') {
throw new StackAssertionError('No active span found');
}
}

View File

@ -1416,6 +1416,9 @@ importers:
packages/stack-shared:
dependencies:
'@opentelemetry/api':
specifier: ^1.9.0
version: 1.9.0
'@simplewebauthn/browser':
specifier: ^11.0.0
version: 11.0.0