mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
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:
parent
6eaf49237f
commit
acc646cb0b
@ -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),
|
||||
})),
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@ -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't have one yet? Paste your project folder path instead and we'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'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>
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -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>) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
96
packages/stack-cli/src/lib/sentry.ts
Normal file
96
packages/stack-cli/src/lib/sentry.ts
Normal 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));
|
||||
});
|
||||
}
|
||||
@ -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' }),
|
||||
|
||||
280
pnpm-lock.yaml
280
pnpm-lock.yaml
@ -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: {}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user