From 233dd50d4f4f8b854115e4f1348466f534fa953a Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Thu, 23 Apr 2026 15:39:52 -0700 Subject: [PATCH 01/12] cli init changes --- packages/stack-cli/src/commands/init.ts | 32 +++++++++++-------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/packages/stack-cli/src/commands/init.ts b/packages/stack-cli/src/commands/init.ts index 8dc3ee1076..1bfe6643fe 100644 --- a/packages/stack-cli/src/commands/init.ts +++ b/packages/stack-cli/src/commands/init.ts @@ -57,15 +57,13 @@ async function runInit(program: Command, opts: InitOptions) { console.log("Welcome to Stack Auth!\n"); - const mode: string = "link"; - // TODO: re-enable local emulator option - // const mode: string = opts.mode ?? await select({ - // message: "Would you like to link to an existing project, or create a new one?", - // choices: [ - // { name: "Create a new project (local emulator)", value: "create" as const }, - // { name: "Link an existing project", value: "link" as const }, - // ], - // }); + const mode: string = opts.mode ?? await select({ + message: "Would you like to link to an existing project, or create a new one?", + choices: [ + { name: "Link an existing project", value: "link" as const }, + { name: "Create a new project (local emulator)", value: "create" as const }, + ], + }); let configPath: string | undefined; @@ -104,15 +102,13 @@ async function handleLink(flags: Record, opts: InitOptions, out } else if (opts.mode === "link-cloud") { source = "cloud"; } else { - source = "cloud"; - // TODO: re-enable config file linking option - // source = await select({ - // message: "How would you like to link your project?", - // choices: [ - // { name: "Link from config file", value: "config-file" as const }, - // { name: "Link from app.stack-auth.com", value: "cloud" as const }, - // ], - // }); + source = await select({ + message: "How would you like to link your project?", + choices: [ + { name: "Link from config file", value: "config-file" as const }, + { name: "Link from app.stack-auth.com", value: "cloud" as const }, + ], + }); } if (source === "config-file") { From 5586a3639af75796bca04adf57e24582b447435a Mon Sep 17 00:00:00 2001 From: aadesh18 <110230993+aadesh18@users.noreply.github.com> Date: Fri, 24 Apr 2026 10:29:55 -0700 Subject: [PATCH 02/12] initial commit (#1382) Adds the ability to create a project using cli. --- packages/stack-cli/src/commands/init.ts | 138 +++++++++++++------ packages/stack-cli/src/commands/project.ts | 38 +---- packages/stack-cli/src/lib/create-project.ts | 36 +++++ 3 files changed, 136 insertions(+), 76 deletions(-) create mode 100644 packages/stack-cli/src/lib/create-project.ts diff --git a/packages/stack-cli/src/commands/init.ts b/packages/stack-cli/src/commands/init.ts index 1bfe6643fe..50c26372a8 100644 --- a/packages/stack-cli/src/commands/init.ts +++ b/packages/stack-cli/src/commands/init.ts @@ -10,11 +10,12 @@ import { writeConfigValue } from "../lib/config.js"; import { CliError, AuthError } from "../lib/errors.js"; import { isNonInteractiveEnv } from "../lib/interactive.js"; import { createInitPrompt } from "../lib/init-prompt.js"; +import { createProjectInteractively } from "../lib/create-project.js"; import { runClaudeAgent } from "../lib/claude-agent.js"; import { detectImportPackageFromDir, renderConfigFileContent } from "@stackframe/stack-shared/dist/config-rendering"; type InitOptions = { - mode?: "create" | "link-config" | "link-cloud", + mode?: "create" | "create-cloud" | "link-config" | "link-cloud", apps?: string, configFile?: string, selectProjectId?: string, @@ -26,7 +27,7 @@ export function registerInitCommand(program: Command) { program .command("init") .description("Initialize Stack Auth in your project") - .option("--mode ", "Mode: create, link-config, or link-cloud (skips interactive prompts)") + .option("--mode ", "Mode: create, create-cloud, link-config, or link-cloud (skips interactive prompts)") .option("--apps ", "Comma-separated app IDs to enable (for create mode)") .option("--config-file ", "Path to existing config file (for link-config mode)") .option("--select-project-id ", "Project ID to link (for link-cloud mode)") @@ -57,13 +58,24 @@ async function runInit(program: Command, opts: InitOptions) { console.log("Welcome to Stack Auth!\n"); - const mode: string = opts.mode ?? await select({ - message: "Would you like to link to an existing project, or create a new one?", - choices: [ - { name: "Link an existing project", value: "link" as const }, - { name: "Create a new project (local emulator)", value: "create" as const }, - ], - }); + let mode: string; + if (opts.mode) { + mode = opts.mode; + } else if (opts.selectProjectId) { + mode = "link-cloud"; + } else if (opts.configFile) { + mode = "link-config"; + } else { + console.log("Creating a new Stack Auth project.\n"); + const location = await select({ + message: "Where would you like to create the project?", + choices: [ + { name: "Stack Auth Cloud", value: "hosted" as const }, + { name: "Local (requires local emulator installation, ~1.3gb storage required)", value: "local" as const }, + ], + }); + mode = location === "local" ? "create" : "create-cloud"; + } let configPath: string | undefined; @@ -73,6 +85,9 @@ async function runInit(program: Command, opts: InitOptions) { } else if (mode === "create") { const result = await handleCreate(opts, outputDir); configPath = result.configPath; + } else if (mode === "create-cloud") { + const result = await handleCreateCloud(flags, opts, outputDir); + configPath = result.configPath; } else { throw new CliError(`Unknown mode: ${mode}`); } @@ -138,10 +153,9 @@ async function handleLinkFromConfigFile(opts: InitOptions): Promise<{ configPath return { configPath }; } -async function handleLinkFromCloud(flags: Record, opts: InitOptions, outputDir: string): Promise<{ configPath?: string }> { - let sessionAuth; +async function ensureLoggedInSession(flags: Record) { try { - sessionAuth = resolveSessionAuth(flags as { projectId?: string }); + return resolveSessionAuth(flags as { projectId?: string }); } catch (e) { if (e instanceof AuthError) { if (isNonInteractiveEnv()) { @@ -149,37 +163,16 @@ async function handleLinkFromCloud(flags: Record, opts: InitOpt } console.log("You need to log in first.\n"); await performLogin(flags); - sessionAuth = resolveSessionAuth(flags as { projectId?: string }); - } else { - throw e; + return resolveSessionAuth(flags as { projectId?: string }); } + throw e; } +} - const user = await getInternalUser(sessionAuth); - const projects = await user.listOwnedProjects(); - - if (projects.length === 0) { - throw new CliError("You don't own any projects. Create one at app.stack-auth.com first."); - } - - let projectId: string; - if (opts.selectProjectId) { - const found = projects.find((p) => p.id === opts.selectProjectId); - if (!found) { - throw new CliError(`Project '${opts.selectProjectId}' not found among your owned projects.`); - } - projectId = opts.selectProjectId; - } else { - projectId = await select({ - message: "Select a project:", - choices: projects.map((p) => ({ - name: `${p.displayName} (${p.id})`, - value: p.id, - })), - }); - } - - const project = projects.find((p) => p.id === projectId)!; +async function writeProjectKeysToEnv( + project: { id: string, app: { createInternalApiKey: (opts: { description: string, expiresAt: Date, hasPublishableClientKey: boolean, hasSecretServerKey: boolean, hasSuperSecretAdminKey: boolean }) => Promise<{ publishableClientKey?: string | null, secretServerKey?: string | null }> } }, + outputDir: string, +) { const apiKey = await project.app.createInternalApiKey({ description: "Created by CLI init script", expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 200), // 200 years @@ -190,7 +183,7 @@ async function handleLinkFromCloud(flags: Record, opts: InitOpt const envLines = [ "# Stack Auth", - `NEXT_PUBLIC_STACK_PROJECT_ID=${projectId}`, + `NEXT_PUBLIC_STACK_PROJECT_ID=${project.id}`, `NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=${apiKey.publishableClientKey ?? ""}`, `STACK_SECRET_SERVER_KEY=${apiKey.secretServerKey ?? ""}`, ].join("\n"); @@ -222,7 +215,70 @@ async function handleLinkFromCloud(flags: Record, opts: InitOpt fs.writeFileSync(envPath, envLines + "\n"); console.log("\nCreated .env with Stack Auth keys"); } +} + +async function handleCreateCloud(flags: Record, opts: InitOptions, outputDir: string): Promise<{ configPath?: string }> { + const sessionAuth = await ensureLoggedInSession(flags); + const user = await getInternalUser(sessionAuth); + const newProject = await createProjectInteractively(user, { + defaultDisplayName: path.basename(outputDir), + }); + console.log(`\nCreated project: ${newProject.displayName} (${newProject.id})\n`); + + await writeProjectKeysToEnv(newProject, outputDir); + return {}; +} + +async function handleLinkFromCloud(flags: Record, opts: InitOptions, outputDir: string): Promise<{ configPath?: string }> { + const sessionAuth = await ensureLoggedInSession(flags); + const user = await getInternalUser(sessionAuth); + let projects = await user.listOwnedProjects(); + let autoCreatedProjectId: string | null = null; + + if (projects.length === 0) { + if (isNonInteractiveEnv()) { + throw new CliError("No projects found. Run `stack project create --display-name ` first, or set --select-project-id."); + } + + const shouldCreate = await confirm({ + message: "You don't have any Stack Auth projects yet. Would you like to create one?", + default: true, + }); + + if (!shouldCreate) { + throw new CliError("You don't own any projects. Create one at app.stack-auth.com or re-run and choose to create one."); + } + + const newProject = await createProjectInteractively(user, { + defaultDisplayName: path.basename(outputDir), + }); + console.log(`\nCreated project: ${newProject.displayName} (${newProject.id})\n`); + projects = [newProject]; + autoCreatedProjectId = newProject.id; + } + + let projectId: string; + if (opts.selectProjectId) { + const found = projects.find((p) => p.id === opts.selectProjectId); + if (!found) { + throw new CliError(`Project '${opts.selectProjectId}' not found among your owned projects.`); + } + projectId = opts.selectProjectId; + } else if (autoCreatedProjectId) { + projectId = autoCreatedProjectId; + } else { + projectId = await select({ + message: "Select a project:", + choices: projects.map((p) => ({ + name: `${p.displayName} (${p.id})`, + value: p.id, + })), + }); + } + + const project = projects.find((p) => p.id === projectId)!; + await writeProjectKeysToEnv(project, outputDir); return {}; } diff --git a/packages/stack-cli/src/commands/project.ts b/packages/stack-cli/src/commands/project.ts index 16dbfc4e62..2b1f49ff16 100644 --- a/packages/stack-cli/src/commands/project.ts +++ b/packages/stack-cli/src/commands/project.ts @@ -1,22 +1,7 @@ import { Command } from "commander"; -import * as readline from "readline"; import { resolveSessionAuth } from "../lib/auth.js"; import { getInternalUser } from "../lib/app.js"; -import { isNonInteractiveEnv } from "../lib/interactive.js"; -import { CliError } from "../lib/errors.js"; - -function prompt(question: string): Promise { - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - }); - return new Promise((resolve) => { - rl.question(question, (answer) => { - rl.close(); - resolve(answer); - }); - }); -} +import { createProjectInteractively } from "../lib/create-project.js"; export function registerProjectCommand(program: Command) { const project = program @@ -54,25 +39,8 @@ export function registerProjectCommand(program: Command) { const auth = resolveSessionAuth(flags); const user = await getInternalUser(auth); - let displayName: string = opts.displayName; - if (!displayName) { - if (isNonInteractiveEnv()) { - throw new CliError("--display-name is required in non-interactive environments (CI)."); - } - displayName = await prompt("Project display name: "); - if (!displayName.trim()) { - throw new CliError("Display name cannot be empty."); - } - } - - const teams = await user.listTeams(); - if (teams.length === 0) { - throw new CliError("No teams found. You need a team to create a project."); - } - - const newProject = await user.createProject({ - displayName, - teamId: teams[0].id, + const newProject = await createProjectInteractively(user, { + displayName: opts.displayName, }); if (program.opts().json) { diff --git a/packages/stack-cli/src/lib/create-project.ts b/packages/stack-cli/src/lib/create-project.ts new file mode 100644 index 0000000000..686a2c96ba --- /dev/null +++ b/packages/stack-cli/src/lib/create-project.ts @@ -0,0 +1,36 @@ +import { input } from "@inquirer/prompts"; +import type { CurrentInternalUser } from "@stackframe/js"; +import { CliError } from "./errors.js"; +import { isNonInteractiveEnv } from "./interactive.js"; + +type CreateProjectOptions = { + displayName?: string, + defaultDisplayName?: string, +}; + +export async function createProjectInteractively( + user: CurrentInternalUser, + opts: CreateProjectOptions = {}, +) { + let displayName = opts.displayName; + if (!displayName) { + if (isNonInteractiveEnv()) { + throw new CliError("--display-name is required in non-interactive environments (CI)."); + } + displayName = await input({ + message: "Project display name:", + default: opts.defaultDisplayName, + validate: (v) => v.trim().length > 0 || "Display name cannot be empty.", + }); + } + + const teams = await user.listTeams(); + if (teams.length === 0) { + throw new CliError("No teams found on your account. Create a team at app.stack-auth.com first."); + } + + return await user.createProject({ + displayName: displayName.trim(), + teamId: teams[0].id, + }); +} From ba2d75f80b0b302bfa3910ae9f3e1a7645212601 Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Fri, 24 Apr 2026 10:52:58 -0700 Subject: [PATCH 03/12] fix(stack-cli): honor inferred link mode and fail loudly on missing API keys - handleLink now respects the mode resolved by runInit (from --config-file / --select-project-id), so those flags skip the interactive source prompt. - writeProjectKeysToEnv throws via throwErr instead of silently writing empty publishable/secret keys to .env when the API returns null. --- packages/stack-cli/src/commands/init.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/stack-cli/src/commands/init.ts b/packages/stack-cli/src/commands/init.ts index 50c26372a8..74987f8a44 100644 --- a/packages/stack-cli/src/commands/init.ts +++ b/packages/stack-cli/src/commands/init.ts @@ -13,6 +13,7 @@ import { createInitPrompt } from "../lib/init-prompt.js"; import { createProjectInteractively } from "../lib/create-project.js"; import { runClaudeAgent } from "../lib/claude-agent.js"; import { detectImportPackageFromDir, renderConfigFileContent } from "@stackframe/stack-shared/dist/config-rendering"; +import { throwErr } from "@stackframe/stack-shared/dist/utils/errors"; type InitOptions = { mode?: "create" | "create-cloud" | "link-config" | "link-cloud", @@ -80,7 +81,7 @@ async function runInit(program: Command, opts: InitOptions) { let configPath: string | undefined; if (mode === "link" || mode === "link-config" || mode === "link-cloud") { - const result = await handleLink(flags, opts, outputDir); + const result = await handleLink(flags, opts, outputDir, mode); configPath = result.configPath; } else if (mode === "create") { const result = await handleCreate(opts, outputDir); @@ -109,12 +110,12 @@ async function runInit(program: Command, opts: InitOptions) { } } -async function handleLink(flags: Record, opts: InitOptions, outputDir: string): Promise<{ configPath?: string }> { +async function handleLink(flags: Record, opts: InitOptions, outputDir: string, resolvedMode?: string): Promise<{ configPath?: string }> { let source: "config-file" | "cloud"; - if (opts.mode === "link-config") { + if (resolvedMode === "link-config" || opts.mode === "link-config") { source = "config-file"; - } else if (opts.mode === "link-cloud") { + } else if (resolvedMode === "link-cloud" || opts.mode === "link-cloud") { source = "cloud"; } else { source = await select({ @@ -181,11 +182,14 @@ async function writeProjectKeysToEnv( hasSuperSecretAdminKey: false, }); + const publishableClientKey = apiKey.publishableClientKey ?? throwErr("createInternalApiKey returned no publishableClientKey despite hasPublishableClientKey=true"); + const secretServerKey = apiKey.secretServerKey ?? throwErr("createInternalApiKey returned no secretServerKey despite hasSecretServerKey=true"); + const envLines = [ "# Stack Auth", `NEXT_PUBLIC_STACK_PROJECT_ID=${project.id}`, - `NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=${apiKey.publishableClientKey ?? ""}`, - `STACK_SECRET_SERVER_KEY=${apiKey.secretServerKey ?? ""}`, + `NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=${publishableClientKey}`, + `STACK_SECRET_SERVER_KEY=${secretServerKey}`, ].join("\n"); const envPath = path.resolve(outputDir, ".env"); From 22beaa778bb360b9dec1e3ef589934e2f61f0dfe Mon Sep 17 00:00:00 2001 From: Aadesh Kheria Date: Fri, 24 Apr 2026 13:35:09 -0700 Subject: [PATCH 04/12] added next steps instructions --- packages/stack-cli/src/commands/init.ts | 34 +++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/packages/stack-cli/src/commands/init.ts b/packages/stack-cli/src/commands/init.ts index 74987f8a44..2ef5d09329 100644 --- a/packages/stack-cli/src/commands/init.ts +++ b/packages/stack-cli/src/commands/init.ts @@ -79,16 +79,19 @@ async function runInit(program: Command, opts: InitOptions) { } let configPath: string | undefined; + let projectId: string | undefined; if (mode === "link" || mode === "link-config" || mode === "link-cloud") { const result = await handleLink(flags, opts, outputDir, mode); configPath = result.configPath; + projectId = result.projectId; } else if (mode === "create") { const result = await handleCreate(opts, outputDir); configPath = result.configPath; } else if (mode === "create-cloud") { const result = await handleCreateCloud(flags, opts, outputDir); configPath = result.configPath; + projectId = result.projectId; } else { throw new CliError(`Unknown mode: ${mode}`); } @@ -108,9 +111,30 @@ async function runInit(program: Command, opts: InitOptions) { } else { console.log("\n" + initPrompt); } + + const { dashboardUrl } = resolveLoginConfig(flags as { projectId?: string }); + printNextSteps({ mode, projectId, dashboardUrl }); +} + +function printNextSteps(args: { mode: string, projectId?: string, dashboardUrl: string }) { + console.log("\nYou're all set! What's next:\n"); + console.log(" • Start your dev server, then visit /handler/sign-up to create a test user"); + console.log(" (and /handler/sign-in to log in). Drop into a page to see the session."); + + if (args.mode === "create") { + console.log(" • You're wired up to the local emulator. Start it in another terminal:"); + console.log(" npx @stackframe/stack-cli emulator start"); + console.log(" Local dashboard: http://localhost:26700"); + } else if (args.projectId) { + console.log(" • Manage this project in the dashboard:"); + console.log(` ${args.dashboardUrl}/projects/${args.projectId}`); + } + + console.log(" • Docs: https://docs.stack-auth.com"); + console.log(""); } -async function handleLink(flags: Record, opts: InitOptions, outputDir: string, resolvedMode?: string): Promise<{ configPath?: string }> { +async function handleLink(flags: Record, opts: InitOptions, outputDir: string, resolvedMode?: string): Promise<{ configPath?: string, projectId?: string }> { let source: "config-file" | "cloud"; if (resolvedMode === "link-config" || opts.mode === "link-config") { @@ -221,7 +245,7 @@ async function writeProjectKeysToEnv( } } -async function handleCreateCloud(flags: Record, opts: InitOptions, outputDir: string): Promise<{ configPath?: string }> { +async function handleCreateCloud(flags: Record, _opts: InitOptions, outputDir: string): Promise<{ configPath?: string, projectId?: string }> { const sessionAuth = await ensureLoggedInSession(flags); const user = await getInternalUser(sessionAuth); @@ -231,10 +255,10 @@ async function handleCreateCloud(flags: Record, opts: InitOptio console.log(`\nCreated project: ${newProject.displayName} (${newProject.id})\n`); await writeProjectKeysToEnv(newProject, outputDir); - return {}; + return { projectId: newProject.id }; } -async function handleLinkFromCloud(flags: Record, opts: InitOptions, outputDir: string): Promise<{ configPath?: string }> { +async function handleLinkFromCloud(flags: Record, opts: InitOptions, outputDir: string): Promise<{ configPath?: string, projectId?: string }> { const sessionAuth = await ensureLoggedInSession(flags); const user = await getInternalUser(sessionAuth); let projects = await user.listOwnedProjects(); @@ -283,7 +307,7 @@ async function handleLinkFromCloud(flags: Record, opts: InitOpt const project = projects.find((p) => p.id === projectId)!; await writeProjectKeysToEnv(project, outputDir); - return {}; + return { projectId }; } async function performLogin(flags: Record) { From 2da2ca5dc02ecd92fcb7cf7ae94805e0ecba0a31 Mon Sep 17 00:00:00 2001 From: Aadesh Kheria Date: Mon, 27 Apr 2026 16:06:50 -0700 Subject: [PATCH 05/12] cli bugs --- .../internal/local-emulator/project/route.tsx | 98 +++- .../projects/page-client.tsx | 96 +++- packages/stack-cli/package.json | 1 + packages/stack-cli/src/commands/emulator.ts | 39 ++ packages/stack-cli/src/commands/init.ts | 20 +- packages/stack-cli/src/index.ts | 25 + packages/stack-cli/src/lib/sentry.ts | 110 +++++ packages/stack-cli/tsdown.config.ts | 3 + pnpm-lock.yaml | 458 +++++++----------- 9 files changed, 534 insertions(+), 316 deletions(-) create mode 100644 packages/stack-cli/src/lib/sentry.ts diff --git a/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx b/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx index 5e13731498..eb10f66bc4 100644 --- a/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx +++ b/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx @@ -12,7 +12,7 @@ import { import { DEFAULT_BRANCH_ID, getSoleTenancyFromProjectBranch } from "@/lib/tenancies"; import { getPrismaClientForTenancy, globalPrismaClient } from "@/prisma-client"; import { createSmartRouteHandler } from "@/route-handlers/smart-route-handler"; -import { clientOrHigherAuthTypeSchema, yupNumber, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields"; +import { clientOrHigherAuthTypeSchema, yupArray, yupNumber, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields"; import { generateSecureRandomString } from "@stackframe/stack-shared/dist/utils/crypto"; import { StackAssertionError, StatusError } from "@stackframe/stack-shared/dist/utils/errors"; import { generateUuid } from "@stackframe/stack-shared/dist/utils/uuids"; @@ -215,10 +215,20 @@ export const POST = createSmartRouteHandler({ throw new StatusError(StatusError.BadRequest, "absolute_file_path must be an absolute path."); } - const absoluteFilePath = path.resolve(req.body.absolute_file_path); - const resolvedFilePath = resolveEmulatorPath(absoluteFilePath); + const inputPath = path.resolve(req.body.absolute_file_path); + let inputStat; + try { + inputStat = await fs.stat(resolveEmulatorPath(inputPath)); + } catch { + inputStat = undefined; + } + + const looksLikeConfigFile = /\.(ts|js|mjs)$/i.test(inputPath); + const absoluteFilePath = (inputStat?.isDirectory() || (!inputStat && !looksLikeConfigFile)) + ? path.join(inputPath, "stack.config.ts") + : inputPath; - // Validate file exists before creating a project + const resolvedFilePath = resolveEmulatorPath(absoluteFilePath); let fileExists: boolean; try { await fs.access(resolvedFilePath); @@ -227,13 +237,13 @@ export const POST = createSmartRouteHandler({ fileExists = false; } if (!fileExists) { - throw new StatusError(StatusError.BadRequest, `Config file not found: ${absoluteFilePath}`); - } - - // If the file is empty, write a default config - const fileContent = await fs.readFile(resolvedFilePath, "utf-8"); - if (fileContent.trim() === "") { await writeConfigToFile(absoluteFilePath, {}); + } else { + // If the file is empty, write a default config. + const fileContent = await fs.readFile(resolvedFilePath, "utf-8"); + if (fileContent.trim() === "") { + await writeConfigToFile(absoluteFilePath, {}); + } } await assertLocalEmulatorOwnerTeamReadiness(); @@ -255,3 +265,71 @@ export const POST = createSmartRouteHandler({ }; }, }); + +type LocalEmulatorProjectListRow = { + projectId: string, + absoluteFilePath: string, + updatedAt: Date, +}; + +export const GET = createSmartRouteHandler({ + metadata: { + hidden: true, + summary: "List recent local emulator projects", + description: "Returns previously opened local emulator project mappings, most-recent first.", + tags: ["Local Emulator"], + }, + request: yupObject({ + auth: yupObject({ + type: clientOrHigherAuthTypeSchema.defined(), + project: yupObject({ + id: yupString().oneOf(["internal"]).defined(), + }).defined(), + }).defined(), + method: yupString().oneOf(["GET"]).defined(), + }), + response: yupObject({ + statusCode: yupNumber().oneOf([200]).defined(), + bodyType: yupString().oneOf(["json"]).defined(), + body: yupObject({ + projects: yupArray(yupObject({ + project_id: yupString().defined(), + absolute_file_path: yupString().defined(), + display_name: yupString().defined(), + }).defined()).defined(), + }).defined(), + }), + handler: async () => { + if (!isLocalEmulatorEnabled()) { + throw new StatusError(StatusError.BadRequest, LOCAL_EMULATOR_ONLY_ENDPOINT_MESSAGE); + } + + const rows = await globalPrismaClient.$queryRaw(Prisma.sql` + SELECT "projectId", "absoluteFilePath", "updatedAt" + FROM "LocalEmulatorProject" + ORDER BY "updatedAt" DESC + LIMIT 20 + `); + + const projectIds = rows.map((r) => r.projectId); + const projects = projectIds.length > 0 + ? await globalPrismaClient.project.findMany({ + where: { id: { in: projectIds } }, + select: { id: true, displayName: true }, + }) + : []; + const displayNameById = new Map(projects.map((p) => [p.id, p.displayName])); + + return { + statusCode: 200 as const, + bodyType: "json" as const, + body: { + projects: rows.map((r) => ({ + project_id: r.projectId, + absolute_file_path: r.absoluteFilePath, + display_name: displayNameById.get(r.projectId) ?? path.basename(r.absoluteFilePath), + })), + }, + }; + }, +}); diff --git a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx index fe8427917f..af7c9e24fe 100644 --- a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx @@ -65,6 +65,7 @@ export default function PageClient() { const [openConfigFileDialog, setOpenConfigFileDialog] = useState(false); const [absoluteConfigFilePath, setAbsoluteConfigFilePath] = useState(""); const [openingConfigFile, setOpeningConfigFile] = useState(false); + const [recentConfigProjects, setRecentConfigProjects] = useState>([]); const [projectStatuses, setProjectStatuses] = useState>(new Map()); const [loadingProjectStatuses, setLoadingProjectStatuses] = useState(true); const router = useRouter(); @@ -118,17 +119,53 @@ export default function PageClient() { }; }, [appInternals, rawProjects.length]); + useEffect(() => { + if (!openConfigFileDialog || !isLocalEmulator) return; + let cancelled = false; + runAsynchronously(async () => { + try { + const response = await appInternals.sendRequest("/internal/local-emulator/project", { method: "GET" }, "client"); + if (!response.ok) return; + const body = await response.json() as { projects?: Array<{ project_id?: string, absolute_file_path?: string, display_name?: string }> }; + if (cancelled || !body.projects) return; + const parsed = body.projects + .filter((p): p is { project_id: string, absolute_file_path: string, display_name: string } => + typeof p.project_id === "string" && typeof p.absolute_file_path === "string" && typeof p.display_name === "string", + ); + setRecentConfigProjects(parsed); + } catch { + // best-effort — dialog still works without the recent list + } + }); + return () => { + cancelled = true; + }; + }, [openConfigFileDialog, isLocalEmulator, appInternals]); + + const pathCopyTip = useMemo(() => { + const p = typeof navigator !== "undefined" ? navigator.platform : ""; + if (/Mac|iPhone|iPad|iPod/i.test(p)) { + return "Tip: in Finder, right-click the file → hold ⌥ Option → Copy as Pathname, then paste here."; + } + if (/Win/i.test(p)) { + return "Tip: in File Explorer, Shift + right-click the file → Copy as path, then paste here."; + } + return "Tip: from your project folder, run `realpath stack.config.ts` in a terminal."; + }, []); + const handleOpenConfigFile = async () => { const trimmedPath = absoluteConfigFilePath.trim(); if (trimmedPath.length === 0) { - throw new Error("Please enter an absolute config file path."); + toast({ description: "Please enter a path to your project or stack.config.ts.", variant: "destructive" }); + return; } const hasUnixAbsolutePath = trimmedPath.startsWith("/"); const hasWindowsAbsolutePath = /^[a-zA-Z]:[\\/]/.test(trimmedPath); const hasWindowsUncPath = trimmedPath.startsWith("\\\\"); if (!hasUnixAbsolutePath && !hasWindowsAbsolutePath && !hasWindowsUncPath) { - throw new Error("Config file path must be absolute."); + toast({ description: "The path must be absolute (e.g. /Users/you/project or /Users/you/project/stack.config.ts).", variant: "destructive" }); + return; } setOpeningConfigFile(true); @@ -149,19 +186,20 @@ export default function PageClient() { const responseBody = await response.json(); if (!response.ok) { + let message = "Couldn't open that path. Make sure it points to your project folder or a valid stack.config.ts."; if (typeof responseBody === "string" && responseBody.length > 0) { - throw new Error(responseBody); - } - if ( + message = responseBody; + } else if ( responseBody != null && typeof responseBody === "object" && "error" in responseBody && typeof responseBody.error === "string" && responseBody.error.length > 0 ) { - throw new Error(responseBody.error); + message = responseBody.error; } - throw new Error("Failed to open config file project in local emulator."); + toast({ description: message, variant: "destructive" }); + return; } if ( @@ -170,7 +208,8 @@ export default function PageClient() { !("project_id" in responseBody) || typeof responseBody.project_id !== "string" ) { - throw new Error("Local emulator endpoint returned an invalid response."); + toast({ description: "Local emulator endpoint returned an invalid response.", variant: "destructive" }); + return; } setOpenConfigFileDialog(false); @@ -178,6 +217,11 @@ export default function PageClient() { await appInternals.refreshOwnedProjects(); router.push(`/projects/${encodeURIComponent(responseBody.project_id)}`); await wait(2000); + } catch (e) { + toast({ + description: e instanceof Error ? e.message : "Something went wrong opening that project.", + variant: "destructive", + }); } finally { setOpeningConfigFile(false); } @@ -248,7 +292,7 @@ export default function PageClient() { router.push("/new-project"); return await wait(2000); }} - >{isLocalEmulator ? "Open config file" : "Create Project"} + >{isLocalEmulator ? "Open a project" : "Create Project"} @@ -264,24 +308,52 @@ export default function PageClient() { > - Open config file + Open your Stack Auth project
- Enter the absolute path to your local Stack config file. The local emulator will create or reuse the mapped project and open it in the dashboard. + Point the local dashboard at the stack.config.ts in your project. If you just ran stack init, it was created at the root of that project. + + + Don't have one yet? Paste your project folder path instead and we'll create stack.config.ts for you. + {recentConfigProjects.length > 0 && ( +
+ Recent +
+ {recentConfigProjects.map((p) => ( + + ))} +
+
+ )} setAbsoluteConfigFilePath(event.target.value)} /> + + {pathCopyTip} +
- diff --git a/packages/stack-cli/package.json b/packages/stack-cli/package.json index 645dd1a433..04a6d3c8d6 100644 --- a/packages/stack-cli/package.json +++ b/packages/stack-cli/package.json @@ -29,6 +29,7 @@ "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.73", "@inquirer/prompts": "^7.0.0", + "@sentry/node": "^10.42.0", "@stackframe/js": "workspace:*", "@stackframe/stack-shared": "workspace:*", "commander": "^13.1.0", diff --git a/packages/stack-cli/src/commands/emulator.ts b/packages/stack-cli/src/commands/emulator.ts index 3a67d26c07..ebb5dadbfb 100644 --- a/packages/stack-cli/src/commands/emulator.ts +++ b/packages/stack-cli/src/commands/emulator.ts @@ -251,6 +251,38 @@ async function startEmulator(arch: "arm64" | "amd64"): Promise { await runEmulator("start", { EMULATOR_ARCH: arch, STACK_EMULATOR_CLI_WROTE_ISO: "1" }); } +function printEmulatorWelcome(): void { + const dashboardPort = envPort("EMULATOR_DASHBOARD_PORT", DEFAULT_EMULATOR_DASHBOARD_PORT); + const backendPort = envPort("EMULATOR_BACKEND_PORT", DEFAULT_EMULATOR_BACKEND_PORT); + const inbucketPort = envPort("EMULATOR_INBUCKET_PORT", DEFAULT_EMULATOR_INBUCKET_PORT); + + console.log("\nEmulator is up.\n"); + console.log("The Stack Auth emulator runs a full local Stack Auth stack (backend, dashboard,"); + console.log("Postgres, Redis, MinIO, and a test mail server) inside a VM on your machine."); + console.log("It gives you an offline, disposable Stack Auth you can develop against — no"); + console.log("cloud account needed, and you can reset it any time.\n"); + console.log("Services:"); + console.log(` • Local dashboard http://localhost:${dashboardPort}`); + console.log(` • Backend API http://localhost:${backendPort}`); + console.log(` • Test inbox http://localhost:${inbucketPort} (catches all outbound email)`); + console.log(""); + console.log("Common commands:"); + console.log(" stack emulator status Check service health"); + console.log(" stack emulator stop Stop the VM (keeps data)"); + console.log(" stack emulator reset Wipe all state and start fresh"); + console.log(" stack emulator run Start the emulator, run , stop on exit"); + console.log(""); +} + +export function isEmulatorImageInstalled(arch?: "arm64" | "amd64"): boolean { + try { + const resolvedArch = arch ?? resolveArch(); + return existsSync(join(emulatorImageDir(), `stack-emulator-${resolvedArch}.qcow2`)); + } catch { + return false; + } +} + export function resolveArch(raw?: string): "arm64" | "amd64" { const arch = raw ?? (process.arch === "arm64" ? "arm64" : process.arch === "x64" ? "amd64" : null); if (arch === "arm64" || arch === "amd64") return arch; @@ -576,16 +608,23 @@ export function registerEmulatorCommand(program: Command) { } } + let freshlyStarted = false; if (isEmulatorRunning()) { console.warn("Emulator already running, reusing existing instance."); } else { await startEmulator(arch); + freshlyStarted = true; } if (resolvedConfigFile) { const pck = await readInternalPck(); const creds = await fetchEmulatorCredentials(pck, emulatorBackendPort(), resolvedConfigFile); console.log(JSON.stringify(creds, null, 2)); + return; + } + + if (freshlyStarted) { + printEmulatorWelcome(); } }); diff --git a/packages/stack-cli/src/commands/init.ts b/packages/stack-cli/src/commands/init.ts index 2ef5d09329..c989a81bfd 100644 --- a/packages/stack-cli/src/commands/init.ts +++ b/packages/stack-cli/src/commands/init.ts @@ -12,6 +12,7 @@ import { isNonInteractiveEnv } from "../lib/interactive.js"; import { createInitPrompt } from "../lib/init-prompt.js"; import { createProjectInteractively } from "../lib/create-project.js"; import { runClaudeAgent } from "../lib/claude-agent.js"; +import { isEmulatorImageInstalled } from "./emulator.js"; import { detectImportPackageFromDir, renderConfigFileContent } from "@stackframe/stack-shared/dist/config-rendering"; import { throwErr } from "@stackframe/stack-shared/dist/utils/errors"; @@ -68,11 +69,14 @@ async function runInit(program: Command, opts: InitOptions) { mode = "link-config"; } else { console.log("Creating a new Stack Auth project.\n"); + const localLabel = isEmulatorImageInstalled() + ? "Local (emulator already installed)" + : "Local (requires local emulator installation, ~1.3gb storage required)"; const location = await select({ message: "Where would you like to create the project?", choices: [ { name: "Stack Auth Cloud", value: "hosted" as const }, - { name: "Local (requires local emulator installation, ~1.3gb storage required)", value: "local" as const }, + { name: localLabel, value: "local" as const }, ], }); mode = location === "local" ? "create" : "create-cloud"; @@ -100,6 +104,9 @@ async function runInit(program: Command, opts: InitOptions) { const useAgent = opts.agent !== false && !isNonInteractiveEnv(); if (useAgent) { + console.log("\nRunning your coding agent to wire up Stack Auth."); + console.log("This also registers the Stack Auth MCP server (https://mcp.stack-auth.com)"); + console.log("so your agent can read the docs and answer Stack-specific questions going forward.\n"); const success = await runClaudeAgent({ prompt: `Execute ALL of the following setup steps in my project now. Do not ask questions — just detect the framework and package manager from existing files and proceed.\n\n${initPrompt}`, cwd: outputDir, @@ -197,6 +204,7 @@ async function ensureLoggedInSession(flags: Record) { async function writeProjectKeysToEnv( project: { id: string, app: { createInternalApiKey: (opts: { description: string, expiresAt: Date, hasPublishableClientKey: boolean, hasSecretServerKey: boolean, hasSuperSecretAdminKey: boolean }) => Promise<{ publishableClientKey?: string | null, secretServerKey?: string | null }> } }, outputDir: string, + variant: "cloud" | "local" = "cloud", ) { const apiKey = await project.app.createInternalApiKey({ description: "Created by CLI init script", @@ -209,8 +217,16 @@ async function writeProjectKeysToEnv( const publishableClientKey = apiKey.publishableClientKey ?? throwErr("createInternalApiKey returned no publishableClientKey despite hasPublishableClientKey=true"); const secretServerKey = apiKey.secretServerKey ?? throwErr("createInternalApiKey returned no secretServerKey despite hasSecretServerKey=true"); + const header = variant === "local" + ? [ + "# Stack Auth — local emulator keys", + "# These credentials point at your local Stack Auth emulator, not a cloud project.", + "# They are only valid while the emulator is running (`stack emulator start`).", + ] + : ["# Stack Auth"]; + const envLines = [ - "# Stack Auth", + ...header, `NEXT_PUBLIC_STACK_PROJECT_ID=${project.id}`, `NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=${publishableClientKey}`, `STACK_SECRET_SERVER_KEY=${secretServerKey}`, diff --git a/packages/stack-cli/src/index.ts b/packages/stack-cli/src/index.ts index 69f4ddc372..1fbffa00ac 100644 --- a/packages/stack-cli/src/index.ts +++ b/packages/stack-cli/src/index.ts @@ -1,3 +1,6 @@ +import { initSentry, reportUnexpectedError, flushSentry } from "./lib/sentry.js"; +initSentry(); + import { Command } from "commander"; import { readFileSync } from "fs"; import { fileURLToPath } from "url"; @@ -44,9 +47,31 @@ async function main() { console.error(`Error: ${err.message}`); process.exit(1); } + reportUnexpectedError(err); + await flushSentry(); throw err; } } +async function handleFatal(err: unknown): Promise { + try { + reportUnexpectedError(err); + await flushSentry(); + } catch { + // best-effort + } + console.error(err); + process.exit(1); +} + +process.on("uncaughtException", (err) => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + handleFatal(err); +}); +process.on("unhandledRejection", (reason) => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + handleFatal(reason); +}); + // eslint-disable-next-line @typescript-eslint/no-floating-promises main(); diff --git a/packages/stack-cli/src/lib/sentry.ts b/packages/stack-cli/src/lib/sentry.ts new file mode 100644 index 0000000000..662536acd3 --- /dev/null +++ b/packages/stack-cli/src/lib/sentry.ts @@ -0,0 +1,110 @@ +import * as Sentry from "@sentry/node"; +import { sentryBaseConfig } from "@stackframe/stack-shared/dist/utils/sentry"; +import { nicify } from "@stackframe/stack-shared/dist/utils/strings"; +import { readFileSync } from "fs"; +import { homedir } from "os"; +import { dirname, join } from "path"; +import { fileURLToPath } from "url"; + +// Replaced at build time by tsdown `define`. Empty = not configured (dev/unbuilt). +declare const __STACK_CLI_SENTRY_DSN__: string; + +let initialized = false; + +function readPackageVersion(): string | undefined { + try { + const here = dirname(fileURLToPath(import.meta.url)); + const pkg = JSON.parse(readFileSync(join(here, "..", "package.json"), "utf-8")) as { version?: string }; + return pkg.version; + } catch { + return undefined; + } +} + +function scrubString(input: string): string { + let out = input; + const home = homedir(); + if (home && home.length > 1) { + out = out.split(home).join("~"); + } + out = out.replace(/\b(sk_[A-Za-z0-9_-]+|pk_[A-Za-z0-9_-]+|pck_[A-Za-z0-9_-]+|stk_[A-Za-z0-9_-]+|ssk_[A-Za-z0-9_-]+|eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)\b/g, "[redacted]"); + return out; +} + +function isSensitiveKey(key: string): boolean { + return /token|key|secret|password|dsn|authorization|cookie/i.test(key); +} + +function scrubValue(value: unknown, key?: string): unknown { + if (key && isSensitiveKey(key) && value != null) { + return "[redacted]"; + } + if (typeof value === "string") { + return scrubString(value); + } + if (Array.isArray(value)) { + return value.map((v) => scrubValue(v)); + } + if (value && typeof value === "object") { + const out: Record = {}; + for (const [k, v] of Object.entries(value)) { + out[k] = scrubValue(v, k); + } + return out; + } + return value; +} + +export function initSentry() { + if (initialized) return; + if (process.env.NODE_ENV === "development" || process.env.CI) return; + + const dsn = typeof __STACK_CLI_SENTRY_DSN__ === "string" ? __STACK_CLI_SENTRY_DSN__ : ""; + if (!dsn) return; + + const version = readPackageVersion(); + + Sentry.init({ + ...sentryBaseConfig, + dsn, + release: version ? `stack-cli@${version}` : undefined, + environment: "production", + sendDefaultPii: false, + tracesSampleRate: 0, + includeLocalVariables: false, + beforeSend(event, hint) { + const error = hint.originalException; + let nicified; + try { + nicified = nicify(error, { maxDepth: 8 }); + } catch (e) { + nicified = `Error occurred during nicification: ${e}`; + } + if (error instanceof Error) { + event.extra = { + ...event.extra, + cause: error.cause, + errorProps: { ...error }, + nicifiedError: nicified, + }; + } + return scrubValue(event) as typeof event; + }, + }); + + initialized = true; +} + +export function reportUnexpectedError(err: unknown) { + if (!initialized) return; + Sentry.captureException(err); +} + +export async function flushSentry() { + if (!initialized) return; + try { + await Sentry.flush(2000); + } catch { + // best-effort + } +} diff --git a/packages/stack-cli/tsdown.config.ts b/packages/stack-cli/tsdown.config.ts index db4ec2a8da..c7c11003ea 100644 --- a/packages/stack-cli/tsdown.config.ts +++ b/packages/stack-cli/tsdown.config.ts @@ -7,6 +7,9 @@ const config: UserConfig = { dts: true, outDir: 'dist', external: ['@anthropic-ai/claude-agent-sdk'], + define: { + __STACK_CLI_SENTRY_DSN__: JSON.stringify(process.env.STACK_CLI_SENTRY_DSN_BUILD ?? ''), + }, format: { esm: { outExtensions: () => ({ js: '.js', dts: '.d.ts' }), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5ec346963c..c2e5295a44 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1020,7 +1020,7 @@ importers: devDependencies: mint: specifier: ^4.2.487 - version: 4.2.487(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/node@24.9.2)(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0) + version: 4.2.487(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/node@20.17.6)(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0) examples/cjs-test: dependencies: @@ -1568,10 +1568,10 @@ importers: version: link:../../packages/stack '@supabase/ssr': specifier: latest - version: 0.10.0(@supabase/supabase-js@2.102.1) + version: 0.10.2(@supabase/supabase-js@2.103.3) '@supabase/supabase-js': specifier: latest - version: 2.102.1 + version: 2.103.3 jose: specifier: ^5.2.2 version: 5.6.3 @@ -2088,6 +2088,9 @@ importers: '@inquirer/prompts': specifier: ^7.0.0 version: 7.10.1(@types/node@20.17.6) + '@sentry/node': + specifier: ^10.42.0 + version: 10.45.0 '@stackframe/js': specifier: workspace:* version: link:../js @@ -9891,36 +9894,36 @@ packages: resolution: {integrity: sha512-SXuhqhuR5FXaYgKTXzZJeqtVA6JKb9IZWaGeEUxHHiOcFy2p51wccO72bYpXwoK4D5pzQOIYLTuAc7etxyMmwg==} engines: {node: '>=12.16'} - '@supabase/auth-js@2.102.1': - resolution: {integrity: sha512-2uH2WB0H98TOGDtaFWhxIcR42Dro/VB7VDZanz/4bVJsqioIue1m3TUqu3xciDm2W9r+1LXQvYNsYbQfWmD+uQ==} + '@supabase/auth-js@2.103.3': + resolution: {integrity: sha512-SMDJ4vg5jLXNEHdhN4J4ujSb203WangbDw1n3VaARH0ZqM51E6lJnoUAHlpQU9N7SzP0hfgghA9IvT8c7tGRfg==} engines: {node: '>=20.0.0'} - '@supabase/functions-js@2.102.1': - resolution: {integrity: sha512-UcrcKTPnAIo+Yp9Jjq9XXwFbsmgRYY637mwka9ZjmTIWcX/xr1pote4OVvaGQycVY1KTiQgjMvpC0Q0yJhRq3w==} + '@supabase/functions-js@2.103.3': + resolution: {integrity: sha512-A2ZHi95GIRRlN9LGOSa/zGEIPg9taR1giDI9Gkfkgrcz0YmKV8ShiAplIrKsHQFdkzKxtsO3maJF0efL+i31mg==} engines: {node: '>=20.0.0'} '@supabase/phoenix@0.4.0': resolution: {integrity: sha512-RHSx8bHS02xwfHdAbX5Lpbo6PXbgyf7lTaXTlwtFDPwOIw64NnVRwFAXGojHhjtVYI+PEPNSWwkL90f4agN3bw==} - '@supabase/postgrest-js@2.102.1': - resolution: {integrity: sha512-InLvXKAYf8BIqiv9jWOYudWB3rU8A9uMbcip5BQ5sLLNPrbO1Ekkr79OvlhZBgMNSppxVyC7wPPGzLxMcTZhlA==} + '@supabase/postgrest-js@2.103.3': + resolution: {integrity: sha512-S0k/9FJVXDeejNfQLCJwRlm4IH8Wet/HEEdBTBpX6/G2o1eU/6CjQop/hJPZIwlQkI6D/zbHH8KymuCsBgy6jA==} engines: {node: '>=20.0.0'} - '@supabase/realtime-js@2.102.1': - resolution: {integrity: sha512-h2fCumib/v6u7XMwSPgxnpfimjX4xCEayUHrxWLC7UurfQjUZJ0pmJDgm6yj80DnUerxuulRghwm5zXYysFG/Q==} + '@supabase/realtime-js@2.103.3': + resolution: {integrity: sha512-fUvKtSXMUk1BkApVwAurWtHF4Vzbb0UB9aC/fQXrRBek7Ta3Kaora+wHf/fGwFNQs7uRz+mvjIVpzLfpR32VXA==} engines: {node: '>=20.0.0'} - '@supabase/ssr@0.10.0': - resolution: {integrity: sha512-36jIu+DuKzg5EgA3fnH+zHvwASvpKcL4zPgmHoZaULroS5Q4mzeHcM69zJ0sXUHddO5IcHjQNZJ9Vyhl/DdbRw==} + '@supabase/ssr@0.10.2': + resolution: {integrity: sha512-JFbchN63CXLFHJRNT7udec4/RoD9PmXkSGko3QSO6vUuqGBtSzdmxR7FPfQNr7SuFd65I7Xv46q66ALjEN1cgQ==} peerDependencies: - '@supabase/supabase-js': ^2.100.1 + '@supabase/supabase-js': ^2.102.1 - '@supabase/storage-js@2.102.1': - resolution: {integrity: sha512-eCL9T4Xpe40nmKlkUJ7Zq/hk34db1xPiT0WL3Iv5MbJqHuCAe5TxhV8Rjqd6DNZrzjtfYObZtYl9jKJaHrivqw==} + '@supabase/storage-js@2.103.3': + resolution: {integrity: sha512-5bAIEubrw5keHcdKR2RTois0O1M2Ilx4UYuzOzc07G6mLGCPS/8t1nbC6Vq451pnxR3sK+rmtFHWb9CY/OPjAw==} engines: {node: '>=20.0.0'} - '@supabase/supabase-js@2.102.1': - resolution: {integrity: sha512-bChxPVeLDnYN9M2d/u4fXsvylwSQG5grAl+HN8f+ZD9a9PuVU+Ru+xGmEsk+b9Iz3rJC9ZQnQUJYQ28fApdWYA==} + '@supabase/supabase-js@2.103.3': + resolution: {integrity: sha512-DuPiAz5pIJsTAQCt7B6bDZrnLzlq9+/5bta/GWTsgpLn6AkuZQcmYsQHYplv4skQ8U2raKY5HASQOu4KtYq9Qw==} engines: {node: '>=20.0.0'} '@sveltejs/sv-utils@0.0.3': @@ -14227,9 +14230,6 @@ packages: import-in-the-middle@1.14.2: resolution: {integrity: sha512-5tCuY9BV8ujfOpwtAGgsTx9CGUapcFMEEyByLv1B+v2+6DhAcw+Zr0nhQT7uwaZ7DiourxFEscghOR8e1aPLQw==} - import-in-the-middle@2.0.0: - resolution: {integrity: sha512-yNZhyQYqXpkT0AKq3F3KLasUSK4fHvebNH5hOsKQw2dhGSALvQ4U0BqUc5suziKvydO5u5hgN2hy1RJaho8U5A==} - import-in-the-middle@2.0.6: resolution: {integrity: sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw==} @@ -22245,7 +22245,7 @@ snapshots: '@fastify/otel@0.17.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.212.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 minimatch: 10.2.4 @@ -22676,16 +22676,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/checkbox@4.3.2(@types/node@24.9.2)': - dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.9.2) - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/confirm@5.1.21(@types/node@20.17.6)': dependencies: '@inquirer/core': 10.3.2(@types/node@20.17.6) @@ -22693,13 +22683,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/confirm@5.1.21(@types/node@24.9.2)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/type': 3.0.10(@types/node@24.9.2) - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/core@10.3.2(@types/node@20.17.6)': dependencies: '@inquirer/ansi': 1.0.2 @@ -22713,19 +22696,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/core@10.3.2(@types/node@24.9.2)': - dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.9.2) - cli-width: 4.1.0 - mute-stream: 2.0.0 - signal-exit: 4.1.0 - wrap-ansi: 6.2.0 - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/editor@4.2.23(@types/node@20.17.6)': dependencies: '@inquirer/core': 10.3.2(@types/node@20.17.6) @@ -22734,14 +22704,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/editor@4.2.23(@types/node@24.9.2)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/external-editor': 1.0.3(@types/node@24.9.2) - '@inquirer/type': 3.0.10(@types/node@24.9.2) - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/expand@4.0.23(@types/node@20.17.6)': dependencies: '@inquirer/core': 10.3.2(@types/node@20.17.6) @@ -22750,14 +22712,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/expand@4.0.23(@types/node@24.9.2)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/type': 3.0.10(@types/node@24.9.2) - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/external-editor@1.0.3(@types/node@20.17.6)': dependencies: chardet: 2.1.1 @@ -22765,13 +22719,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/external-editor@1.0.3(@types/node@24.9.2)': - dependencies: - chardet: 2.1.1 - iconv-lite: 0.7.0 - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/figures@1.0.15': {} '@inquirer/figures@1.0.3': {} @@ -22783,13 +22730,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/input@4.3.1(@types/node@24.9.2)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/type': 3.0.10(@types/node@24.9.2) - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/number@3.0.23(@types/node@20.17.6)': dependencies: '@inquirer/core': 10.3.2(@types/node@20.17.6) @@ -22797,13 +22737,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/number@3.0.23(@types/node@24.9.2)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/type': 3.0.10(@types/node@24.9.2) - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/password@4.0.23(@types/node@20.17.6)': dependencies: '@inquirer/ansi': 1.0.2 @@ -22812,14 +22745,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/password@4.0.23(@types/node@24.9.2)': - dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/type': 3.0.10(@types/node@24.9.2) - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/prompts@7.10.1(@types/node@20.17.6)': dependencies: '@inquirer/checkbox': 4.3.2(@types/node@20.17.6) @@ -22835,35 +22760,20 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/prompts@7.10.1(@types/node@24.9.2)': + '@inquirer/prompts@7.9.0(@types/node@20.17.6)': dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@24.9.2) - '@inquirer/confirm': 5.1.21(@types/node@24.9.2) - '@inquirer/editor': 4.2.23(@types/node@24.9.2) - '@inquirer/expand': 4.0.23(@types/node@24.9.2) - '@inquirer/input': 4.3.1(@types/node@24.9.2) - '@inquirer/number': 3.0.23(@types/node@24.9.2) - '@inquirer/password': 4.0.23(@types/node@24.9.2) - '@inquirer/rawlist': 4.1.11(@types/node@24.9.2) - '@inquirer/search': 3.2.2(@types/node@24.9.2) - '@inquirer/select': 4.4.2(@types/node@24.9.2) - optionalDependencies: - '@types/node': 24.9.2 - - '@inquirer/prompts@7.9.0(@types/node@24.9.2)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@24.9.2) - '@inquirer/confirm': 5.1.21(@types/node@24.9.2) - '@inquirer/editor': 4.2.23(@types/node@24.9.2) - '@inquirer/expand': 4.0.23(@types/node@24.9.2) - '@inquirer/input': 4.3.1(@types/node@24.9.2) - '@inquirer/number': 3.0.23(@types/node@24.9.2) - '@inquirer/password': 4.0.23(@types/node@24.9.2) - '@inquirer/rawlist': 4.1.11(@types/node@24.9.2) - '@inquirer/search': 3.2.2(@types/node@24.9.2) - '@inquirer/select': 4.4.2(@types/node@24.9.2) + '@inquirer/checkbox': 4.3.2(@types/node@20.17.6) + '@inquirer/confirm': 5.1.21(@types/node@20.17.6) + '@inquirer/editor': 4.2.23(@types/node@20.17.6) + '@inquirer/expand': 4.0.23(@types/node@20.17.6) + '@inquirer/input': 4.3.1(@types/node@20.17.6) + '@inquirer/number': 3.0.23(@types/node@20.17.6) + '@inquirer/password': 4.0.23(@types/node@20.17.6) + '@inquirer/rawlist': 4.1.11(@types/node@20.17.6) + '@inquirer/search': 3.2.2(@types/node@20.17.6) + '@inquirer/select': 4.4.2(@types/node@20.17.6) optionalDependencies: - '@types/node': 24.9.2 + '@types/node': 20.17.6 '@inquirer/rawlist@4.1.11(@types/node@20.17.6)': dependencies: @@ -22873,14 +22783,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/rawlist@4.1.11(@types/node@24.9.2)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/type': 3.0.10(@types/node@24.9.2) - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/search@3.2.2(@types/node@20.17.6)': dependencies: '@inquirer/core': 10.3.2(@types/node@20.17.6) @@ -22890,15 +22792,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/search@3.2.2(@types/node@24.9.2)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.9.2) - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/select@4.4.2(@types/node@20.17.6)': dependencies: '@inquirer/ansi': 1.0.2 @@ -22909,24 +22802,10 @@ snapshots: optionalDependencies: '@types/node': 20.17.6 - '@inquirer/select@4.4.2(@types/node@24.9.2)': - dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.9.2) - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 24.9.2 - '@inquirer/type@3.0.10(@types/node@20.17.6)': optionalDependencies: '@types/node': 20.17.6 - '@inquirer/type@3.0.10(@types/node@24.9.2)': - optionalDependencies: - '@types/node': 24.9.2 - '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -23064,9 +22943,9 @@ snapshots: dependencies: langium: 3.3.1 - '@mintlify/cli@4.0.1090(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/node@24.9.2)(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0)': + '@mintlify/cli@4.0.1090(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/node@20.17.6)(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0)': dependencies: - '@inquirer/prompts': 7.9.0(@types/node@24.9.2) + '@inquirer/prompts': 7.9.0(@types/node@20.17.6) '@mintlify/common': 1.0.835(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0) '@mintlify/link-rot': 3.0.1010(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0) '@mintlify/prebuild': 1.0.977(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0) @@ -23079,7 +22958,7 @@ snapshots: front-matter: 4.0.2 fs-extra: 11.2.0 ink: 6.3.0(@types/react@18.3.12)(react@19.2.3) - inquirer: 12.3.0(@types/node@24.9.2) + inquirer: 12.3.0(@types/node@20.17.6) js-yaml: 4.1.0 mdast-util-mdx-jsx: 3.2.0 open: 8.4.2 @@ -23995,7 +23874,7 @@ snapshots: '@opentelemetry/instrumentation-amqplib@0.50.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: @@ -24004,9 +23883,9 @@ snapshots: '@opentelemetry/instrumentation-amqplib@0.60.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24014,7 +23893,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@types/aws-lambda': 8.10.159 transitivePeerDependencies: - supports-color @@ -24022,9 +23901,9 @@ snapshots: '@opentelemetry/instrumentation-aws-sdk@0.68.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24041,14 +23920,14 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color '@opentelemetry/instrumentation-connect@0.47.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 '@types/connect': 3.4.38 @@ -24058,9 +23937,9 @@ snapshots: '@opentelemetry/instrumentation-connect@0.56.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@types/connect': 3.4.38 transitivePeerDependencies: - supports-color @@ -24069,7 +23948,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24097,7 +23976,7 @@ snapshots: '@opentelemetry/instrumentation-express@0.52.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: @@ -24106,25 +23985,25 @@ snapshots: '@opentelemetry/instrumentation-express@0.61.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color '@opentelemetry/instrumentation-fastify@0.57.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color '@opentelemetry/instrumentation-fs@0.23.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -24132,7 +24011,7 @@ snapshots: '@opentelemetry/instrumentation-fs@0.32.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -24169,14 +24048,14 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color '@opentelemetry/instrumentation-hapi@0.50.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: @@ -24185,9 +24064,9 @@ snapshots: '@opentelemetry/instrumentation-hapi@0.59.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24206,7 +24085,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 forwarded-parse: 2.1.2 transitivePeerDependencies: - supports-color @@ -24225,7 +24104,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) '@opentelemetry/redis-common': 0.38.2 - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24241,7 +24120,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24257,14 +24136,14 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color '@opentelemetry/instrumentation-koa@0.51.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: @@ -24273,9 +24152,9 @@ snapshots: '@opentelemetry/instrumentation-koa@0.61.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24297,7 +24176,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@types/memcached': 2.2.10 transitivePeerDependencies: - supports-color @@ -24314,14 +24193,14 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color '@opentelemetry/instrumentation-mongoose@0.50.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: @@ -24330,9 +24209,9 @@ snapshots: '@opentelemetry/instrumentation-mongoose@0.59.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24349,7 +24228,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -24367,7 +24246,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@types/mysql': 2.15.27 transitivePeerDependencies: - supports-color @@ -24376,7 +24255,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24384,7 +24263,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24393,7 +24272,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/api-logs': 0.213.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24401,7 +24280,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@types/oracledb': 6.5.2 transitivePeerDependencies: - supports-color @@ -24409,7 +24288,7 @@ snapshots: '@opentelemetry/instrumentation-pg@0.55.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) @@ -24421,9 +24300,9 @@ snapshots: '@opentelemetry/instrumentation-pg@0.65.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) '@types/pg': 8.15.6 '@types/pg-pool': 2.0.7 @@ -24434,7 +24313,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/api-logs': 0.213.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -24453,16 +24332,16 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) '@opentelemetry/redis-common': 0.38.2 - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color '@opentelemetry/instrumentation-restify@0.58.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24470,7 +24349,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24501,7 +24380,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@types/tedious': 4.0.14 transitivePeerDependencies: - supports-color @@ -24509,7 +24388,7 @@ snapshots: '@opentelemetry/instrumentation-undici@0.14.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -24517,9 +24396,9 @@ snapshots: '@opentelemetry/instrumentation-undici@0.23.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24553,7 +24432,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/api-logs': 0.207.0 - import-in-the-middle: 2.0.0 + import-in-the-middle: 2.0.6 require-in-the-middle: 8.0.1 transitivePeerDependencies: - supports-color @@ -24672,34 +24551,34 @@ snapshots: '@opentelemetry/resource-detector-alibaba-cloud@0.33.3(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/resource-detector-aws@2.13.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/resource-detector-azure@0.21.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/resource-detector-container@0.8.4(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/resource-detector-gcp@0.48.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) gcp-metadata: 8.1.2 transitivePeerDependencies: - supports-color @@ -24714,7 +24593,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/resources@2.6.0(@opentelemetry/api@1.9.0)': dependencies: @@ -24800,7 +24679,7 @@ snapshots: '@opentelemetry/sdk-metrics': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-node': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -24858,7 +24737,7 @@ snapshots: '@opentelemetry/sql-common@0.41.2(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@orama/orama@3.1.16': {} @@ -28372,38 +28251,38 @@ snapshots: - supports-color - webpack - '@sentry/node-core@10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': + '@sentry/node-core@10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 '@sentry/core': 10.11.0 - '@sentry/opentelemetry': 10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + '@sentry/opentelemetry': 10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) import-in-the-middle: 1.14.2 - '@sentry/node-core@10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': + '@sentry/node-core@10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': dependencies: '@sentry/core': 10.45.0 - '@sentry/opentelemetry': 10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + '@sentry/opentelemetry': 10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) import-in-the-middle: 3.0.0 optionalDependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 '@sentry/node@10.11.0': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-amqplib': 0.50.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-connect': 0.47.0(@opentelemetry/api@1.9.0) @@ -28427,13 +28306,13 @@ snapshots: '@opentelemetry/instrumentation-redis': 0.51.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-tedious': 0.22.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-undici': 0.14.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 '@prisma/instrumentation': 6.14.0(@opentelemetry/api@1.9.0) '@sentry/core': 10.11.0 - '@sentry/node-core': 10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) - '@sentry/opentelemetry': 10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + '@sentry/node-core': 10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + '@sentry/opentelemetry': 10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) import-in-the-middle: 1.14.2 minimatch: 9.0.5 transitivePeerDependencies: @@ -28443,8 +28322,8 @@ snapshots: dependencies: '@fastify/otel': 0.17.1(@opentelemetry/api@1.9.0) '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-amqplib': 0.60.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-connect': 0.56.0(@opentelemetry/api@1.9.0) @@ -28468,33 +28347,33 @@ snapshots: '@opentelemetry/instrumentation-redis': 0.61.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-tedious': 0.32.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-undici': 0.23.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 '@prisma/instrumentation': 7.4.2(@opentelemetry/api@1.9.0) '@sentry/core': 10.45.0 - '@sentry/node-core': 10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) - '@sentry/opentelemetry': 10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + '@sentry/node-core': 10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + '@sentry/opentelemetry': 10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) import-in-the-middle: 3.0.0 transitivePeerDependencies: - supports-color - '@sentry/opentelemetry@10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': + '@sentry/opentelemetry@10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 '@sentry/core': 10.11.0 - '@sentry/opentelemetry@10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.37.0)': + '@sentry/opentelemetry@10.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@sentry/core': 10.11.0 '@sentry/opentelemetry@10.45.0(@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/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': @@ -28506,12 +28385,12 @@ snapshots: '@opentelemetry/semantic-conventions': 1.40.0 '@sentry/core': 10.45.0 - '@sentry/opentelemetry@10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': + '@sentry/opentelemetry@10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.40.0 '@sentry/core': 10.45.0 @@ -28538,13 +28417,13 @@ snapshots: '@sentry/vercel-edge@10.11.0': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) '@sentry/core': 10.11.0 '@sentry/vercel-edge@10.45.0': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.0) '@sentry/core': 10.45.0 '@sentry/webpack-plugin@4.3.0(encoding@0.1.13)(webpack@5.92.0(esbuild@0.24.2))': @@ -29473,21 +29352,21 @@ snapshots: '@stripe/stripe-js@7.7.0': {} - '@supabase/auth-js@2.102.1': + '@supabase/auth-js@2.103.3': dependencies: tslib: 2.8.1 - '@supabase/functions-js@2.102.1': + '@supabase/functions-js@2.103.3': dependencies: tslib: 2.8.1 '@supabase/phoenix@0.4.0': {} - '@supabase/postgrest-js@2.102.1': + '@supabase/postgrest-js@2.103.3': dependencies: tslib: 2.8.1 - '@supabase/realtime-js@2.102.1': + '@supabase/realtime-js@2.103.3': dependencies: '@supabase/phoenix': 0.4.0 '@types/ws': 8.18.1 @@ -29497,23 +29376,23 @@ snapshots: - bufferutil - utf-8-validate - '@supabase/ssr@0.10.0(@supabase/supabase-js@2.102.1)': + '@supabase/ssr@0.10.2(@supabase/supabase-js@2.103.3)': dependencies: - '@supabase/supabase-js': 2.102.1 + '@supabase/supabase-js': 2.103.3 cookie: 1.0.2 - '@supabase/storage-js@2.102.1': + '@supabase/storage-js@2.103.3': dependencies: iceberg-js: 0.8.1 tslib: 2.8.1 - '@supabase/supabase-js@2.102.1': + '@supabase/supabase-js@2.103.3': dependencies: - '@supabase/auth-js': 2.102.1 - '@supabase/functions-js': 2.102.1 - '@supabase/postgrest-js': 2.102.1 - '@supabase/realtime-js': 2.102.1 - '@supabase/storage-js': 2.102.1 + '@supabase/auth-js': 2.103.3 + '@supabase/functions-js': 2.103.3 + '@supabase/postgrest-js': 2.103.3 + '@supabase/realtime-js': 2.103.3 + '@supabase/storage-js': 2.103.3 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -30247,6 +30126,7 @@ snapshots: '@types/node@24.9.2': dependencies: undici-types: 7.16.0 + optional: true '@types/nodemailer@6.4.15': dependencies: @@ -35298,13 +35178,6 @@ snapshots: cjs-module-lexer: 1.4.0 module-details-from-path: 1.0.3 - import-in-the-middle@2.0.0: - dependencies: - acorn: 8.15.0 - acorn-import-attributes: 1.9.5(acorn@8.15.0) - cjs-module-lexer: 1.4.0 - module-details-from-path: 1.0.3 - import-in-the-middle@2.0.6: dependencies: acorn: 8.15.0 @@ -35393,12 +35266,12 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - inquirer@12.3.0(@types/node@24.9.2): + inquirer@12.3.0(@types/node@20.17.6): dependencies: - '@inquirer/core': 10.3.2(@types/node@24.9.2) - '@inquirer/prompts': 7.10.1(@types/node@24.9.2) - '@inquirer/type': 3.0.10(@types/node@24.9.2) - '@types/node': 24.9.2 + '@inquirer/core': 10.3.2(@types/node@20.17.6) + '@inquirer/prompts': 7.10.1(@types/node@20.17.6) + '@inquirer/type': 3.0.10(@types/node@20.17.6) + '@types/node': 20.17.6 ansi-escapes: 4.3.2 mute-stream: 2.0.0 run-async: 3.0.0 @@ -36881,9 +36754,9 @@ snapshots: dependencies: minipass: 7.1.2 - mint@4.2.487(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/node@24.9.2)(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0): + mint@4.2.487(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/node@20.17.6)(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0): dependencies: - '@mintlify/cli': 4.0.1090(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/node@24.9.2)(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0) + '@mintlify/cli': 4.0.1090(@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/node@20.17.6)(@types/react@18.3.12)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(tsx@4.19.3)(typescript@5.9.3)(yaml@2.6.0) transitivePeerDependencies: - '@radix-ui/react-popover' - '@types/node' @@ -39175,7 +39048,7 @@ snapshots: require-in-the-middle@8.0.1: dependencies: debug: 4.4.3 - module-details-from-path: 1.0.3 + module-details-from-path: 1.0.4 transitivePeerDependencies: - supports-color @@ -41046,7 +40919,8 @@ snapshots: undici-types@6.21.0: {} - undici-types@7.16.0: {} + undici-types@7.16.0: + optional: true undici@6.19.8: {} From be13df15cfa7b8d966572dbd674e14a3c7d4703b Mon Sep 17 00:00:00 2001 From: Aadesh Kheria Date: Tue, 28 Apr 2026 11:08:48 -0700 Subject: [PATCH 06/12] bot comments --- .../latest/internal/local-emulator/project/route.tsx | 12 ++++++++++-- .../(outside-dashboard)/projects/page-client.tsx | 2 +- packages/stack-cli/src/commands/init.ts | 7 +++++-- packages/stack-cli/src/index.ts | 4 +--- packages/stack-cli/src/lib/create-project.ts | 8 ++++---- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx b/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx index eb10f66bc4..2f2cc9e297 100644 --- a/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx +++ b/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx @@ -23,6 +23,14 @@ type LocalEmulatorProjectMappingRow = { projectId: string, }; +function deriveDisplayLabel(absoluteFilePath: string): string { + const base = path.basename(absoluteFilePath); + if (base.toLowerCase() === "stack.config.ts") { + return path.basename(path.dirname(absoluteFilePath)) || base; + } + return base; +} + async function assertLocalEmulatorOwnerTeamReadiness() { const internalTenancy = await getSoleTenancyFromProjectBranch("internal", DEFAULT_BRANCH_ID); const internalPrisma = await getPrismaClientForTenancy(internalTenancy); @@ -76,7 +84,7 @@ async function getOrCreateLocalEmulatorProjectId(absoluteFilePath: string): Prom update: {}, create: { id: projectId, - displayName: `Local Emulator: ${path.basename(absoluteFilePath) || "Project"}`, + displayName: `Local Emulator: ${deriveDisplayLabel(absoluteFilePath) || "Project"}`, description: `Local emulator project for ${absoluteFilePath}`, isProductionMode: false, ownerTeamId: LOCAL_EMULATOR_OWNER_TEAM_ID, @@ -327,7 +335,7 @@ export const GET = createSmartRouteHandler({ projects: rows.map((r) => ({ project_id: r.projectId, absolute_file_path: r.absoluteFilePath, - display_name: displayNameById.get(r.projectId) ?? path.basename(r.absoluteFilePath), + display_name: displayNameById.get(r.projectId) ?? deriveDisplayLabel(r.absoluteFilePath), })), }, }; diff --git a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx index af7c9e24fe..e977468900 100644 --- a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx @@ -134,7 +134,7 @@ export default function PageClient() { ); setRecentConfigProjects(parsed); } catch { - // best-effort — dialog still works without the recent list + if (!cancelled) setRecentConfigProjects([]); } }); return () => { diff --git a/packages/stack-cli/src/commands/init.ts b/packages/stack-cli/src/commands/init.ts index c989a81bfd..b612ba04b1 100644 --- a/packages/stack-cli/src/commands/init.ts +++ b/packages/stack-cli/src/commands/init.ts @@ -23,6 +23,7 @@ type InitOptions = { selectProjectId?: string, outputDir?: string, agent?: boolean, + displayName?: string, }; export function registerInitCommand(program: Command) { @@ -35,8 +36,9 @@ export function registerInitCommand(program: Command) { .option("--select-project-id ", "Project ID to link (for link-cloud mode)") .option("--output-dir ", "Directory to write output files (defaults to cwd)") .option("--no-agent", "Skip Claude agent and print setup instructions instead") + .option("--display-name ", "Project display name (used by create-cloud mode)") .action(async (opts: InitOptions) => { - const hasFlags = opts.mode != null; + const hasFlags = opts.mode != null || opts.configFile != null || opts.selectProjectId != null; if (!hasFlags && isNonInteractiveEnv()) { throw new CliError("stack init requires an interactive terminal. Use --mode flag for non-interactive usage."); @@ -261,11 +263,12 @@ async function writeProjectKeysToEnv( } } -async function handleCreateCloud(flags: Record, _opts: InitOptions, outputDir: string): Promise<{ configPath?: string, projectId?: string }> { +async function handleCreateCloud(flags: Record, opts: InitOptions, outputDir: string): Promise<{ configPath?: string, projectId?: string }> { const sessionAuth = await ensureLoggedInSession(flags); const user = await getInternalUser(sessionAuth); const newProject = await createProjectInteractively(user, { + displayName: opts.displayName, defaultDisplayName: path.basename(outputDir), }); console.log(`\nCreated project: ${newProject.displayName} (${newProject.id})\n`); diff --git a/packages/stack-cli/src/index.ts b/packages/stack-cli/src/index.ts index 1fbffa00ac..a7d16095df 100644 --- a/packages/stack-cli/src/index.ts +++ b/packages/stack-cli/src/index.ts @@ -47,9 +47,7 @@ async function main() { console.error(`Error: ${err.message}`); process.exit(1); } - reportUnexpectedError(err); - await flushSentry(); - throw err; + await handleFatal(err); } } diff --git a/packages/stack-cli/src/lib/create-project.ts b/packages/stack-cli/src/lib/create-project.ts index 686a2c96ba..448d6fc909 100644 --- a/packages/stack-cli/src/lib/create-project.ts +++ b/packages/stack-cli/src/lib/create-project.ts @@ -12,16 +12,16 @@ export async function createProjectInteractively( user: CurrentInternalUser, opts: CreateProjectOptions = {}, ) { - let displayName = opts.displayName; + let displayName = opts.displayName?.trim(); if (!displayName) { if (isNonInteractiveEnv()) { throw new CliError("--display-name is required in non-interactive environments (CI)."); } - displayName = await input({ + displayName = (await input({ message: "Project display name:", default: opts.defaultDisplayName, validate: (v) => v.trim().length > 0 || "Display name cannot be empty.", - }); + })).trim(); } const teams = await user.listTeams(); @@ -30,7 +30,7 @@ export async function createProjectInteractively( } return await user.createProject({ - displayName: displayName.trim(), + displayName, teamId: teams[0].id, }); } From 9dc4751382ff454aad5fa7983118c70374d62d46 Mon Sep 17 00:00:00 2001 From: Aadesh Kheria Date: Tue, 28 Apr 2026 12:41:52 -0700 Subject: [PATCH 07/12] bot comments --- .../internal/local-emulator/project/route.tsx | 10 ++++- .../projects/page-client.tsx | 39 ++++++++++++----- packages/stack-cli/src/commands/init.ts | 42 +++++++++---------- packages/stack-cli/src/commands/project.ts | 4 +- packages/stack-cli/src/lib/create-project.ts | 5 ++- 5 files changed, 64 insertions(+), 36 deletions(-) diff --git a/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx b/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx index 2f2cc9e297..9834455aa7 100644 --- a/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx +++ b/apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx @@ -219,8 +219,14 @@ export const POST = createSmartRouteHandler({ if (!isLocalEmulatorEnabled()) { throw new StatusError(StatusError.BadRequest, LOCAL_EMULATOR_ONLY_ENDPOINT_MESSAGE); } - if (!path.isAbsolute(req.body.absolute_file_path)) { - throw new StatusError(StatusError.BadRequest, "absolute_file_path must be an absolute path."); + if (!path.posix.isAbsolute(req.body.absolute_file_path)) { + const looksWindows = path.win32.isAbsolute(req.body.absolute_file_path); + throw new StatusError( + StatusError.BadRequest, + looksWindows + ? "absolute_file_path must be a POSIX absolute path. The local emulator runs in a Linux VM and does not accept Windows-style paths. Use the in-VM path or run the emulator from WSL." + : "absolute_file_path must be an absolute path.", + ); } const inputPath = path.resolve(req.body.absolute_file_path); diff --git a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx index e977468900..2ac505a238 100644 --- a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx @@ -66,6 +66,7 @@ export default function PageClient() { const [absoluteConfigFilePath, setAbsoluteConfigFilePath] = useState(""); const [openingConfigFile, setOpeningConfigFile] = useState(false); const [recentConfigProjects, setRecentConfigProjects] = useState>([]); + const [recentConfigProjectsError, setRecentConfigProjectsError] = useState(false); const [projectStatuses, setProjectStatuses] = useState>(new Map()); const [loadingProjectStatuses, setLoadingProjectStatuses] = useState(true); const router = useRouter(); @@ -122,19 +123,29 @@ export default function PageClient() { useEffect(() => { if (!openConfigFileDialog || !isLocalEmulator) return; let cancelled = false; + setRecentConfigProjectsError(false); runAsynchronously(async () => { try { const response = await appInternals.sendRequest("/internal/local-emulator/project", { method: "GET" }, "client"); - if (!response.ok) return; + if (!response.ok) { + if (!cancelled) { + setRecentConfigProjects([]); + setRecentConfigProjectsError(true); + } + return; + } const body = await response.json() as { projects?: Array<{ project_id?: string, absolute_file_path?: string, display_name?: string }> }; - if (cancelled || !body.projects) return; - const parsed = body.projects + if (cancelled) return; + const parsed = (body.projects ?? []) .filter((p): p is { project_id: string, absolute_file_path: string, display_name: string } => typeof p.project_id === "string" && typeof p.absolute_file_path === "string" && typeof p.display_name === "string", ); setRecentConfigProjects(parsed); } catch { - if (!cancelled) setRecentConfigProjects([]); + if (!cancelled) { + setRecentConfigProjects([]); + setRecentConfigProjectsError(true); + } } }); return () => { @@ -148,7 +159,7 @@ export default function PageClient() { return "Tip: in Finder, right-click the file → hold ⌥ Option → Copy as Pathname, then paste here."; } if (/Win/i.test(p)) { - return "Tip: in File Explorer, Shift + right-click the file → Copy as path, then paste here."; + return "Note: the emulator runs in a Linux VM and needs a POSIX path. From WSL, run `wslpath -a stack.config.ts` (or `realpath stack.config.ts`) and paste that here."; } return "Tip: from your project folder, run `realpath stack.config.ts` in a terminal."; }, []); @@ -160,11 +171,14 @@ export default function PageClient() { return; } - const hasUnixAbsolutePath = trimmedPath.startsWith("/"); - const hasWindowsAbsolutePath = /^[a-zA-Z]:[\\/]/.test(trimmedPath); - const hasWindowsUncPath = trimmedPath.startsWith("\\\\"); - if (!hasUnixAbsolutePath && !hasWindowsAbsolutePath && !hasWindowsUncPath) { - toast({ description: "The path must be absolute (e.g. /Users/you/project or /Users/you/project/stack.config.ts).", variant: "destructive" }); + if (!trimmedPath.startsWith("/")) { + const looksWindows = /^[a-zA-Z]:[\\/]/.test(trimmedPath) || trimmedPath.startsWith("\\\\"); + toast({ + description: looksWindows + ? "The local emulator runs in a Linux VM and only accepts POSIX paths (e.g. /Users/you/project). Windows paths aren't supported — use WSL or the in-VM path." + : "The path must be absolute (e.g. /Users/you/project or /Users/you/project/stack.config.ts).", + variant: "destructive", + }); return; } @@ -335,6 +349,11 @@ export default function PageClient() { )} + {recentConfigProjectsError && recentConfigProjects.length === 0 && ( + + Couldn't load recent projects. Paste a path below to continue. + + )} ", "Project display name (used by create-cloud mode)") .action(async (opts: InitOptions) => { + if (opts.mode != null && !VALID_INIT_MODES.includes(opts.mode)) { + throw new CliError(`Invalid --mode: ${opts.mode}. Expected one of: ${VALID_INIT_MODES.join(", ")}.`); + } const hasFlags = opts.mode != null || opts.configFile != null || opts.selectProjectId != null; if (!hasFlags && isNonInteractiveEnv()) { @@ -87,7 +93,7 @@ async function runInit(program: Command, opts: InitOptions) { let configPath: string | undefined; let projectId: string | undefined; - if (mode === "link" || mode === "link-config" || mode === "link-cloud") { + if (mode === "link-config" || mode === "link-cloud") { const result = await handleLink(flags, opts, outputDir, mode); configPath = result.configPath; projectId = result.projectId; @@ -143,24 +149,8 @@ function printNextSteps(args: { mode: string, projectId?: string, dashboardUrl: console.log(""); } -async function handleLink(flags: Record, opts: InitOptions, outputDir: string, resolvedMode?: string): Promise<{ configPath?: string, projectId?: string }> { - let source: "config-file" | "cloud"; - - if (resolvedMode === "link-config" || opts.mode === "link-config") { - source = "config-file"; - } else if (resolvedMode === "link-cloud" || opts.mode === "link-cloud") { - source = "cloud"; - } else { - source = await select({ - message: "How would you like to link your project?", - choices: [ - { name: "Link from config file", value: "config-file" as const }, - { name: "Link from app.stack-auth.com", value: "cloud" as const }, - ], - }); - } - - if (source === "config-file") { +async function handleLink(flags: Record, opts: InitOptions, outputDir: string, resolvedMode: "link-config" | "link-cloud"): Promise<{ configPath?: string, projectId?: string }> { + if (resolvedMode === "link-config") { return await handleLinkFromConfigFile(opts); } return await handleLinkFromCloud(flags, opts, outputDir); @@ -267,9 +257,11 @@ async function handleCreateCloud(flags: Record, opts: InitOptio const sessionAuth = await ensureLoggedInSession(flags); const user = await getInternalUser(sessionAuth); + const { dashboardUrl } = resolveLoginConfig(flags as { projectId?: string }); const newProject = await createProjectInteractively(user, { displayName: opts.displayName, defaultDisplayName: path.basename(outputDir), + dashboardUrl, }); console.log(`\nCreated project: ${newProject.displayName} (${newProject.id})\n`); @@ -284,8 +276,11 @@ async function handleLinkFromCloud(flags: Record, opts: InitOpt let autoCreatedProjectId: string | null = null; if (projects.length === 0) { + if (opts.selectProjectId) { + throw new CliError(`Project '${opts.selectProjectId}' not found among your owned projects. Check the ID or omit --select-project-id to create a new project interactively.`); + } if (isNonInteractiveEnv()) { - throw new CliError("No projects found. Run `stack project create --display-name ` first, or set --select-project-id."); + throw new CliError("No projects found. Run `stack project create --display-name ` first."); } const shouldCreate = await confirm({ @@ -294,11 +289,14 @@ async function handleLinkFromCloud(flags: Record, opts: InitOpt }); if (!shouldCreate) { - throw new CliError("You don't own any projects. Create one at app.stack-auth.com or re-run and choose to create one."); + const { dashboardUrl } = resolveLoginConfig(flags as { projectId?: string }); + throw new CliError(`You don't own any projects. Create one at ${dashboardUrl} or re-run and choose to create one.`); } + const { dashboardUrl } = resolveLoginConfig(flags as { projectId?: string }); const newProject = await createProjectInteractively(user, { defaultDisplayName: path.basename(outputDir), + dashboardUrl, }); console.log(`\nCreated project: ${newProject.displayName} (${newProject.id})\n`); projects = [newProject]; diff --git a/packages/stack-cli/src/commands/project.ts b/packages/stack-cli/src/commands/project.ts index 2b1f49ff16..d67061cc6b 100644 --- a/packages/stack-cli/src/commands/project.ts +++ b/packages/stack-cli/src/commands/project.ts @@ -1,5 +1,5 @@ import { Command } from "commander"; -import { resolveSessionAuth } from "../lib/auth.js"; +import { resolveLoginConfig, resolveSessionAuth } from "../lib/auth.js"; import { getInternalUser } from "../lib/app.js"; import { createProjectInteractively } from "../lib/create-project.js"; @@ -38,9 +38,11 @@ export function registerProjectCommand(program: Command) { const flags = program.opts(); const auth = resolveSessionAuth(flags); const user = await getInternalUser(auth); + const { dashboardUrl } = resolveLoginConfig(flags as { projectId?: string }); const newProject = await createProjectInteractively(user, { displayName: opts.displayName, + dashboardUrl, }); if (program.opts().json) { diff --git a/packages/stack-cli/src/lib/create-project.ts b/packages/stack-cli/src/lib/create-project.ts index 448d6fc909..05e610be24 100644 --- a/packages/stack-cli/src/lib/create-project.ts +++ b/packages/stack-cli/src/lib/create-project.ts @@ -1,11 +1,13 @@ import { input } from "@inquirer/prompts"; import type { CurrentInternalUser } from "@stackframe/js"; +import { DEFAULT_DASHBOARD_URL } from "./auth.js"; import { CliError } from "./errors.js"; import { isNonInteractiveEnv } from "./interactive.js"; type CreateProjectOptions = { displayName?: string, defaultDisplayName?: string, + dashboardUrl?: string, }; export async function createProjectInteractively( @@ -26,7 +28,8 @@ export async function createProjectInteractively( const teams = await user.listTeams(); if (teams.length === 0) { - throw new CliError("No teams found on your account. Create a team at app.stack-auth.com first."); + const dashboardUrl = opts.dashboardUrl ?? DEFAULT_DASHBOARD_URL; + throw new CliError(`No teams found on your account. Create a team at ${dashboardUrl} first.`); } return await user.createProject({ From e09914e18b2d73f1f22e2b11051dc2903db3cf1e Mon Sep 17 00:00:00 2001 From: Aadesh Kheria Date: Tue, 28 Apr 2026 13:31:36 -0700 Subject: [PATCH 08/12] bot comment --- .../projects/page-client.tsx | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx index 2ac505a238..bae0c38dfb 100644 --- a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx @@ -134,12 +134,23 @@ export default function PageClient() { } return; } - const body = await response.json() as { projects?: Array<{ project_id?: string, absolute_file_path?: string, display_name?: string }> }; + const body = await response.json() as { projects?: unknown }; if (cancelled) return; - const parsed = (body.projects ?? []) - .filter((p): p is { project_id: string, absolute_file_path: string, display_name: string } => - typeof p.project_id === "string" && typeof p.absolute_file_path === "string" && typeof p.display_name === "string", - ); + if (!Array.isArray(body.projects)) { + throw new Error("Invalid recent-projects payload"); + } + const parsed = body.projects.map((p: unknown): { project_id: string, absolute_file_path: string, display_name: string } => { + if ( + !p || typeof p !== "object" + || typeof (p as Record).project_id !== "string" + || typeof (p as Record).absolute_file_path !== "string" + || typeof (p as Record).display_name !== "string" + ) { + throw new Error("Invalid recent-projects payload"); + } + const r = p as Record; + return { project_id: r.project_id, absolute_file_path: r.absolute_file_path, display_name: r.display_name }; + }); setRecentConfigProjects(parsed); } catch { if (!cancelled) { From e22fc33fea62bee3f9142724c8c8ceafad5cdacc Mon Sep 17 00:00:00 2001 From: Aadesh Kheria Date: Tue, 28 Apr 2026 13:48:02 -0700 Subject: [PATCH 09/12] bot comments --- packages/stack-cli/src/commands/init.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/stack-cli/src/commands/init.ts b/packages/stack-cli/src/commands/init.ts index 4647c3ed08..1a7edcf1b9 100644 --- a/packages/stack-cli/src/commands/init.ts +++ b/packages/stack-cli/src/commands/init.ts @@ -142,7 +142,7 @@ function printNextSteps(args: { mode: string, projectId?: string, dashboardUrl: console.log(" Local dashboard: http://localhost:26700"); } else if (args.projectId) { console.log(" • Manage this project in the dashboard:"); - console.log(` ${args.dashboardUrl}/projects/${args.projectId}`); + console.log(` ${args.dashboardUrl}/projects/${encodeURIComponent(args.projectId)}`); } console.log(" • Docs: https://docs.stack-auth.com"); @@ -322,7 +322,8 @@ async function handleLinkFromCloud(flags: Record, opts: InitOpt }); } - const project = projects.find((p) => p.id === projectId)!; + const project = projects.find((p) => p.id === projectId) + ?? throwErr(`Project not found: ${projectId}`); await writeProjectKeysToEnv(project, outputDir); return { projectId }; } From 21b0bbf900b553a539a53d646f073975cf840ad5 Mon Sep 17 00:00:00 2001 From: Aadesh Kheria Date: Wed, 29 Apr 2026 12:33:16 -0700 Subject: [PATCH 10/12] comment fix --- packages/stack-cli/src/index.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/stack-cli/src/index.ts b/packages/stack-cli/src/index.ts index a7d16095df..e3121c0e6f 100644 --- a/packages/stack-cli/src/index.ts +++ b/packages/stack-cli/src/index.ts @@ -62,14 +62,5 @@ async function handleFatal(err: unknown): Promise { process.exit(1); } -process.on("uncaughtException", (err) => { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - handleFatal(err); -}); -process.on("unhandledRejection", (reason) => { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - handleFatal(reason); -}); - // eslint-disable-next-line @typescript-eslint/no-floating-promises main(); From 921f1bdc73ebdd91e038de0baa13d9ec6545f11e Mon Sep 17 00:00:00 2001 From: Aadesh Kheria Date: Mon, 4 May 2026 11:11:59 -0700 Subject: [PATCH 11/12] comment fix --- packages/stack-cli/src/index.ts | 20 +++++++------------ packages/stack-cli/src/lib/sentry.ts | 30 ++++++++-------------------- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/packages/stack-cli/src/index.ts b/packages/stack-cli/src/index.ts index e3121c0e6f..12a3688791 100644 --- a/packages/stack-cli/src/index.ts +++ b/packages/stack-cli/src/index.ts @@ -1,6 +1,8 @@ -import { initSentry, reportUnexpectedError, flushSentry } from "./lib/sentry.js"; +import { initSentry } from "./lib/sentry.js"; initSentry(); +import * as Sentry from "@sentry/node"; +import { captureError } from "@stackframe/stack-shared/dist/utils/errors"; import { Command } from "commander"; import { readFileSync } from "fs"; import { fileURLToPath } from "url"; @@ -47,20 +49,12 @@ async function main() { console.error(`Error: ${err.message}`); process.exit(1); } - await handleFatal(err); + captureError("stack-cli-fatal", err); + await Sentry.flush(2000); + console.error(err); + process.exit(1); } } -async function handleFatal(err: unknown): Promise { - try { - reportUnexpectedError(err); - await flushSentry(); - } catch { - // best-effort - } - console.error(err); - process.exit(1); -} - // eslint-disable-next-line @typescript-eslint/no-floating-promises main(); diff --git a/packages/stack-cli/src/lib/sentry.ts b/packages/stack-cli/src/lib/sentry.ts index 662536acd3..31f4ab96d6 100644 --- a/packages/stack-cli/src/lib/sentry.ts +++ b/packages/stack-cli/src/lib/sentry.ts @@ -1,4 +1,7 @@ import * as Sentry from "@sentry/node"; +import { getEnvVariable, getNodeEnvironment } from "@stackframe/stack-shared/dist/utils/env"; +import { registerErrorSink } from "@stackframe/stack-shared/dist/utils/errors"; +import { ignoreUnhandledRejection } from "@stackframe/stack-shared/dist/utils/promises"; import { sentryBaseConfig } from "@stackframe/stack-shared/dist/utils/sentry"; import { nicify } from "@stackframe/stack-shared/dist/utils/strings"; import { readFileSync } from "fs"; @@ -9,8 +12,6 @@ import { fileURLToPath } from "url"; // Replaced at build time by tsdown `define`. Empty = not configured (dev/unbuilt). declare const __STACK_CLI_SENTRY_DSN__: string; -let initialized = false; - function readPackageVersion(): string | undefined { try { const here = dirname(fileURLToPath(import.meta.url)); @@ -56,17 +57,13 @@ function scrubValue(value: unknown, key?: string): unknown { } export function initSentry() { - if (initialized) return; - if (process.env.NODE_ENV === "development" || process.env.CI) return; - const dsn = typeof __STACK_CLI_SENTRY_DSN__ === "string" ? __STACK_CLI_SENTRY_DSN__ : ""; - if (!dsn) return; - const version = readPackageVersion(); Sentry.init({ ...sentryBaseConfig, dsn, + enabled: !!dsn && getNodeEnvironment() !== "development" && !getEnvVariable("CI", ""), release: version ? `stack-cli@${version}` : undefined, environment: "production", sendDefaultPii: false, @@ -92,19 +89,8 @@ export function initSentry() { }, }); - initialized = true; -} - -export function reportUnexpectedError(err: unknown) { - if (!initialized) return; - Sentry.captureException(err); -} - -export async function flushSentry() { - if (!initialized) return; - try { - await Sentry.flush(2000); - } catch { - // best-effort - } + registerErrorSink((location, error) => { + Sentry.captureException(error, { extra: { location } }); + ignoreUnhandledRejection(Sentry.flush(2000)); + }); } From c79d3b339737423ef19acbc8e4796e54dc4f966a Mon Sep 17 00:00:00 2001 From: Aadesh Kheria Date: Mon, 4 May 2026 12:57:17 -0700 Subject: [PATCH 12/12] duplicate import fix --- packages/stack-cli/src/commands/project.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/stack-cli/src/commands/project.ts b/packages/stack-cli/src/commands/project.ts index 7650c2596c..1dcad88541 100644 --- a/packages/stack-cli/src/commands/project.ts +++ b/packages/stack-cli/src/commands/project.ts @@ -1,7 +1,6 @@ import { Command } from "commander"; -import { resolveLoginConfig, resolveSessionAuth } from "../lib/auth.js"; import { getInternalUser } from "../lib/app.js"; -import { createProjectInteractively } from "../lib/create-project.js"; +import { resolveLoginConfig, resolveSessionAuth } from "../lib/auth.js"; import { createProjectInteractively } from "../lib/create-project.js"; export function registerProjectCommand(program: Command) {