-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: launch darkly markdown component (#1550)
- Loading branch information
1 parent
272ee0c
commit cb53af9
Showing
10 changed files
with
261 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
packages/ui/app/src/mdx/components/launchdarkly/LaunchDarkly.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { captureException } from "@sentry/nextjs"; | ||
import { atom, useAtomValue } from "jotai"; | ||
import { loadable } from "jotai/utils"; | ||
import * as LDClient from "launchdarkly-js-client-sdk"; | ||
import { PropsWithChildren, ReactNode, useCallback, useEffect, useState } from "react"; | ||
import { selectApiRoute } from "../../../hooks/useApiRoute"; | ||
|
||
async function fetchClientSideId(route: string): Promise<string | undefined> { | ||
const json = await fetch(route).then((res) => res.json()); | ||
return json?.["client-side-id"]; | ||
} | ||
|
||
// this is a singleton atom that initializes the LaunchDarkly client-side SDK | ||
const ldClientAtom = atom<Promise<LDClient.LDClient | undefined>>(async (get) => { | ||
if (typeof window === "undefined") { | ||
return undefined; | ||
} | ||
const route = selectApiRoute(get, "/api/fern-docs/integrations/launchdarkly"); | ||
const clientSideId = await fetchClientSideId(route); | ||
if (!clientSideId) { | ||
return undefined; | ||
} | ||
|
||
const client = LDClient.initialize(clientSideId, { | ||
kind: "user", | ||
anonymous: true, | ||
}); | ||
|
||
await client.waitForInitialization(); | ||
|
||
return client; | ||
}); | ||
|
||
const useLaunchDarklyFlag = (flag: string): boolean => { | ||
const loadableClient = useAtomValue(loadable(ldClientAtom)); | ||
const client = loadableClient.state === "hasData" ? loadableClient.data : undefined; | ||
if (loadableClient.state === "hasError") { | ||
captureException(loadableClient.error); | ||
} | ||
|
||
const getFlagEnabled = useCallback(() => { | ||
return client?.variation(flag, false) ?? false; | ||
}, [client, flag]); | ||
|
||
const [enabled, setEnabled] = useState(getFlagEnabled); | ||
|
||
useEffect(() => { | ||
setEnabled(getFlagEnabled()); | ||
|
||
if (!client) { | ||
return; | ||
} | ||
|
||
const listener = () => { | ||
setEnabled(getFlagEnabled()); | ||
}; | ||
|
||
client.on("ready", listener); | ||
client.on("change", listener); | ||
|
||
return () => { | ||
client.off("ready", listener); | ||
client.off("change", listener); | ||
}; | ||
}, [client, flag, getFlagEnabled]); | ||
|
||
return enabled; | ||
}; | ||
|
||
export interface LaunchDarklyProps { | ||
flag: string; | ||
} | ||
|
||
export function LaunchDarkly({ flag, children }: PropsWithChildren<LaunchDarklyProps>): ReactNode { | ||
const ldClient = useLaunchDarklyFlag(flag); | ||
|
||
if (!ldClient) { | ||
return null; | ||
} | ||
|
||
return children; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./LaunchDarkly"; |
29 changes: 29 additions & 0 deletions
29
packages/ui/docs-bundle/src/pages/api/fern-docs/integrations/launchdarkly.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { getXFernHostEdge } from "@/server/xfernhost/edge"; | ||
import { get } from "@vercel/edge-config"; | ||
import { NextRequest, NextResponse } from "next/server"; | ||
import { z } from "zod"; | ||
|
||
export const runtime = "edge"; | ||
|
||
const LaunchDarklyEdgeConfigSchema = z.object({ | ||
// NOTE: this is client-side visible, so we should be careful about what we expose here if we add more fields | ||
"client-side-id": z.string().optional(), | ||
}); | ||
|
||
type LaunchDarklyEdgeConfigSchema = z.infer<typeof LaunchDarklyEdgeConfigSchema>; | ||
|
||
export default async function handler(req: NextRequest): Promise<NextResponse<LaunchDarklyEdgeConfigSchema>> { | ||
const domain = getXFernHostEdge(req); | ||
try { | ||
const config = (await get<Record<string, LaunchDarklyEdgeConfigSchema>>("launchdarkly"))?.[domain]; | ||
if (config == null) { | ||
return NextResponse.json({}, { status: 404 }); | ||
} | ||
|
||
return NextResponse.json(config); | ||
} catch (e) { | ||
// eslint-disable-next-line no-console | ||
console.error(e); | ||
return NextResponse.json({}, { status: 500 }); | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
instances: | ||
- url: https://launchdarkly-test.docs.dev.buildwithfern.com | ||
title: Launch Darkly Test | ||
navigation: [] | ||
landing-page: | ||
page: Test | ||
path: test.mdx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"organization": "fern", | ||
"version": "0.43.4-7-gfe56df403b" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
### Testing | ||
|
||
<LaunchDarkly flag="flag-1"> | ||
|
||
Testing **flag 1** | ||
|
||
</LaunchDarkly> | ||
|
||
<LaunchDarkly flag="flag-2"> | ||
|
||
Testing **flag 2** | ||
|
||
</LaunchDarkly> |