Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion apps/web/src/components/ingest/guided-setup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { cleanup, fireEvent, render, screen } from "@testing-library/react"
import { afterEach, describe, expect, it } from "vitest"

import { REPLAY_BLOCK_CLASS } from "@/components/common/replay-privacy"
import { ConnectInstructions } from "./guided-setup"
import { isClerkAuthEnabled } from "@/lib/services/common/auth-mode"
import { ConnectInstructions, useGuidedFramework } from "./guided-setup"

const API_KEY = "mpl_ingest_supersecretkey123"

Expand Down Expand Up @@ -37,3 +38,26 @@ describe("ConnectInstructions", () => {
expect(leaked).toEqual([])
})
})

function FrameworkProbe() {
const { framework } = useGuidedFramework()
return <span data-testid="framework">{framework}</span>
}

/**
* Rendered with no `ClerkProvider`, which is what a self-hosted build is:
* `main.tsx` mounts one only when `isClerkAuthEnabled`. A Clerk hook called
* unconditionally in here threw, and self-hosted `/settings` opens on the
* ingestion tab that renders it.
*/
describe("useGuidedFramework", () => {
afterEach(cleanup)

it("renders self-hosted, outside a ClerkProvider", () => {
expect(isClerkAuthEnabled).toBe(false)

render(<FrameworkProbe />)

expect(screen.getByTestId("framework").textContent).toBe("nodejs")
})
})
39 changes: 32 additions & 7 deletions apps/web/src/components/ingest/guided-setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from "@/components/quick-start/framework-icons"
import { sdkSnippets, type FrameworkId } from "@/components/quick-start/sdk-snippets"
import { ingestUrl } from "@/lib/services/common/ingest-url"
import { isClerkAuthEnabled } from "@/lib/services/common/auth-mode"
import { useQuickStart } from "@/hooks/use-quick-start"
import type { RoleOption } from "@/atoms/quick-start-atoms"
import { CopyableField } from "@maple/ui/components/ui/copyable-field"
Expand Down Expand Up @@ -42,19 +43,43 @@ interface GuidedSetupProps {
showCredentials?: boolean
}

/**
* Per-org framework selection for the guided ingestion flow, defaulting from the
* quick-start qualify answers. Shared by `GuidedSetup` and the ingestion
* settings page (which composes the picker into its own section header).
*/
export function useGuidedFramework() {
const { orgId } = useAuth()
interface GuidedFramework {
readonly framework: FrameworkId
readonly setFramework: (framework: FrameworkId) => void
}

const useGuidedFrameworkFor = (orgId: string | null | undefined): GuidedFramework => {
const { selectedFramework, setSelectedFramework, qualifyAnswers } = useQuickStart(orgId)

const roleDefault = qualifyAnswers.role ? ROLE_DEFAULT_FRAMEWORK[qualifyAnswers.role] : "nodejs"
return { framework: selectedFramework ?? roleDefault, setFramework: setSelectedFramework }
}

function useClerkGuidedFramework(): GuidedFramework {
const { orgId } = useAuth()
return useGuidedFrameworkFor(orgId)
}

/** Self-hosted: one org, so the selection lives under the default key. */
function useSelfHostedGuidedFramework(): GuidedFramework {
return useGuidedFrameworkFor(null)
}

/**
* Per-org framework selection for the guided ingestion flow, defaulting from the
* quick-start qualify answers. Shared by `GuidedSetup` and the ingestion
* settings page (which composes the picker into its own section header).
*
* The variant is chosen at module scope off a build-time constant, the same
* shape as `useOrganizationFeatureFlags`: `main.tsx` mounts `ClerkProvider` only
* when `isClerkAuthEnabled`, and `useAuth()` throws without one — an early
* return inside the hook would come after it had already run. Self-hosted
* `/settings` opens on the ingestion tab, so this threw before rendering it.
*/
export const useGuidedFramework: () => GuidedFramework = isClerkAuthEnabled
? useClerkGuidedFramework
: useSelfHostedGuidedFramework

/**
* Framework picker + Install / Instrument / Claude Code tabs. The shared body of
* the guided ingestion flow, used by the dashboard setup checklist and the
Expand Down
Loading