stack-cli: cloud/local init flow, auto-create on empty projects, post-setup next-steps (#1383)

### Summary

Reworks `stack init` UX, adds Sentry error reporting to the CLI,
polishes the emulator start flow, and overhauls the local-emulator
dashboard's "Open config file" dialog.

#### `stack init` flow
- **New top-level flow.** Drops the old "link existing vs. create new
local" fork. `init` now asks *where* to create the project — "Stack Auth
Cloud" or "Local". Adds a new `create-cloud` mode that logs the user in,
creates a cloud project, mints keys, and writes `.env` — no round-trip
through the dashboard.
- **Conditional emulator-install warning.** The "Local" choice label
only shows "(requires local emulator installation, ~1.3gb storage
required)" when the QEMU image isn't already on disk; otherwise it shows
"(emulator already installed)". Driven by a new
`isEmulatorImageInstalled()` helper in `commands/emulator.ts`.
- **Auto-create on zero-projects.** When the link-from-cloud path hits
an empty project list, the CLI now prompts *"You don't have any Stack
Auth projects yet. Would you like to create one?"* and, on yes, runs the
same flow as `stack project create`. Skips the pointless "select a
project" prompt when we just created one.
- **MCP-server notice.** Before invoking the coding agent, the CLI
announces that it's also registering the Stack Auth MCP server
(`mcp.stack-auth.com`) so the agent can answer Stack-specific questions
going forward.
- **Local-emulator env header.** When `writeProjectKeysToEnv` runs in
`local` mode it writes a 3-line comment header above the keys explaining
they're emulator-only and only valid while the emulator is running.
- **"What's next" footer.** After setup finishes, prints a short
orientation block: where the sign-up/sign-in routes live
(`/handler/sign-up`, `/handler/sign-in`), how to start the local
emulator (for `create` mode), a dashboard deep link for cloud projects
(respects `STACK_DASHBOARD_URL`), and a docs link.

#### Sentry error reporting (`lib/sentry.ts`, `index.ts`,
`tsdown.config.ts`)
- New `lib/sentry.ts` initializes `@sentry/node` with PII scrubbing
(Stack key prefixes, JWTs, home-dir paths, sensitive field names like
`token`/`secret`/`password`/`dsn`).
- DSN is baked at build time via a tsdown `define` sentinel
(`__STACK_CLI_SENTRY_DSN__`) — no DSN in source, no runtime env-var
dependency for installed users. CI sets `STACK_CLI_SENTRY_DSN_BUILD`
before `pnpm build`.
- Disabled when `NODE_ENV=development` or `CI`. No user opt-out.
- Wired into `main()`'s catch (only for unexpected errors —
`CliError`/`AuthError` still print and exit cleanly) plus
`uncaughtException` and `unhandledRejection` handlers via a
`handleFatal` helper.

#### `stack emulator start` welcome
- After a fresh start (not when reusing a running VM, not when
`--config-file` keeps stdout JSON-only), prints a short "Emulator is up"
block with service URLs (dashboard / backend / inbucket) and common
commands (`status`, `stop`, `reset`, `run`).

#### Local-emulator dashboard "Open config file" dialog
The dialog at `http://localhost:26700` (when no project is loaded) used
to be a single text input asking for an absolute path, with no
explanation of where that path comes from.

**Backend**
(`apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx`):
- POST is now tolerant of directory paths or paths that don't end in
`.ts`/`.js`/`.mjs` — it appends `stack.config.ts` and creates the file
if missing (`writeConfigToFile` mkdir's parents). Lets users paste a
project folder instead of hunting for the config file.
- New GET endpoint returns up to 20 most-recent `LocalEmulatorProject`
rows joined with their display names, sorted by `updatedAt` desc. Same
`isLocalEmulatorEnabled()` + client-auth gating as POST.

**Dashboard**
(`apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx`):
- Title changed to "Open your Stack Auth project". Description now
explicitly ties the file to `stack init`: *"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."*
- Added: *"Don't have one yet? Paste your project folder path instead
and we'll create stack.config.ts for you."*
- Recent-projects list (clickable rows that prefill the input) fetched
from the new GET endpoint when the dialog opens.
- OS-specific copy-path tip below the input (macOS ⌥-Copy as Pathname,
Windows Shift+RC Copy as path, Linux `realpath`).
- "Open project" button is disabled when the input is empty.
- All error paths (empty input, non-absolute path, server errors,
exceptions) surface via destructive toasts instead of throwing.

Why no native file picker: browsers do not expose absolute filesystem
paths from `<input type="file">`, drag-and-drop, or the File System
Access API. The backend requires an absolute path, so a Finder-style
picker isn't possible from a web page. The recent list + OS tips are the
workaround.

### Goal

The previous `init` flow dead-ended new users: if you had no project you
got an error telling you to go create one in the dashboard and come
back. The happy path also forced a choice between "link existing" and
"create local emulator" — not the question most users are trying to
answer. The emulator dashboard's open-project dialog had similar
friction: an unexplained path field with no recall of previously-opened
projects. And the CLI silently swallowed unexpected errors with no
telemetry. This branch makes the first-run path work end-to-end from the
terminal, gives the emulator dashboard a usable open-project surface,
and turns CLI crashes into actionable bug reports.

### How to review

- Start with `packages/stack-cli/src/commands/init.ts` — the whole
user-facing flow lives in `runInit`. Mode dispatch at the top,
`handleCreateCloud` is the new cloud branch, `printNextSteps` is the
footer, the MCP notice prints right before `runClaudeAgent`.
- `packages/stack-cli/src/lib/sentry.ts` is small and self-contained;
the sentinel-replacement contract is in `tsdown.config.ts`'s `define`
block. Confirm `dist/index.js` contains zero `__STACK_CLI_SENTRY_DSN__`
occurrences after a build with the env var unset, and the actual DSN
host after a build with it set.
- `packages/stack-cli/src/commands/emulator.ts` —
`printEmulatorWelcome()` is the welcome block;
`isEmulatorImageInstalled()` is the new exported helper used by
`init.ts`.
-
`apps/backend/src/app/api/latest/internal/local-emulator/project/route.tsx`
— the directory-tolerance branch is in the POST handler around the
`looksLikeConfigFile` check; the GET handler is appended at the bottom.
-
`apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/projects/page-client.tsx`
— dialog markup, recent-list fetch effect, `pathCopyTip` memo, and the
toast-based error handling in `handleOpenConfigFile`.
- Non-interactive (CI) paths stay strict: empty-project list still
errors with a pointer to `stack project create --display-name`. No
surprise project creation in CI.
- No tests. The CLI has no harness for the interactive flow;
verification is manual.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Recent local emulator projects listed in the config dialog for quick
selection.
* New CLI create-cloud mode and --display-name flag; interactive cloud
project creation and clearer next steps.
* Emulator start shows a welcome banner with service URLs when a new
instance starts.

* **Improvements**
* Config dialog UX, validation, error-toasting, and platform-aware copy
refined; “Open project” disabled for empty/invalid paths.
* CLI: centralized interactive project creation and improved fatal error
handling.

* **Chores**
  * Sentry added and initialized for CLI error reporting.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Bilal Godil <bg2002@gmail.com>
This commit is contained in:
aadesh18 2026-05-08 10:47:49 -07:00 committed by GitHub
parent 6eaf49237f
commit acc646cb0b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 665 additions and 171 deletions

View File

@ -4,10 +4,11 @@ import {
LOCAL_EMULATOR_ADMIN_USER_ID,
LOCAL_EMULATOR_ONLY_ENDPOINT_MESSAGE,
LOCAL_EMULATOR_OWNER_TEAM_ID,
isLocalEmulatorOnboardingEnabledInConfig,
isLocalEmulatorEnabled,
isLocalEmulatorOnboardingEnabledInConfig,
readConfigFromFile,
resolveEmulatorPath,
writeConfigToFile,
writeShowOnboardingConfigToFile,
} from "@/lib/local-emulator";
import { DEFAULT_BRANCH_ID, getSoleTenancyFromProjectBranch } from "@/lib/tenancies";
@ -18,6 +19,7 @@ import {
projectOnboardingStatusSchema,
projectOnboardingStatusValues,
type ProjectOnboardingStatus,
yupArray,
yupBoolean,
yupNumber,
yupObject,
@ -37,6 +39,14 @@ function isProjectOnboardingStatus(value: string): value is ProjectOnboardingSta
return projectOnboardingStatusValues.some((status) => status === value);
}
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);
@ -90,7 +100,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,
@ -287,14 +297,30 @@ 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 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;
}
// Validate file exists before creating a project
const looksLikeConfigFile = /\.(ts|js|mjs)$/i.test(inputPath);
const absoluteFilePath = (inputStat?.isDirectory() || (!inputStat && !looksLikeConfigFile))
? path.join(inputPath, "stack.config.ts")
: inputPath;
const resolvedFilePath = resolveEmulatorPath(absoluteFilePath);
let fileExists: boolean;
try {
await fs.access(resolvedFilePath);
@ -303,7 +329,7 @@ export const POST = createSmartRouteHandler({
fileExists = false;
}
if (!fileExists) {
throw new StatusError(StatusError.BadRequest, `Config file not found: ${absoluteFilePath}`);
await writeConfigToFile(absoluteFilePath, {});
}
const fileContent = await fs.readFile(resolvedFilePath, "utf-8");
@ -335,3 +361,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<LocalEmulatorProjectListRow[]>(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) ?? deriveDisplayLabel(r.absoluteFilePath),
})),
},
};
},
});

View File

@ -66,6 +66,8 @@ export default function PageClient() {
const [openConfigFileDialog, setOpenConfigFileDialog] = useState(false);
const [absoluteConfigFilePath, setAbsoluteConfigFilePath] = useState("");
const [openingConfigFile, setOpeningConfigFile] = useState(false);
const [recentConfigProjects, setRecentConfigProjects] = useState<Array<{ project_id: string, absolute_file_path: string, display_name: string }>>([]);
const [recentConfigProjectsError, setRecentConfigProjectsError] = useState(false);
const [projectStatuses, setProjectStatuses] = useState<Map<string, ProjectOnboardingStatus>>(new Map());
const [loadingProjectStatuses, setLoadingProjectStatuses] = useState(true);
const [projectDau, setProjectDau] = useState<Map<string, { date: string, activity: number }[]>>(new Map());
@ -157,17 +159,77 @@ export default function PageClient() {
};
}, [appInternals, rawProjects.length]);
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) {
if (!cancelled) {
setRecentConfigProjects([]);
setRecentConfigProjectsError(true);
}
return;
}
const body = await response.json() as { projects?: unknown };
if (cancelled) return;
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<string, unknown>).project_id !== "string"
|| typeof (p as Record<string, unknown>).absolute_file_path !== "string"
|| typeof (p as Record<string, unknown>).display_name !== "string"
) {
throw new Error("Invalid recent-projects payload");
}
const r = p as Record<string, string>;
return { project_id: r.project_id, absolute_file_path: r.absolute_file_path, display_name: r.display_name };
});
setRecentConfigProjects(parsed);
} catch {
if (!cancelled) {
setRecentConfigProjects([]);
setRecentConfigProjectsError(true);
}
}
});
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 "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.";
}, []);
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.");
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;
}
setOpeningConfigFile(true);
@ -188,19 +250,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 (
@ -209,7 +272,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;
}
const onboardingStatus = "onboarding_status" in responseBody
? responseBody.onboarding_status
@ -232,6 +296,11 @@ export default function PageClient() {
router.push(`/new-project?project_id=${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);
}
@ -302,7 +371,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"}
</Button>
</div>
</div>
@ -318,24 +387,57 @@ export default function PageClient() {
>
<DialogContent className="sm:max-w-[520px]">
<DialogHeader>
<DialogTitle>Open config file</DialogTitle>
<DialogTitle>Open your Stack Auth project</DialogTitle>
</DialogHeader>
<div className="space-y-3">
<Typography variant="secondary">
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 <code>stack.config.ts</code> in your project. If you just ran <code>stack init</code>, it was created at the root of that project.
</Typography>
<Typography variant="secondary" className="text-xs">
Don&apos;t have one yet? Paste your project folder path instead and we&apos;ll create <code>stack.config.ts</code> for you.
</Typography>
{recentConfigProjects.length > 0 && (
<div className="space-y-1">
<Typography variant="secondary" className="text-xs uppercase tracking-wide">Recent</Typography>
<div className="max-h-40 overflow-y-auto rounded-md border">
{recentConfigProjects.map((p) => (
<button
key={p.project_id}
type="button"
className="block w-full truncate px-3 py-2 text-left text-sm hover:bg-muted"
onClick={() => setAbsoluteConfigFilePath(p.absolute_file_path)}
title={p.absolute_file_path}
>
{p.absolute_file_path}
</button>
))}
</div>
</div>
)}
{recentConfigProjectsError && recentConfigProjects.length === 0 && (
<Typography variant="secondary" className="text-xs text-destructive">
Couldn&apos;t load recent projects. Paste a path below to continue.
</Typography>
)}
<Input
autoFocus
placeholder="/Users/you/project/stack.config.ts"
value={absoluteConfigFilePath}
onChange={(event) => setAbsoluteConfigFilePath(event.target.value)}
/>
<Typography variant="secondary" className="text-xs">
{pathCopyTip}
</Typography>
</div>
<DialogFooter className="pt-2">
<Button variant="outline" onClick={() => setOpenConfigFileDialog(false)} disabled={openingConfigFile}>
Cancel
</Button>
<Button onClick={handleOpenConfigFile} loading={openingConfigFile}>
<Button
onClick={handleOpenConfigFile}
loading={openingConfigFile}
disabled={absoluteConfigFilePath.trim().length === 0}
>
Open project
</Button>
</DialogFooter>

View File

@ -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",

View File

@ -312,6 +312,38 @@ async function startEmulator(arch: "arm64" | "amd64"): Promise<void> {
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 <cmd> Start the emulator, run <cmd>, 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;
@ -744,10 +776,12 @@ 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) {
@ -759,6 +793,11 @@ export function registerEmulatorCommand(program: Command) {
publishable_client_key: creds.publishable_client_key,
secret_server_key: creds.secret_server_key,
}, null, 2));
return;
}
if (freshlyStarted) {
printEmulatorWelcome();
}
});

View File

@ -12,16 +12,21 @@ 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";
const VALID_INIT_MODES = ["create", "create-cloud", "link-config", "link-cloud"] as const;
type InitMode = typeof VALID_INIT_MODES[number];
type InitOptions = {
mode?: "create" | "create-cloud" | "link-config" | "link-cloud",
mode?: InitMode,
apps?: string,
configFile?: string,
selectProjectId?: string,
outputDir?: string,
agent?: boolean,
displayName?: string,
};
export function registerInitCommand(program: Command) {
@ -34,8 +39,12 @@ export function registerInitCommand(program: Command) {
.option("--select-project-id <id>", "Project ID to link (for link-cloud mode)")
.option("--output-dir <dir>", "Directory to write output files (defaults to cwd)")
.option("--no-agent", "Skip Claude agent and print setup instructions instead")
.option("--display-name <name>", "Project display name (used by create-cloud mode)")
.action(async (opts: InitOptions) => {
const hasFlags = opts.mode != null;
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()) {
throw new CliError("stack init requires an interactive terminal. Use --mode flag for non-interactive usage.");
@ -91,7 +100,7 @@ async function runInit(program: Command, opts: InitOptions) {
console.log("Welcome to Stack Auth!\n");
let mode: "create" | "create-cloud" | "link" | "link-config" | "link-cloud";
let mode: string;
if (opts.mode) {
mode = opts.mode;
} else if (opts.selectProjectId) {
@ -99,54 +108,45 @@ async function runInit(program: Command, opts: InitOptions) {
} else if (opts.configFile) {
mode = "link-config";
} else {
const action = await select({
message: "Would you like to link to an existing project, or create a new one?",
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: "Create a new project", value: "create" as const },
{ name: "Link an existing project", value: "link" as const },
{ name: "Stack Auth Cloud", value: "hosted" as const },
{ name: localLabel, value: "local" as const },
],
});
if (action === "link") {
mode = "link";
} else {
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";
}
mode = location === "local" ? "create" : "create-cloud";
}
let configPath: string | undefined;
let projectId: string | undefined;
switch (mode) {
case "link":
case "link-config":
case "link-cloud": {
const result = await handleLink(flags, opts, outputDir, mode);
configPath = result.configPath;
break;
}
case "create": {
const result = await handleCreate(opts, outputDir);
configPath = result.configPath;
break;
}
case "create-cloud": {
const result = await handleCreateCloud(flags, opts, outputDir);
configPath = result.configPath;
break;
}
if (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}`);
}
const initPrompt = createInitPrompt(false, configPath);
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,
@ -158,26 +158,31 @@ async function runInit(program: Command, opts: InitOptions) {
} else {
console.log("\n" + initPrompt);
}
const { dashboardUrl } = resolveLoginConfig(flags as { projectId?: string });
printNextSteps({ mode, projectId, dashboardUrl });
}
async function handleLink(flags: Record<string, unknown>, opts: InitOptions, outputDir: string, resolvedMode: "link" | "link-config" | "link-cloud"): Promise<{ configPath?: string }> {
let source: "config-file" | "cloud";
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 <UserButton /> into a page to see the session.");
if (resolvedMode === "link-config") {
source = "config-file";
} else if (resolvedMode === "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 (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/${encodeURIComponent(args.projectId)}`);
}
if (source === "config-file") {
console.log(" • Docs: https://docs.stack-auth.com");
console.log("");
}
async function handleLink(flags: Record<string, unknown>, 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);
@ -223,6 +228,7 @@ async function ensureLoggedInSession(flags: Record<string, unknown>) {
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",
@ -235,8 +241,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}`,
@ -271,28 +285,34 @@ async function writeProjectKeysToEnv(
}
}
async function handleCreateCloud(flags: Record<string, unknown>, opts: InitOptions, outputDir: string): Promise<{ configPath?: string }> {
async function handleCreateCloud(flags: Record<string, unknown>, opts: InitOptions, outputDir: string): Promise<{ configPath?: string, projectId?: string }> {
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`);
await writeProjectKeysToEnv(newProject, outputDir);
return {};
return { projectId: newProject.id };
}
async function handleLinkFromCloud(flags: Record<string, unknown>, opts: InitOptions, outputDir: string): Promise<{ configPath?: string }> {
async function handleLinkFromCloud(flags: Record<string, unknown>, opts: InitOptions, outputDir: string): Promise<{ configPath?: string, projectId?: 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 (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 <name>` first, or set --select-project-id.");
throw new CliError("No projects found. Run `stack project create --display-name <name>` first.");
}
const shouldCreate = await confirm({
@ -301,11 +321,14 @@ async function handleLinkFromCloud(flags: Record<string, unknown>, 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];
@ -331,9 +354,10 @@ async function handleLinkFromCloud(flags: Record<string, unknown>, 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 {};
return { projectId };
}
async function performLogin(flags: Record<string, unknown>) {

View File

@ -1,6 +1,6 @@
import { Command } from "commander";
import { resolveSessionAuth } from "../lib/auth.js";
import { getInternalUser } from "../lib/app.js";
import { resolveLoginConfig, resolveSessionAuth } from "../lib/auth.js";
import { createProjectInteractively } from "../lib/create-project.js";
export function registerProjectCommand(program: Command) {
@ -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) {

View File

@ -1,3 +1,8 @@
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";
@ -48,7 +53,10 @@ async function main() {
console.error(`Error: ${err.message}`);
process.exit(1);
}
throw err;
captureError("stack-cli-fatal", err);
await Sentry.flush(2000);
console.error(err);
process.exit(1);
}
}

View File

@ -1,36 +1,39 @@
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(
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();
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({
displayName: displayName.trim(),
displayName,
teamId: teams[0].id,
});
}

View File

@ -0,0 +1,96 @@
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";
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;
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<string, unknown> = {};
for (const [k, v] of Object.entries(value)) {
out[k] = scrubValue(v, k);
}
return out;
}
return value;
}
export function initSentry() {
const dsn = typeof __STACK_CLI_SENTRY_DSN__ === "string" ? __STACK_CLI_SENTRY_DSN__ : "";
const version = readPackageVersion();
Sentry.init({
...sentryBaseConfig,
dsn,
enabled: !!dsn && getNodeEnvironment() !== "development" && !getEnvVariable("CI", ""),
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;
},
});
registerErrorSink((location, error) => {
Sentry.captureException(error, { extra: { location } });
ignoreUnhandledRejection(Sentry.flush(2000));
});
}

View File

@ -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' }),

View File

@ -1059,7 +1059,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@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)
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)
examples/cjs-test:
dependencies:
@ -2127,6 +2127,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
@ -22286,7 +22289,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
@ -22717,6 +22720,16 @@ 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)
@ -22724,6 +22737,13 @@ 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
@ -22737,6 +22757,19 @@ 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)
@ -22745,6 +22778,14 @@ 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)
@ -22753,6 +22794,14 @@ 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
@ -22760,6 +22809,13 @@ 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': {}
@ -22771,6 +22827,13 @@ 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)
@ -22778,6 +22841,13 @@ 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
@ -22786,6 +22856,14 @@ 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)
@ -22801,20 +22879,35 @@ snapshots:
optionalDependencies:
'@types/node': 20.17.6
'@inquirer/prompts@7.9.0(@types/node@20.17.6)':
'@inquirer/prompts@7.10.1(@types/node@24.9.2)':
dependencies:
'@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)
'@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': 20.17.6
'@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)
optionalDependencies:
'@types/node': 24.9.2
'@inquirer/rawlist@4.1.11(@types/node@20.17.6)':
dependencies:
@ -22824,6 +22917,14 @@ 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)
@ -22833,6 +22934,15 @@ 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
@ -22843,10 +22953,24 @@ 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
@ -22990,9 +23114,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@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)':
'@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)':
dependencies:
'@inquirer/prompts': 7.9.0(@types/node@20.17.6)
'@inquirer/prompts': 7.9.0(@types/node@24.9.2)
'@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)(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)
@ -23005,7 +23129,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@20.17.6)
inquirer: 12.3.0(@types/node@24.9.2)
js-yaml: 4.1.0
mdast-util-mdx-jsx: 3.2.0
open: 8.4.2
@ -24320,7 +24444,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:
@ -24373,7 +24497,7 @@ snapshots:
'@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
@ -24422,7 +24546,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:
@ -24449,7 +24573,7 @@ snapshots:
'@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
@ -24501,7 +24625,7 @@ snapshots:
'@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:
@ -24589,7 +24713,7 @@ snapshots:
'@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:
@ -24646,7 +24770,7 @@ snapshots:
'@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:
@ -24734,7 +24858,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)
@ -24834,7 +24958,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
@ -25183,7 +25307,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': {}
@ -28697,38 +28821,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)
@ -28752,13 +28876,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:
@ -28768,8 +28892,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)
@ -28793,26 +28917,17 @@ 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)':
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
'@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)':
dependencies:
'@opentelemetry/api': 1.9.0
@ -28822,6 +28937,15 @@ snapshots:
'@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.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.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)':
dependencies:
'@opentelemetry/api': 1.9.0
@ -28831,12 +28955,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
@ -28863,7 +28987,7 @@ 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':
@ -30572,7 +30696,6 @@ snapshots:
'@types/node@24.9.2':
dependencies:
undici-types: 7.16.0
optional: true
'@types/nodemailer@6.4.15':
dependencies:
@ -33650,7 +33773,7 @@ snapshots:
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.56.1(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.56.1(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.56.1(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
eslint-plugin-react: 7.37.2(eslint@8.57.1)
eslint-plugin-react-hooks: 5.1.0(eslint@8.57.1)
@ -33674,7 +33797,7 @@ snapshots:
debug: 4.4.3
enhanced-resolve: 5.17.0
eslint: 8.57.1
eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.56.1(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
fast-glob: 3.3.3
get-tsconfig: 4.8.1
@ -33724,7 +33847,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1):
eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.56.1(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
dependencies:
debug: 3.2.7
optionalDependencies:
@ -33784,7 +33907,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.56.1(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@ -35719,12 +35842,12 @@ snapshots:
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
inquirer@12.3.0(@types/node@20.17.6):
inquirer@12.3.0(@types/node@24.9.2):
dependencies:
'@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
'@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
ansi-escapes: 4.3.2
mute-stream: 2.0.0
run-async: 3.0.0
@ -37207,9 +37330,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@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):
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):
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@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)
'@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)
transitivePeerDependencies:
- '@radix-ui/react-popover'
- '@types/node'
@ -41405,8 +41528,7 @@ snapshots:
undici-types@6.21.0: {}
undici-types@7.16.0:
optional: true
undici-types@7.16.0: {}
undici@6.19.8: {}