diff --git a/packages/fern-docs/bundle/src/app/[[...slug]]/llms-full.txt.ts b/packages/fern-docs/bundle/src/app/[[...slug]]/llms-full.txt.ts index a2a9f1b079..3d06a9d71e 100644 --- a/packages/fern-docs/bundle/src/app/[[...slug]]/llms-full.txt.ts +++ b/packages/fern-docs/bundle/src/app/[[...slug]]/llms-full.txt.ts @@ -5,7 +5,7 @@ import { getDocsDomainEdge, getHostEdge } from "@/server/xfernhost/edge"; import { FernNavigation } from "@fern-api/fdr-sdk"; import { CONTINUE, SKIP } from "@fern-api/fdr-sdk/traversers"; import { isNonNullish } from "@fern-api/ui-core-utils"; -import { getFeatureFlags } from "@fern-docs/edge-config"; +import { getEdgeFlags } from "@fern-docs/edge-config"; import { addLeadingSlash, COOKIE_FERN_TOKEN } from "@fern-docs/utils"; import { uniqBy } from "es-toolkit/array"; import { cookies } from "next/headers"; @@ -20,9 +20,9 @@ export async function handleLLMSFullTxt( const domain = getDocsDomainEdge(req); const host = getHostEdge(req); const fern_token = cookies().get(COOKIE_FERN_TOKEN)?.value; - const featureFlags = await getFeatureFlags(domain); - const loader = DocsLoader.for(domain, host, fern_token).withFeatureFlags( - featureFlags + const edgeFlags = await getEdgeFlags(domain); + const loader = DocsLoader.for(domain, host, fern_token).withEdgeFlags( + edgeFlags ); const root = getSectionRoot(await loader.root(), path); @@ -53,7 +53,7 @@ export async function handleLLMSFullTxt( nodes, (a) => FernNavigation.getPageId(a) ?? a.canonicalSlug ?? a.slug ).map(async (node) => { - const markdown = await getMarkdownForPath(node, loader, featureFlags); + const markdown = await getMarkdownForPath(node, loader, edgeFlags); if (markdown == null) { return undefined; } diff --git a/packages/fern-docs/bundle/src/app/[[...slug]]/llms.txt.ts b/packages/fern-docs/bundle/src/app/[[...slug]]/llms.txt.ts index ce605bcad1..355781f8af 100644 --- a/packages/fern-docs/bundle/src/app/[[...slug]]/llms.txt.ts +++ b/packages/fern-docs/bundle/src/app/[[...slug]]/llms.txt.ts @@ -6,7 +6,7 @@ import { getDocsDomainEdge, getHostEdge } from "@/server/xfernhost/edge"; import * as FernNavigation from "@fern-api/fdr-sdk/navigation"; import { CONTINUE, SKIP } from "@fern-api/fdr-sdk/traversers"; import { isNonNullish, withDefaultProtocol } from "@fern-api/ui-core-utils"; -import { getFeatureFlags } from "@fern-docs/edge-config"; +import { getEdgeFlags } from "@fern-docs/edge-config"; import { COOKIE_FERN_TOKEN, addLeadingSlash } from "@fern-docs/utils"; import { cookies } from "next/headers"; import { NextRequest, NextResponse } from "next/server"; @@ -40,9 +40,9 @@ export async function handleLLMSTxt( const domain = getDocsDomainEdge(req); const host = getHostEdge(req); const fern_token = cookies().get(COOKIE_FERN_TOKEN)?.value; - const featureFlags = await getFeatureFlags(domain); - const loader = DocsLoader.for(domain, host, fern_token).withFeatureFlags( - featureFlags + const edgeFlags = await getEdgeFlags(domain); + const loader = DocsLoader.for(domain, host, fern_token).withEdgeFlags( + edgeFlags ); const root = getSectionRoot(await loader.root(), path); @@ -71,7 +71,7 @@ export async function handleLLMSTxt( const landingPage = getLandingPage(root); const markdown = landingPage != null - ? await getMarkdownForPath(landingPage, loader, featureFlags) + ? await getMarkdownForPath(landingPage, loader, edgeFlags) : undefined; // traverse the tree in a depth-first manner to collect all the nodes that have markdown content diff --git a/packages/fern-docs/bundle/src/app/[[...slug]]/markdown.ts b/packages/fern-docs/bundle/src/app/[[...slug]]/markdown.ts index 8580bb7c9c..39125e63ed 100644 --- a/packages/fern-docs/bundle/src/app/[[...slug]]/markdown.ts +++ b/packages/fern-docs/bundle/src/app/[[...slug]]/markdown.ts @@ -4,7 +4,7 @@ import { getPageNodeForPath, } from "@/server/getMarkdownForPath"; import { getDocsDomainEdge, getHostEdge } from "@/server/xfernhost/edge"; -import { getFeatureFlags } from "@fern-docs/edge-config"; +import { getEdgeFlags } from "@fern-docs/edge-config"; import { addLeadingSlash, COOKIE_FERN_TOKEN } from "@fern-docs/utils"; import { cookies } from "next/headers"; import { notFound } from "next/navigation"; @@ -23,9 +23,9 @@ export async function handleMarkdown( const domain = getDocsDomainEdge(req); const host = getHostEdge(req); const fern_token = cookies().get(COOKIE_FERN_TOKEN)?.value; - const featureFlags = await getFeatureFlags(domain); - const loader = DocsLoader.for(domain, host, fern_token).withFeatureFlags( - featureFlags + const edgeFlags = await getEdgeFlags(domain); + const loader = DocsLoader.for(domain, host, fern_token).withEdgeFlags( + edgeFlags ); const node = getPageNodeForPath(await loader.root(), path); @@ -39,7 +39,7 @@ export async function handleMarkdown( return new NextResponse(null, { status: 403 }); } - const markdown = await getMarkdownForPath(node, loader, featureFlags); + const markdown = await getMarkdownForPath(node, loader, edgeFlags); if (markdown == null) { notFound(); } diff --git a/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/endpoint/[endpoint]/route.ts b/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/endpoint/[endpoint]/route.ts index ca49715a67..1a74efc275 100644 --- a/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/endpoint/[endpoint]/route.ts +++ b/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/endpoint/[endpoint]/route.ts @@ -1,7 +1,7 @@ import { getAuthStateEdge } from "@/server/auth/getAuthStateEdge"; import * as ApiDefinition from "@fern-api/fdr-sdk/api-definition"; import { ApiDefinitionLoader } from "@fern-docs/cache"; -import { getFeatureFlags } from "@fern-docs/edge-config"; +import { getEdgeFlags } from "@fern-docs/edge-config"; import { getMdxBundler } from "@fern-docs/ui/bundlers"; import { NextRequest, NextResponse } from "next/server"; @@ -20,7 +20,7 @@ export async function GET( ); } - const flags = await getFeatureFlags(authState.domain); + const flags = await getEdgeFlags(authState.domain); const engine = flags.useMdxBundler ? "mdx-bundler" : "next-mdx-remote"; const serializeMdx = await getMdxBundler(engine); @@ -28,7 +28,7 @@ export async function GET( authState.domain, ApiDefinition.ApiDefinitionId(api) ) - .withFlags(flags) + .withEdgeFlags(flags) .withMdxBundler(serializeMdx, engine) .withPrune({ type: "endpoint", diff --git a/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/webhook/[webhook]/route.ts b/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/webhook/[webhook]/route.ts index 711977278c..4f5472159f 100644 --- a/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/webhook/[webhook]/route.ts +++ b/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/webhook/[webhook]/route.ts @@ -1,7 +1,7 @@ import { getAuthStateEdge } from "@/server/auth/getAuthStateEdge"; import * as ApiDefinition from "@fern-api/fdr-sdk/api-definition"; import { ApiDefinitionLoader } from "@fern-docs/cache"; -import { getFeatureFlags } from "@fern-docs/edge-config"; +import { getEdgeFlags } from "@fern-docs/edge-config"; import { getMdxBundler } from "@fern-docs/ui/bundlers"; import { NextRequest, NextResponse } from "next/server"; @@ -20,7 +20,7 @@ export async function GET( ); } - const flags = await getFeatureFlags(authState.domain); + const flags = await getEdgeFlags(authState.domain); const engine = flags.useMdxBundler ? "mdx-bundler" : "next-mdx-remote"; const serializeMdx = await getMdxBundler(engine); @@ -28,7 +28,7 @@ export async function GET( authState.domain, ApiDefinition.ApiDefinitionId(api) ) - .withFlags(flags) + .withEdgeFlags(flags) .withMdxBundler(serializeMdx, engine) .withPrune({ type: "webhook", diff --git a/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/websocket/[websocket]/route.ts b/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/websocket/[websocket]/route.ts index ab3238e9d5..b218c5617f 100644 --- a/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/websocket/[websocket]/route.ts +++ b/packages/fern-docs/bundle/src/app/api/fern-docs/api-definition/[api]/websocket/[websocket]/route.ts @@ -1,7 +1,7 @@ import { getAuthStateEdge } from "@/server/auth/getAuthStateEdge"; import * as ApiDefinition from "@fern-api/fdr-sdk/api-definition"; import { ApiDefinitionLoader } from "@fern-docs/cache"; -import { getFeatureFlags } from "@fern-docs/edge-config"; +import { getEdgeFlags } from "@fern-docs/edge-config"; import { getMdxBundler } from "@fern-docs/ui/bundlers"; import { NextRequest, NextResponse } from "next/server"; @@ -20,7 +20,7 @@ export async function GET( ); } - const flags = await getFeatureFlags(authState.domain); + const flags = await getEdgeFlags(authState.domain); const engine = flags.useMdxBundler ? "mdx-bundler" : "next-mdx-remote"; const serializeMdx = await getMdxBundler(engine); @@ -28,7 +28,7 @@ export async function GET( authState.domain, ApiDefinition.ApiDefinitionId(api) ) - .withFlags(flags) + .withEdgeFlags(flags) .withMdxBundler(serializeMdx, engine) .withPrune({ type: "webSocket", diff --git a/packages/fern-docs/bundle/src/app/api/fern-docs/integrations/launchdarkly.ts b/packages/fern-docs/bundle/src/app/api/fern-docs/integrations/launchdarkly/route.ts similarity index 93% rename from packages/fern-docs/bundle/src/app/api/fern-docs/integrations/launchdarkly.ts rename to packages/fern-docs/bundle/src/app/api/fern-docs/integrations/launchdarkly/route.ts index a246362837..eee5a75fd9 100644 --- a/packages/fern-docs/bundle/src/app/api/fern-docs/integrations/launchdarkly.ts +++ b/packages/fern-docs/bundle/src/app/api/fern-docs/integrations/launchdarkly/route.ts @@ -11,8 +11,7 @@ import { NextRequest, NextResponse, userAgent } from "next/server"; export const runtime = "edge"; -interface LaunchDarklyInfo { - clientSideId: string; +interface LaunchDarklyContext { kind: "multi"; user: | { anonymous: true } @@ -29,7 +28,7 @@ interface LaunchDarklyInfo { export async function GET( req: NextRequest -): Promise> { +): Promise> { const domain = getDocsDomainEdge(req); const config = await safeGetLaunchDarklySettings(domain); @@ -40,7 +39,6 @@ export async function GET( } return NextResponse.json({ - clientSideId, kind: "multi" as const, user: await getUserContext(req), device: await getDeviceContext(req), @@ -72,7 +70,7 @@ async function hashString( async function getUserContext( req: NextRequest -): Promise { +): Promise { const jar = cookies(); const fernToken = jar.get(COOKIE_FERN_TOKEN)?.value; @@ -102,7 +100,7 @@ async function getUserContext( async function getDeviceContext( req: NextRequest -): Promise { +): Promise { const agent = userAgent(req); const hash = (await hashString(agent.ua)) ?? crypto.randomUUID(); diff --git a/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/chat/route.ts b/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/chat/route.ts index ece9d9e858..79c5ec4d9a 100644 --- a/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/chat/route.ts +++ b/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/chat/route.ts @@ -10,7 +10,7 @@ import { getDocsDomainEdge } from "@/server/xfernhost/edge"; import { createAnthropic } from "@ai-sdk/anthropic"; // import { createAmazonBedrock } from "@ai-sdk/amazon-bedrock"; import { createOpenAI } from "@ai-sdk/openai"; -import { getAuthEdgeConfig, getFeatureFlags } from "@fern-docs/edge-config"; +import { getAuthEdgeConfig, getEdgeFlags } from "@fern-docs/edge-config"; import { createDefaultSystemPrompt } from "@fern-docs/search-server"; import { queryTurbopuffer, @@ -48,12 +48,12 @@ export async function POST(req: NextRequest) { } const start = Date.now(); - const [authEdgeConfig, featureFlags] = await Promise.all([ + const [authEdgeConfig, edgeFlags] = await Promise.all([ getAuthEdgeConfig(domain), - getFeatureFlags(domain), + getEdgeFlags(domain), ]); - if (!featureFlags.isAskAiEnabled) { + if (!edgeFlags.isAskAiEnabled) { throw new Error(`Ask AI is not enabled for ${domain}`); } diff --git a/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/reindex/algolia/route.ts b/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/reindex/algolia/route.ts index 03fabde064..ed51829e2e 100644 --- a/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/reindex/algolia/route.ts +++ b/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/reindex/algolia/route.ts @@ -8,7 +8,7 @@ import { } from "@/server/env-variables"; import { Gate, withBasicTokenAnonymous } from "@/server/withRbac"; import { getDocsDomainEdge } from "@/server/xfernhost/edge"; -import { getAuthEdgeConfig, getFeatureFlags } from "@fern-docs/edge-config"; +import { getAuthEdgeConfig, getEdgeFlags } from "@fern-docs/edge-config"; import { SEARCH_INDEX, algoliaIndexSettingsTask, @@ -40,9 +40,9 @@ export async function GET(req: NextRequest): Promise { } const start = Date.now(); - const [authEdgeConfig, featureFlags] = await Promise.all([ + const [authEdgeConfig, edgeFlags] = await Promise.all([ getAuthEdgeConfig(domain), - getFeatureFlags(domain), + getEdgeFlags(domain), ]); await algoliaIndexSettingsTask({ @@ -70,7 +70,7 @@ export async function GET(req: NextRequest): Promise { ) === Gate.DENY ); }, - ...featureFlags, + ...edgeFlags, }); const end = Date.now(); diff --git a/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/reindex/turbopuffer/route.ts b/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/reindex/turbopuffer/route.ts index 03d11d321b..0eef3705ea 100644 --- a/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/reindex/turbopuffer/route.ts +++ b/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/reindex/turbopuffer/route.ts @@ -1,5 +1,5 @@ import { createOpenAI } from "@ai-sdk/openai"; -import { getAuthEdgeConfig, getFeatureFlags } from "@fern-docs/edge-config"; +import { getAuthEdgeConfig, getEdgeFlags } from "@fern-docs/edge-config"; import { turbopufferUpsertTask } from "@fern-docs/search-server/turbopuffer"; import { addLeadingSlash, withoutStaging } from "@fern-docs/utils"; import { embedMany } from "ai"; @@ -48,12 +48,12 @@ export async function GET(req: NextRequest): Promise { } const start = Date.now(); - const [authEdgeConfig, featureFlags] = await Promise.all([ + const [authEdgeConfig, edgeFlags] = await Promise.all([ getAuthEdgeConfig(domain), - getFeatureFlags(domain), + getEdgeFlags(domain), ]); - if (!featureFlags.isAskAiEnabled) { + if (!edgeFlags.isAskAiEnabled) { throw new Error(`AI Chat is not enabled for ${domain}`); } @@ -64,7 +64,7 @@ export async function GET(req: NextRequest): Promise { environment: fdrEnvironment(), fernToken: fernToken(), domain: withoutStaging(domain), - ...featureFlags, + ...edgeFlags, }, vectorizer: async (chunks) => { const embeddings = await embedMany({ diff --git a/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/suggest/route.ts b/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/suggest/route.ts index d5e77520b6..960916124f 100644 --- a/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/suggest/route.ts +++ b/packages/fern-docs/bundle/src/app/api/fern-docs/search/v2/suggest/route.ts @@ -3,7 +3,7 @@ import { algoliaAppId, anthropicApiKey } from "@/server/env-variables"; import { getDocsDomainEdge } from "@/server/xfernhost/edge"; import { createAnthropic } from "@ai-sdk/anthropic"; import { searchClient } from "@algolia/client-search"; -import { getFeatureFlags } from "@fern-docs/edge-config"; +import { getEdgeFlags } from "@fern-docs/edge-config"; import { SuggestionsSchema } from "@fern-docs/search-server"; import { SEARCH_INDEX, @@ -32,10 +32,10 @@ export async function POST(req: NextRequest): Promise { const start = Date.now(); const domain = getDocsDomainEdge(req); - const featureFlags = await getFeatureFlags(domain); + const edgeFlags = await getEdgeFlags(domain); const cookieJar = cookies(); - if (!featureFlags.isAskAiEnabled) { + if (!edgeFlags.isAskAiEnabled) { throw new Error(`Ask AI is not enabled for ${domain}`); } diff --git a/packages/fern-docs/bundle/src/pages/api/fern-docs/revalidate-all/v3.ts b/packages/fern-docs/bundle/src/pages/api/fern-docs/revalidate-all/v3.ts index f4d58db55c..8ea0f74242 100644 --- a/packages/fern-docs/bundle/src/pages/api/fern-docs/revalidate-all/v3.ts +++ b/packages/fern-docs/bundle/src/pages/api/fern-docs/revalidate-all/v3.ts @@ -8,7 +8,7 @@ import { import { Revalidator } from "@/server/revalidator"; import { getDocsDomainNode, getHostNode } from "@/server/xfernhost/node"; import { NodeCollector } from "@fern-api/fdr-sdk/navigation"; -import { getFeatureFlags } from "@fern-docs/edge-config"; +import { getEdgeFlags } from "@fern-docs/edge-config"; import { withoutStaging } from "@fern-docs/utils"; import type { FernDocs } from "@fern-fern/fern-docs-sdk"; import { NextApiHandler, NextApiRequest, NextApiResponse } from "next"; @@ -50,8 +50,8 @@ const handler: NextApiHandler = async ( // never provide a token here because revalidation should only be done on public routes (for now) const loader = DocsLoader.for(domain, host); - const flags = await getFeatureFlags(domain); - const root = await loader.withFeatureFlags(flags).root(); + const flags = await getEdgeFlags(domain); + const root = await loader.withEdgeFlags(flags).root(); if (!root) { /** diff --git a/packages/fern-docs/bundle/src/pages/api/fern-docs/revalidate-all/v4.ts b/packages/fern-docs/bundle/src/pages/api/fern-docs/revalidate-all/v4.ts index ebdfd68fe5..b9ecfba6e6 100644 --- a/packages/fern-docs/bundle/src/pages/api/fern-docs/revalidate-all/v4.ts +++ b/packages/fern-docs/bundle/src/pages/api/fern-docs/revalidate-all/v4.ts @@ -8,7 +8,7 @@ import { import { Revalidator } from "@/server/revalidator"; import { getDocsDomainNode, getHostNode } from "@/server/xfernhost/node"; import { NodeCollector } from "@fern-api/fdr-sdk/navigation"; -import { getFeatureFlags } from "@fern-docs/edge-config"; +import { getEdgeFlags } from "@fern-docs/edge-config"; import { withoutStaging } from "@fern-docs/utils"; import type { FernDocs } from "@fern-fern/fern-docs-sdk"; import { NextApiHandler, NextApiRequest, NextApiResponse } from "next"; @@ -53,8 +53,8 @@ const handler: NextApiHandler = async ( // never provide a token here because revalidation should only be done on public routes (for now) const loader = DocsLoader.for(domain, host); - const flags = await getFeatureFlags(domain); - const root = await loader.withFeatureFlags(flags).root(); + const flags = await getEdgeFlags(domain); + const root = await loader.withEdgeFlags(flags).root(); if (!root) { /** diff --git a/packages/fern-docs/bundle/src/server/DocsLoader.ts b/packages/fern-docs/bundle/src/server/DocsLoader.ts index 404696596b..8dd91b034e 100644 --- a/packages/fern-docs/bundle/src/server/DocsLoader.ts +++ b/packages/fern-docs/bundle/src/server/DocsLoader.ts @@ -32,15 +32,15 @@ export class DocsLoader { private fernToken: string | undefined ) {} - private featureFlags: DocsLoaderFlags = { + private edgeFlags: DocsLoaderFlags = { isBatchStreamToggleDisabled: false, isApiScrollingDisabled: false, useJavaScriptAsTypeScript: false, alwaysEnableJavaScriptFetch: false, usesApplicationJsonInFormDataValue: false, }; - public withFeatureFlags(featureFlags: DocsLoaderFlags): this { - this.featureFlags = featureFlags; + public withEdgeFlags(edgeFlags: DocsLoaderFlags): this { + this.edgeFlags = edgeFlags; return this; } @@ -106,14 +106,14 @@ export class DocsLoader { const latest = res.definition.apisV2?.[key] ?? (v1 != null - ? ApiDefinitionV1ToLatest.from(v1, this.featureFlags).migrate() + ? ApiDefinitionV1ToLatest.from(v1, this.edgeFlags).migrate() : undefined); if (!latest) { return undefined; } return ApiDefinitionLoader.create(this.domain, key) .withApiDefinition(latest) - .withFlags(this.featureFlags) + .withEdgeFlags(this.edgeFlags) .withResolveDescriptions(false) .withEnvironment(process.env.NEXT_PUBLIC_FDR_ORIGIN) .load(); @@ -143,8 +143,8 @@ export class DocsLoader { return FernNavigation.utils.toRootNode( docs, - this.featureFlags.isBatchStreamToggleDisabled, - this.featureFlags.isApiScrollingDisabled + this.edgeFlags.isBatchStreamToggleDisabled, + this.edgeFlags.isApiScrollingDisabled ); } @@ -167,6 +167,8 @@ export class DocsLoader { } } + // TODO: prune with feature flags state + return root; } diff --git a/packages/fern-docs/bundle/src/server/getMarkdownForPath.ts b/packages/fern-docs/bundle/src/server/getMarkdownForPath.ts index 906779d932..495281f30d 100644 --- a/packages/fern-docs/bundle/src/server/getMarkdownForPath.ts +++ b/packages/fern-docs/bundle/src/server/getMarkdownForPath.ts @@ -6,7 +6,7 @@ import { } from "@fern-api/fdr-sdk/api-definition"; import { MarkdownText } from "@fern-api/fdr-sdk/docs"; import { isNonNullish } from "@fern-api/ui-core-utils"; -import { FeatureFlags } from "@fern-docs/utils"; +import { EdgeFlags } from "@fern-docs/utils"; import { isString } from "es-toolkit/predicate"; import { DocsLoader } from "./DocsLoader"; import { pascalCaseHeaderKey } from "./headerKeyCase"; @@ -16,9 +16,9 @@ import { removeLeadingSlash } from "./removeLeadingSlash"; export async function getMarkdownForPath( node: FernNavigation.NavigationNodePage, loader: DocsLoader, - featureFlags: FeatureFlags + edgeFlags: EdgeFlags ): Promise<{ content: string; contentType: "markdown" | "mdx" } | undefined> { - loader = loader.withFeatureFlags(featureFlags); + loader = loader.withEdgeFlags(edgeFlags); const pages = await loader.pages(); if (FernNavigation.isApiLeaf(node)) { diff --git a/packages/fern-docs/bundle/src/server/withInitialProps.ts b/packages/fern-docs/bundle/src/server/withInitialProps.ts index de11bd3c6b..7d113c4869 100644 --- a/packages/fern-docs/bundle/src/server/withInitialProps.ts +++ b/packages/fern-docs/bundle/src/server/withInitialProps.ts @@ -4,7 +4,8 @@ import visitDiscriminatedUnion from "@fern-api/ui-core-utils/visitDiscriminatedU import { getAuthEdgeConfig, getCustomerAnalytics, - getFeatureFlags, + getEdgeFlags, + getLaunchDarklySettings, getSeoDisabled, } from "@fern-docs/edge-config"; import { @@ -75,8 +76,8 @@ export async function withInitialProps({ } // load from edge config - const [featureFlags, authConfig] = await Promise.all([ - getFeatureFlags(domain), + const [edgeFlags, authConfig] = await Promise.all([ + getEdgeFlags(domain), getAuthEdgeConfig(domain), ]); const authState = await getAuthState( @@ -89,7 +90,7 @@ export async function withInitialProps({ // create loader (this will load all nodes) const loader = DocsLoader.for(domain, host) - .withFeatureFlags(featureFlags) + .withEdgeFlags(edgeFlags) .withAuth(authConfig, authState) .withLoadDocsForUrlResponse(docs); @@ -127,7 +128,7 @@ export async function withInitialProps({ // this is better than following redirects, since it will signal a proper 404 status code. // however, we should consider rendering a custom 404 page in the future using the customer's branding. // see: https://nextjs.org/docs/app/api-reference/file-conventions/not-found - if (featureFlags.is404PageHidden && found.redirect != null) { + if (edgeFlags.is404PageHidden && found.redirect != null) { return withRedirect(found.redirect); } @@ -158,7 +159,7 @@ export async function withInitialProps({ found, authState, definition: docs.definition, - featureFlags, + edgeFlags, }); if (content == null) { @@ -264,7 +265,7 @@ export async function withInitialProps({ // when true, all unauthed pages are visible, but rendered with a LOCK button // so they're not actually "pruned" from the sidebar // TODO: move this out of a feature flag and into the navigation node metadata - discoverable: featureFlags.isAuthenticatedPagesDiscoverable + discoverable: edgeFlags.isAuthenticatedPagesDiscoverable ? (true as const) : undefined, }; @@ -324,9 +325,19 @@ export async function withInitialProps({ ? undefined : filteredTabs.indexOf(found.currentTab); - const engine = featureFlags.useMdxBundler ? "mdx-bundler" : "next-mdx-remote"; + const engine = edgeFlags.useMdxBundler ? "mdx-bundler" : "next-mdx-remote"; const serializeMdx = await getMdxBundler(engine); + const launchDarklyConfig = await getLaunchDarklySettings(docs.baseUrl.domain); + const launchDarklyInfo = + !!launchDarklyConfig?.["client-side-id"] && + !!launchDarklyConfig?.["user-context-endpoint"] + ? { + clientSideId: launchDarklyConfig?.["client-side-id"], + userContextEndpoint: launchDarklyConfig?.["user-context-endpoint"], + } + : undefined; + const props: ComponentProps = { baseUrl: docs.baseUrl, layout: docs.definition.config.layout, @@ -354,7 +365,7 @@ export async function withInitialProps({ sidebar, trailingSlash: isTrailingSlashEnabled(), }, - featureFlags, + edgeFlags, apis: Object.keys(docs.definition.apis).map(FernNavigation.ApiDefinitionId), seo: getSeoProps( docs.baseUrl.domain, @@ -373,7 +384,7 @@ export async function withInitialProps({ docs.baseUrl.domain, docs.baseUrl.basePath ), - theme: featureFlags.isCohereTheme ? "cohere" : "default", + theme: edgeFlags.isCohereTheme ? "cohere" : "default", analyticsConfig: docs.definition.config.analyticsConfig, defaultLang: docs.definition.config.defaultLanguage ?? "curl", stylesheet: renderThemeStylesheet( @@ -384,6 +395,9 @@ export async function withInitialProps({ docs.definition.filesV2, found.tabs.length > 0 ), + featureFlags: { + launchDarkly: launchDarklyInfo, + }, }; // if the user specifies a github navbar link, grab the repo info from it and save it as an SWR fallback diff --git a/packages/fern-docs/bundle/src/server/withResolvedDocsContent.ts b/packages/fern-docs/bundle/src/server/withResolvedDocsContent.ts index 30b4221cad..29afaa5abe 100644 --- a/packages/fern-docs/bundle/src/server/withResolvedDocsContent.ts +++ b/packages/fern-docs/bundle/src/server/withResolvedDocsContent.ts @@ -2,7 +2,7 @@ import { DocsV1Read } from "@fern-api/fdr-sdk"; import type * as FernNavigation from "@fern-api/fdr-sdk/navigation"; import { resolveDocsContent, type DocsContent } from "@fern-docs/ui"; import { getMdxBundler } from "@fern-docs/ui/bundlers"; -import { FeatureFlags } from "@fern-docs/utils"; +import { EdgeFlags } from "@fern-docs/utils"; import { AuthState } from "./auth/getAuthState"; import { withPrunedNavigation } from "./withPrunedNavigation"; @@ -11,7 +11,7 @@ interface WithResolvedDocsContentOpts { found: FernNavigation.utils.Node.Found; authState: AuthState; definition: DocsV1Read.DocsDefinition; - featureFlags: FeatureFlags; + edgeFlags: EdgeFlags; } export async function withResolvedDocsContent({ @@ -19,7 +19,7 @@ export async function withResolvedDocsContent({ found, authState, definition, - featureFlags, + edgeFlags, }: WithResolvedDocsContentOpts): Promise { const node = withPrunedNavigation(found.node, { visibleNodeIds: [found.node.id], @@ -36,7 +36,7 @@ export async function withResolvedDocsContent({ authed: authState.authed, }); - const engine = featureFlags.useMdxBundler ? "mdx-bundler" : "next-mdx-remote"; + const engine = edgeFlags.useMdxBundler ? "mdx-bundler" : "next-mdx-remote"; const serializeMdx = await getMdxBundler(engine); return resolveDocsContent({ @@ -50,12 +50,12 @@ export async function withResolvedDocsContent({ breadcrumb: found.breadcrumb, // strip away authed neighbors unless they are explicitly discoverable - prev: featureFlags.isAuthenticatedPagesDiscoverable + prev: edgeFlags.isAuthenticatedPagesDiscoverable ? found.prev : found.prev?.authed ? undefined : found.prev, - next: featureFlags.isAuthenticatedPagesDiscoverable + next: edgeFlags.isAuthenticatedPagesDiscoverable ? found.next : found.next?.authed ? undefined @@ -64,7 +64,7 @@ export async function withResolvedDocsContent({ apis: definition.apis, apisV2: definition.apisV2, pages: definition.pages, - featureFlags, + edgeFlags, mdxOptions: { files: definition.jsFiles, }, diff --git a/packages/fern-docs/cache/src/ApiDefinitionLoader.ts b/packages/fern-docs/cache/src/ApiDefinitionLoader.ts index 9281cc6856..e2e2c00ef9 100644 --- a/packages/fern-docs/cache/src/ApiDefinitionLoader.ts +++ b/packages/fern-docs/cache/src/ApiDefinitionLoader.ts @@ -11,8 +11,8 @@ import { type PruningNodeType, } from "@fern-api/fdr-sdk/api-definition"; import type * as FernDocs from "@fern-api/fdr-sdk/docs"; -import type { FeatureFlags } from "@fern-docs/utils"; -import { DEFAULT_FEATURE_FLAGS } from "@fern-docs/utils"; +import type { EdgeFlags } from "@fern-docs/utils"; +import { DEFAULT_EDGE_FLAGS } from "@fern-docs/utils"; import { HTTPSnippet, type TargetId } from "httpsnippet-lite"; import { UnreachableCaseError } from "ts-essentials"; import { ApiDefinitionKVCache } from "./ApiDefinitionKVCache"; @@ -37,7 +37,7 @@ const CLIENTS: HTTPSnippetClient[] = [ export class ApiDefinitionLoader { public clone = (): ApiDefinitionLoader => { return new ApiDefinitionLoader(this.domain, this.apiDefinitionId) - .withFlags(this.flags) + .withEdgeFlags(this.edgeFlags) .withEnvironment(this.environment) .withPrune(...this.prune) .withResolveDescriptions(this.resolve) @@ -66,9 +66,9 @@ export class ApiDefinitionLoader { this.cache = ApiDefinitionKVCache.getInstance(domain, apiDefinitionId); } - private flags: FeatureFlags = DEFAULT_FEATURE_FLAGS; - public withFlags = (flags: Partial): this => { - this.flags = { ...this.flags, ...flags }; + private edgeFlags: EdgeFlags = DEFAULT_EDGE_FLAGS; + public withEdgeFlags = (flags: Partial): this => { + this.edgeFlags = { ...this.edgeFlags, ...flags }; return this; }; @@ -124,7 +124,7 @@ export class ApiDefinitionLoader { } } if (v1.ok) { - return ApiDefinitionV1ToLatest.from(v1.body, this.flags).migrate(); + return ApiDefinitionV1ToLatest.from(v1.body, this.edgeFlags).migrate(); } if (!latest.ok) { @@ -193,7 +193,7 @@ export class ApiDefinitionLoader { definition = await this.resolveDescriptions(definition); } - if (this.flags.isHttpSnippetsEnabled) { + if (this.edgeFlags.isHttpSnippetsEnabled) { definition = await this.resolveHttpCodeSnippets(definition); } @@ -266,7 +266,7 @@ export class ApiDefinitionLoader { if ( targetId === "javascript" && snippets[APIV1Read.SupportedLanguage.Typescript]?.length && - !this.flags.alwaysEnableJavaScriptFetch + !this.edgeFlags.alwaysEnableJavaScriptFetch ) { continue; } diff --git a/packages/fern-docs/edge-config/src/getFeatureFlags.ts b/packages/fern-docs/edge-config/src/getEdgeFlags.ts similarity index 96% rename from packages/fern-docs/edge-config/src/getFeatureFlags.ts rename to packages/fern-docs/edge-config/src/getEdgeFlags.ts index f5163dc04b..d6b22f41d7 100644 --- a/packages/fern-docs/edge-config/src/getFeatureFlags.ts +++ b/packages/fern-docs/edge-config/src/getEdgeFlags.ts @@ -1,4 +1,4 @@ -import type { FeatureFlags } from "@fern-docs/utils"; +import type { EdgeFlags } from "@fern-docs/utils"; import { isCustomDomain, isDevelopment, @@ -9,7 +9,7 @@ import { getAll } from "@vercel/edge-config"; export const runtime = "edge"; -const FEATURE_FLAGS = [ +const EDGE_FLAGS = [ "api-playground-enabled" as const, "api-scrolling-disabled" as const, "whitelabeled" as const, @@ -43,13 +43,13 @@ const FEATURE_FLAGS = [ "search-v2" as const, ]; -type FeatureFlag = (typeof FEATURE_FLAGS)[number]; +type EdgeFlag = (typeof EDGE_FLAGS)[number]; -type EdgeConfigResponse = Record; +type EdgeConfigResponse = Record; -export async function getFeatureFlags(domain: string): Promise { +export async function getEdgeFlags(domain: string): Promise { try { - const config = await getAll(FEATURE_FLAGS); + const config = await getAll(EDGE_FLAGS); const isApiPlaygroundEnabled = checkDomainMatchesCustomers( domain, diff --git a/packages/fern-docs/edge-config/src/getLaunchDarklySettings.ts b/packages/fern-docs/edge-config/src/getLaunchDarklySettings.ts index 043efb6ae8..ad47725cbc 100644 --- a/packages/fern-docs/edge-config/src/getLaunchDarklySettings.ts +++ b/packages/fern-docs/edge-config/src/getLaunchDarklySettings.ts @@ -6,6 +6,7 @@ import { z } from "zod"; 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(), + "user-context-endpoint": z.string().optional(), }); export type LaunchDarklyEdgeConfig = z.infer< diff --git a/packages/fern-docs/edge-config/src/index.ts b/packages/fern-docs/edge-config/src/index.ts index b6ae5a4a2a..4ff643ce83 100644 --- a/packages/fern-docs/edge-config/src/index.ts +++ b/packages/fern-docs/edge-config/src/index.ts @@ -1,6 +1,6 @@ export * from "./getAuthEdgeConfig"; export * from "./getCustomerAnalytics"; -export * from "./getFeatureFlags"; +export * from "./getEdgeFlags"; export * from "./getInkeepSettings"; export * from "./getLaunchDarklySettings"; export * from "./getPreviewUrlAuthConfig"; diff --git a/packages/fern-docs/local-preview-bundle/src/utils/getDocsPageProps.ts b/packages/fern-docs/local-preview-bundle/src/utils/getDocsPageProps.ts index ea254a7f86..01846b9efd 100644 --- a/packages/fern-docs/local-preview-bundle/src/utils/getDocsPageProps.ts +++ b/packages/fern-docs/local-preview-bundle/src/utils/getDocsPageProps.ts @@ -12,9 +12,9 @@ import { } from "@fern-docs/ui"; import { serializeMdx } from "@fern-docs/ui/bundlers/next-mdx-remote"; import { - DEFAULT_FEATURE_FLAGS, + DEFAULT_EDGE_FLAGS, + EdgeFlags, getRedirectForPath, - type FeatureFlags, } from "@fern-docs/utils"; import { SidebarTab } from "@fern-platform/fdr-utils"; import type { GetServerSidePropsResult } from "next"; @@ -69,7 +69,7 @@ export async function getDocsPageProps( } // TODO: get feature flags from the API - const featureFlags: FeatureFlags = DEFAULT_FEATURE_FLAGS; + const edgeFlags: EdgeFlags = DEFAULT_EDGE_FLAGS; const content = await resolveDocsContent({ domain: docs.baseUrl.domain, @@ -83,7 +83,7 @@ export async function getDocsPageProps( apis: docs.definition.apis, apisV2: docs.definition.apisV2, pages: docs.definition.pages, - featureFlags, + edgeFlags, mdxOptions: { files: docs.definition.jsFiles, }, @@ -218,7 +218,7 @@ export async function getDocsPageProps( sidebar: node.sidebar, trailingSlash: false, }, - featureFlags, + edgeFlags, apis: Object.keys(docs.definition.apis).map(FdrAPI.ApiDefinitionId), seo: getSeoProps( docs.baseUrl.domain, @@ -244,6 +244,7 @@ export async function getDocsPageProps( docs.definition.filesV2, node.tabs.length > 0 ), + featureFlags: undefined, // TODO: match loading logic in withInitialProps ? }; // if the user specifies a github navbar link, grab the repo info from it and save it as an SWR fallback diff --git a/packages/fern-docs/syntax-highlighter/src/CodeBlockWithClipboardButton.tsx b/packages/fern-docs/syntax-highlighter/src/CodeBlockWithClipboardButton.tsx index 0565cb9d32..98fd7855d6 100644 --- a/packages/fern-docs/syntax-highlighter/src/CodeBlockWithClipboardButton.tsx +++ b/packages/fern-docs/syntax-highlighter/src/CodeBlockWithClipboardButton.tsx @@ -1,6 +1,6 @@ import { CopyToClipboardButton, cn } from "@fern-docs/components"; import React, { PropsWithChildren } from "react"; -import { useFeatureFlags } from "./SyntaxHighlighterFeatureFlags"; +import { useEdgeFlags } from "./SyntaxHighlighterEdgeFlags"; type CodeBlockWithClipboardButtonProps = { code: string; @@ -9,7 +9,7 @@ type CodeBlockWithClipboardButtonProps = { export const CodeBlockWithClipboardButton: React.FC< PropsWithChildren > = ({ code, children }) => { - const { isDarkCodeEnabled } = useFeatureFlags(); + const { isDarkCodeEnabled } = useEdgeFlags(); return (
): ReactNode { + return ( + + {children} + + ); +} + +export const useEdgeFlags = (): { isDarkCodeEnabled: boolean } => { + return useContext(SyntaxHighlighterEdgeFlags); +}; diff --git a/packages/fern-docs/syntax-highlighter/src/SyntaxHighlighterFeatureFlags.tsx b/packages/fern-docs/syntax-highlighter/src/SyntaxHighlighterFeatureFlags.tsx deleted file mode 100644 index 11dcca2515..0000000000 --- a/packages/fern-docs/syntax-highlighter/src/SyntaxHighlighterFeatureFlags.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { - createContext, - useContext, - type PropsWithChildren, - type ReactNode, -} from "react"; - -export const SyntaxHighlighterFeatureFlags = createContext({ - isDarkCodeEnabled: false, -}); - -export function SyntaxHighlighterFeatureFlagsProvider({ - children, - isDarkCodeEnabled, -}: PropsWithChildren<{ isDarkCodeEnabled: boolean }>): ReactNode { - return ( - - {children} - - ); -} - -export const useFeatureFlags = (): { isDarkCodeEnabled: boolean } => { - return useContext(SyntaxHighlighterFeatureFlags); -}; diff --git a/packages/fern-docs/syntax-highlighter/src/index.ts b/packages/fern-docs/syntax-highlighter/src/index.ts index a7c9aa4b13..4d43b52774 100644 --- a/packages/fern-docs/syntax-highlighter/src/index.ts +++ b/packages/fern-docs/syntax-highlighter/src/index.ts @@ -1,4 +1,4 @@ export * from "./CodeBlockWithClipboardButton"; export * from "./FernSyntaxHighlighter"; export type { ScrollToHandle } from "./FernSyntaxHighlighterTokens"; -export { SyntaxHighlighterFeatureFlagsProvider } from "./SyntaxHighlighterFeatureFlags"; +export { SyntaxHighlighterEdgeFlagsProvider } from "./SyntaxHighlighterEdgeFlags"; diff --git a/packages/fern-docs/ui/package.json b/packages/fern-docs/ui/package.json index d41e525cd4..862df55b40 100644 --- a/packages/fern-docs/ui/package.json +++ b/packages/fern-docs/ui/package.json @@ -91,7 +91,7 @@ "jotai-effect": "^1.0.5", "jotai-location": "^0.5.5", "jsonpath": "^1.1.1", - "launchdarkly-js-client-sdk": "^3.4.0", + "launchdarkly-react-client-sdk": "^3.6.0", "mdx-bundler": "^10.0.2", "mermaid": "^11.2.1", "moment": "^2.30.1", diff --git a/packages/fern-docs/ui/src/api-reference/endpoints/EndpointContentLeft.tsx b/packages/fern-docs/ui/src/api-reference/endpoints/EndpointContentLeft.tsx index 1caa231510..da8706415b 100644 --- a/packages/fern-docs/ui/src/api-reference/endpoints/EndpointContentLeft.tsx +++ b/packages/fern-docs/ui/src/api-reference/endpoints/EndpointContentLeft.tsx @@ -4,7 +4,7 @@ import { visitDiscriminatedUnion } from "@fern-api/ui-core-utils"; import { sortBy } from "es-toolkit/array"; import { camelCase, upperFirst } from "es-toolkit/string"; import { memo, useEffect, useRef } from "react"; -import { useFeatureFlags } from "../../atoms"; +import { useEdgeFlags } from "../../atoms"; import { Markdown } from "../../mdx/Markdown"; import { JsonPropertyPath } from "../examples/JsonPropertyPath"; import { TypeComponentSeparator } from "../types/TypeComponentSeparator"; @@ -98,7 +98,7 @@ const UnmemoizedEndpointContentLeft: React.FC = ({ }; }, [selectedError, setSelectedError]); - const { isAuthEnabledInDocs } = useFeatureFlags(); + const { isAuthEnabledInDocs } = useEdgeFlags(); let authHeader: ApiDefinition.ObjectProperty | undefined; if (auth && isAuthEnabledInDocs) { diff --git a/packages/fern-docs/ui/src/api-reference/endpoints/EndpointResponseSection.tsx b/packages/fern-docs/ui/src/api-reference/endpoints/EndpointResponseSection.tsx index 271a8e99bc..fe51e65c7b 100644 --- a/packages/fern-docs/ui/src/api-reference/endpoints/EndpointResponseSection.tsx +++ b/packages/fern-docs/ui/src/api-reference/endpoints/EndpointResponseSection.tsx @@ -1,6 +1,6 @@ import * as ApiDefinition from "@fern-api/fdr-sdk/api-definition"; import * as FernNavigation from "@fern-api/fdr-sdk/navigation"; -import { useFeatureFlags } from "../../atoms"; +import { useEdgeFlags } from "../../atoms"; import { Markdown } from "../../mdx/Markdown"; import { renderTypeShorthand } from "../../type-shorthand"; import { JsonPropertyPath } from "../examples/JsonPropertyPath"; @@ -30,7 +30,7 @@ export const EndpointResponseSection: React.FC< slug, types, }) => { - const { isAudioFileDownloadSpanSummary } = useFeatureFlags(); + const { isAudioFileDownloadSpanSummary } = useEdgeFlags(); return (
diff --git a/packages/fern-docs/ui/src/api-reference/examples/AudioExample.tsx b/packages/fern-docs/ui/src/api-reference/examples/AudioExample.tsx index 3860dacf86..644af62c15 100644 --- a/packages/fern-docs/ui/src/api-reference/examples/AudioExample.tsx +++ b/packages/fern-docs/ui/src/api-reference/examples/AudioExample.tsx @@ -1,6 +1,6 @@ import { FernAudioPlayer } from "@fern-docs/components"; import { FC } from "react"; -import { useFeatureFlags } from "../../atoms"; +import { useEdgeFlags } from "../../atoms"; import { FernErrorBoundary } from "../../components/FernErrorBoundary"; import { TitledExample } from "./TitledExample"; @@ -10,7 +10,7 @@ export declare namespace AudioExample { } const AudioExampleInternal: FC = ({ ...props }) => { - const { isAudioExampleInternal } = useFeatureFlags(); + const { isAudioExampleInternal } = useEdgeFlags(); if (!isAudioExampleInternal) { return null; diff --git a/packages/fern-docs/ui/src/api-reference/examples/CodeSnippetExample.tsx b/packages/fern-docs/ui/src/api-reference/examples/CodeSnippetExample.tsx index 4dafbfaef6..7512cebd23 100644 --- a/packages/fern-docs/ui/src/api-reference/examples/CodeSnippetExample.tsx +++ b/packages/fern-docs/ui/src/api-reference/examples/CodeSnippetExample.tsx @@ -5,7 +5,7 @@ import { import { useResizeObserver } from "@fern-ui/react-commons"; import clsx from "clsx"; import { FC, createRef, useCallback, useEffect, useMemo } from "react"; -import { useFeatureFlags } from "../../atoms"; +import { useEdgeFlags } from "../../atoms"; import { FernErrorBoundary } from "../../components/FernErrorBoundary"; import { JsonPropertyPath } from "./JsonPropertyPath"; import { TitledExample } from "./TitledExample"; @@ -38,7 +38,7 @@ const CodeSnippetExampleInternal: FC = ({ className, ...props }) => { - const { isDarkCodeEnabled } = useFeatureFlags(); + const { isDarkCodeEnabled } = useEdgeFlags(); const codeBlockRef = createRef(); const viewportRef = createRef(); diff --git a/packages/fern-docs/ui/src/atoms/apis.ts b/packages/fern-docs/ui/src/atoms/apis.ts index 148639b476..35c33e9ff2 100644 --- a/packages/fern-docs/ui/src/atoms/apis.ts +++ b/packages/fern-docs/ui/src/atoms/apis.ts @@ -7,7 +7,7 @@ import { useEffect } from "react"; import { useMemoOne } from "use-memo-one"; import { useIsLocalPreview } from "../contexts/local-preview"; import { DOCS_ATOM } from "./docs"; -import { FEATURE_FLAGS_ATOM } from "./flags"; +import { EDGE_FLAGS_ATOM } from "./flags"; import { RESOLVED_API_DEFINITION_ATOM, RESOLVED_PATH_ATOM } from "./navigation"; const SETTABLE_APIS_ATOM = atom< @@ -72,7 +72,7 @@ const IS_API_REFERENCE_PAGINATED = atom((get) => { if (content.type === "api-endpoint-page") { return true; } - return get(FEATURE_FLAGS_ATOM).isApiScrollingDisabled; + return get(EDGE_FLAGS_ATOM).isApiScrollingDisabled; }); export function useIsApiReferencePaginated(): boolean { diff --git a/packages/fern-docs/ui/src/atoms/docs.ts b/packages/fern-docs/ui/src/atoms/docs.ts index 82ee3355b1..f003c99c02 100644 --- a/packages/fern-docs/ui/src/atoms/docs.ts +++ b/packages/fern-docs/ui/src/atoms/docs.ts @@ -1,6 +1,6 @@ import { DocsV1Read } from "@fern-api/fdr-sdk"; import * as FernNavigation from "@fern-api/fdr-sdk/navigation"; -import { DEFAULT_FEATURE_FLAGS } from "@fern-docs/utils"; +import { DEFAULT_EDGE_FLAGS } from "@fern-docs/utils"; import { atomWithReducer, useHydrateAtoms } from "jotai/utils"; import type { PropsWithChildren, ReactNode } from "react"; import type { DocsProps } from "./types"; @@ -63,7 +63,7 @@ export const EMPTY_DOCS_STATE: DocsProps = { apis: {}, endpointIdsToSlugs: {}, }, - featureFlags: DEFAULT_FEATURE_FLAGS, + edgeFlags: DEFAULT_EDGE_FLAGS, apis: [], seo: {}, analytics: undefined, @@ -73,6 +73,7 @@ export const EMPTY_DOCS_STATE: DocsProps = { user: undefined, defaultLang: "curl", stylesheet: "", + featureFlags: undefined, }; export const DOCS_ATOM = atomWithReducer( diff --git a/packages/fern-docs/ui/src/atoms/flags.ts b/packages/fern-docs/ui/src/atoms/flags.ts index 0132e5b3c6..f139f456b6 100644 --- a/packages/fern-docs/ui/src/atoms/flags.ts +++ b/packages/fern-docs/ui/src/atoms/flags.ts @@ -1,23 +1,23 @@ -import type { FeatureFlags } from "@fern-docs/utils"; +import type { EdgeFlags } from "@fern-docs/utils"; import { isEqual } from "es-toolkit/predicate"; import { atom, useAtomValue } from "jotai"; import { selectAtom } from "jotai/utils"; import { useMemoOne } from "use-memo-one"; import { DOCS_ATOM } from "./docs"; -export const FEATURE_FLAGS_ATOM = selectAtom( +export const EDGE_FLAGS_ATOM = selectAtom( DOCS_ATOM, - (docs) => docs.featureFlags, + (docs) => docs.edgeFlags, isEqual ); -FEATURE_FLAGS_ATOM.debugLabel = "FEATURE_FLAGS_ATOM"; +EDGE_FLAGS_ATOM.debugLabel = "EDGE_FLAGS_ATOM"; -export function useFeatureFlags(): FeatureFlags { - return useAtomValue(FEATURE_FLAGS_ATOM); +export function useEdgeFlags(): EdgeFlags { + return useAtomValue(EDGE_FLAGS_ATOM); } -export function useFeatureFlag(flag: keyof FeatureFlags): boolean { +export function useEdgeFlag(flag: keyof EdgeFlags): boolean { return useAtomValue( - useMemoOne(() => atom((get) => !!get(FEATURE_FLAGS_ATOM)[flag]), [flag]) + useMemoOne(() => atom((get) => !!get(EDGE_FLAGS_ATOM)[flag]), [flag]) ); } diff --git a/packages/fern-docs/ui/src/atoms/launchdarkly.ts b/packages/fern-docs/ui/src/atoms/launchdarkly.ts deleted file mode 100644 index 32d2d47553..0000000000 --- a/packages/fern-docs/ui/src/atoms/launchdarkly.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { atom, useAtomValue, useSetAtom } from "jotai"; -import * as LDClient from "launchdarkly-js-client-sdk"; -import { useCallback, useEffect, useState } from "react"; -import { useApiRouteSWR } from "../hooks/useApiRouteSWR"; - -// NOTE do not export this file in any index.ts file so that it can be properly tree-shaken -// otherwise we risk importing launchdarkly-js-client-sdk in all of our bundles - -// TODO: consolidate the types with the edge-config package -interface LaunchDarklyInfo { - clientSideId: string; - kind: "multi"; - user: - | { anonymous: true } - | { - key: string; - email?: string; - name?: string; - }; - device: { - key: string; - [key: string]: unknown; - }; -} - -// this is a singleton atom that initializes the LaunchDarkly client-side SDK -const LD_CLIENT_ATOM = atom(undefined); - -const SET_LAUNCH_DARKLY_INFO_ATOM = atom( - undefined, - async (get, set, info: LaunchDarklyInfo) => { - const client = get(LD_CLIENT_ATOM); - const { clientSideId, ...context } = info; - - if (client) { - await client.identify(context); - return; - } else { - const client = LDClient.initialize(clientSideId, context); - await client.waitForInitialization(); - set(LD_CLIENT_ATOM, client); - } - } -); - -// TODO: support non-boolean flags -export const useLaunchDarklyFlag = ( - flag: string, - equals = true, - not = false -): boolean => { - useInitLaunchDarklyClient(); - - const client = useAtomValue(LD_CLIENT_ATOM); - - // TODO: bootstrap the flag value from the server, and/or local storage - const getFlagEnabled = useCallback(() => { - if (!client) { - return not; - } - // force the flag to be a boolean: - const isTrue = client.variation(flag, false) === equals; - return not ? !isTrue : isTrue; - }, [client, equals, flag, not]); - - const [enabled, setEnabled] = useState(getFlagEnabled); - - // listen for changes to the flag - 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; -}; - -// since useSWR is cached globally, we can use this hook in multiple components without worrying about multiple requests -function useInitLaunchDarklyClient() { - const setInfo = useSetAtom(SET_LAUNCH_DARKLY_INFO_ATOM); - useApiRouteSWR("/api/fern-docs/integrations/launchdarkly", { - onSuccess(data) { - void setInfo(data); - }, - }); -} diff --git a/packages/fern-docs/ui/src/atoms/logo.ts b/packages/fern-docs/ui/src/atoms/logo.ts index c2b4409cc2..72dd12af84 100644 --- a/packages/fern-docs/ui/src/atoms/logo.ts +++ b/packages/fern-docs/ui/src/atoms/logo.ts @@ -6,10 +6,10 @@ import { } from "@fern-api/fdr-sdk/docs"; import { atom, useAtomValue } from "jotai"; import { DOCS_ATOM } from "./docs"; -import { FEATURE_FLAGS_ATOM } from "./flags"; +import { EDGE_FLAGS_ATOM } from "./flags"; export const LOGO_TEXT_ATOM = atom((get) => - get(FEATURE_FLAGS_ATOM).isDocsLogoTextEnabled ? "docs" : undefined + get(EDGE_FLAGS_ATOM).isDocsLogoTextEnabled ? "docs" : undefined ); LOGO_TEXT_ATOM.debugLabel = "LOGO_TEXT_ATOM"; diff --git a/packages/fern-docs/ui/src/atoms/playground.ts b/packages/fern-docs/ui/src/atoms/playground.ts index ba285401f4..2bcc6bbb3e 100644 --- a/packages/fern-docs/ui/src/atoms/playground.ts +++ b/packages/fern-docs/ui/src/atoms/playground.ts @@ -38,7 +38,7 @@ import { } from "../playground/utils"; import { pascalCaseHeaderKeys } from "../playground/utils/header-key-case"; import { FERN_USER_ATOM } from "./auth"; -import { FEATURE_FLAGS_ATOM } from "./flags"; +import { EDGE_FLAGS_ATOM } from "./flags"; import { useAtomEffect } from "./hooks"; import { HEADER_HEIGHT_ATOM } from "./layout"; import { LOCATION_ATOM } from "./location"; @@ -50,7 +50,7 @@ const PLAYGROUND_IS_OPEN_ATOM = atom(false); PLAYGROUND_IS_OPEN_ATOM.debugLabel = "PLAYGROUND_IS_OPEN_ATOM"; export const IS_PLAYGROUND_ENABLED_ATOM = atom( - (get) => get(FEATURE_FLAGS_ATOM).isApiPlaygroundEnabled + (get) => get(EDGE_FLAGS_ATOM).isApiPlaygroundEnabled ); export const MAX_PLAYGROUND_HEIGHT_ATOM = atom((get) => { diff --git a/packages/fern-docs/ui/src/atoms/sidebar.ts b/packages/fern-docs/ui/src/atoms/sidebar.ts index 66539d4d8f..f60a7c6dcb 100644 --- a/packages/fern-docs/ui/src/atoms/sidebar.ts +++ b/packages/fern-docs/ui/src/atoms/sidebar.ts @@ -3,7 +3,7 @@ import { atom, useAtomValue, useSetAtom } from "jotai"; import { RESET, atomWithDefault, useAtomCallback } from "jotai/utils"; import { useCallback } from "react"; import { useCallbackOne, useMemoOne } from "use-memo-one"; -import { FEATURE_FLAGS_ATOM } from "./flags"; +import { EDGE_FLAGS_ATOM } from "./flags"; import { useAtomEffect } from "./hooks"; import { DOCS_LAYOUT_ATOM } from "./layout"; import { @@ -226,7 +226,7 @@ export const useToggleExpandedSidebarNode = ( }; } else { const parents = childToParentsMap.get(nodeId) ?? []; - const { isApiScrollingDisabled } = get(FEATURE_FLAGS_ATOM); + const { isApiScrollingDisabled } = get(EDGE_FLAGS_ATOM); // if long scrolling is enabled, implicitly "expand" its parent nodes if (!isApiScrollingDisabled) { diff --git a/packages/fern-docs/ui/src/atoms/types.ts b/packages/fern-docs/ui/src/atoms/types.ts index baeb416acf..4dc098e159 100644 --- a/packages/fern-docs/ui/src/atoms/types.ts +++ b/packages/fern-docs/ui/src/atoms/types.ts @@ -7,7 +7,7 @@ import type * as FernDocs from "@fern-api/fdr-sdk/docs"; import type * as FernNavigation from "@fern-api/fdr-sdk/navigation"; import type { FernUser } from "@fern-docs/auth"; import { NextSeoProps } from "@fern-docs/next-seo"; -import type { FeatureFlags } from "@fern-docs/utils"; +import type { EdgeFlags } from "@fern-docs/utils"; import { ColorsConfig, SidebarTab, @@ -51,6 +51,15 @@ export interface GithubNavbarLink { export type NavbarLink = DefaultNavbarLink | GithubNavbarLink; +export interface LaunchDarklyInfo { + clientSideId: string; + userContextEndpoint: string; +} + +export interface FeatureFlags { + launchDarkly: LaunchDarklyInfo | undefined; +} + export interface DocsProps { baseUrl: DocsV2Read.BaseUrl; navigation: NavigationProps; @@ -65,7 +74,7 @@ export interface DocsProps { logoHref: DocsV1Read.Url | undefined; files: Record; content: DocsContent; - featureFlags: FeatureFlags; + edgeFlags: EdgeFlags; apis: FdrAPI.ApiDefinitionId[]; seo: NextSeoProps; analytics: CustomerAnalytics | undefined; // deprecated @@ -75,4 +84,5 @@ export interface DocsProps { user: FernUser | undefined; defaultLang: DocsV1Read.ProgrammingLanguage; stylesheet: string; + featureFlags: FeatureFlags | undefined; } diff --git a/packages/fern-docs/ui/src/docs/DocsMainContent.tsx b/packages/fern-docs/ui/src/docs/DocsMainContent.tsx index a4fb62b04c..5992ea9bdf 100644 --- a/packages/fern-docs/ui/src/docs/DocsMainContent.tsx +++ b/packages/fern-docs/ui/src/docs/DocsMainContent.tsx @@ -2,7 +2,7 @@ import dynamic from "next/dynamic"; import { useSearchParams } from "next/navigation"; import { Fragment, ReactElement, memo } from "react"; import { UnreachableCaseError } from "ts-essentials"; -import { useFeatureFlag, useIsReady } from "../atoms"; +import { useEdgeFlag, useIsReady } from "../atoms"; import { FernErrorBoundary } from "../components/FernErrorBoundary"; import type { DocsContent } from "../resolver/DocsContent"; @@ -67,7 +67,7 @@ export const DocsMainContent = memo(function DocsMainContent({ }: { content: DocsContent; }): ReactElement { - const isInlineFeedbackEnabled = useFeatureFlag("isInlineFeedbackEnabled"); + const isInlineFeedbackEnabled = useEdgeFlag("isInlineFeedbackEnabled"); const searchParams = useSearchParams(); const FeedbackPopoverProvider = isInlineFeedbackEnabled diff --git a/packages/fern-docs/ui/src/docs/DocsPage.tsx b/packages/fern-docs/ui/src/docs/DocsPage.tsx index 3ecfdcfa2a..0f6dc8c3c8 100644 --- a/packages/fern-docs/ui/src/docs/DocsPage.tsx +++ b/packages/fern-docs/ui/src/docs/DocsPage.tsx @@ -2,7 +2,7 @@ import dynamic from "next/dynamic"; import { ReactElement } from "react"; import { HydrateAtoms, - useFeatureFlag, + useEdgeFlag, useMessageHandler, useSetJustNavigated, type DocsProps, @@ -59,8 +59,8 @@ export function DocsPage(pageProps: DocsProps): ReactElement | null { } ); - const isSearchV2Enabled = useFeatureFlag("isSearchV2Enabled"); - const isApiPlaygroundEnabled = useFeatureFlag("isApiPlaygroundEnabled"); + const isSearchV2Enabled = useEdgeFlag("isSearchV2Enabled"); + const isApiPlaygroundEnabled = useEdgeFlag("isApiPlaygroundEnabled"); return ( <> diff --git a/packages/fern-docs/ui/src/docs/NextApp.tsx b/packages/fern-docs/ui/src/docs/NextApp.tsx index a41dbfec68..1329686b49 100644 --- a/packages/fern-docs/ui/src/docs/NextApp.tsx +++ b/packages/fern-docs/ui/src/docs/NextApp.tsx @@ -1,6 +1,6 @@ import { EMPTY_OBJECT } from "@fern-api/ui-core-utils"; import { FernTooltipProvider, Toaster } from "@fern-docs/components"; -import { SyntaxHighlighterFeatureFlagsProvider } from "@fern-docs/syntax-highlighter"; +import { SyntaxHighlighterEdgeFlagsProvider } from "@fern-docs/syntax-highlighter"; import { Provider as JotaiProvider } from "jotai"; import type { AppProps } from "next/app"; import { ReactElement } from "react"; @@ -12,6 +12,7 @@ import { LocalPreviewContextProvider } from "../contexts/local-preview"; import "../css/globals.scss"; import { NextNProgress } from "../header/NProgress"; import { useInterceptNextDataHref } from "../hooks/useInterceptNextDataHref"; +import { FeatureFlagProvider } from "../mdx/components/feature/FeatureFlagProvider"; import { ThemeScript } from "../themes/ThemeScript"; export function NextApp({ @@ -29,33 +30,35 @@ export function NextApp({ return ( - - - - - - - + + + + + + - - - - - - + + + + + + + ); diff --git a/packages/fern-docs/ui/src/hooks/useConsoleMessage.ts b/packages/fern-docs/ui/src/hooks/useConsoleMessage.ts index 75258de159..cc328ba11d 100644 --- a/packages/fern-docs/ui/src/hooks/useConsoleMessage.ts +++ b/packages/fern-docs/ui/src/hooks/useConsoleMessage.ts @@ -1,10 +1,10 @@ import { useEffect } from "react"; -import { useFeatureFlags } from "../atoms"; +import { useEdgeFlags } from "../atoms"; let hasBeenCalled = false; export const useConsoleMessage = (): void => { - const { isWhitelabeled } = useFeatureFlags(); + const { isWhitelabeled } = useEdgeFlags(); useEffect(() => { if (hasBeenCalled || isWhitelabeled) { diff --git a/packages/fern-docs/ui/src/hooks/useStandardProxyEnvironment.ts b/packages/fern-docs/ui/src/hooks/useStandardProxyEnvironment.ts index 4d4d1dc548..f354877ed8 100644 --- a/packages/fern-docs/ui/src/hooks/useStandardProxyEnvironment.ts +++ b/packages/fern-docs/ui/src/hooks/useStandardProxyEnvironment.ts @@ -1,6 +1,6 @@ import { withDefaultProtocol } from "@fern-api/ui-core-utils"; import { once } from "es-toolkit/function"; -import { useBasePath, useFeatureFlags } from "../atoms"; +import { useBasePath, useEdgeFlags } from "../atoms"; import { useApiRoute } from "./useApiRoute"; const APP_BUILDWITHFERN_COM = "app.buildwithfern.com"; @@ -26,7 +26,7 @@ export const getAppBuildwithfernCom = once((): string => { export function useStandardProxyEnvironment(): string { const basePath = useBasePath(); - const { proxyShouldUseAppBuildwithfernCom } = useFeatureFlags(); + const { proxyShouldUseAppBuildwithfernCom } = useEdgeFlags(); const proxyBasePath = proxyShouldUseAppBuildwithfernCom ? getAppBuildwithfernCom() : basePath; diff --git a/packages/fern-docs/ui/src/mdx/components/code/CodeGroup.tsx b/packages/fern-docs/ui/src/mdx/components/code/CodeGroup.tsx index 5b56fd77ff..ca70f2dd3b 100644 --- a/packages/fern-docs/ui/src/mdx/components/code/CodeGroup.tsx +++ b/packages/fern-docs/ui/src/mdx/components/code/CodeGroup.tsx @@ -6,7 +6,7 @@ import { import * as Tabs from "@radix-ui/react-tabs"; import clsx from "clsx"; import { useState } from "react"; -import { useFeatureFlags } from "../../../atoms"; +import { useEdgeFlags } from "../../../atoms"; import { HorizontalOverflowMask } from "../../../components/HorizontalOverflowMask"; export declare namespace CodeGroup { @@ -22,7 +22,7 @@ export declare namespace CodeGroup { export const CodeGroup: React.FC> = ({ items, }) => { - const { isDarkCodeEnabled } = useFeatureFlags(); + const { isDarkCodeEnabled } = useEdgeFlags(); const [selectedTabIndex, setSelectedTabIndex] = useState(0); const containerClass = clsx( diff --git a/packages/fern-docs/ui/src/mdx/components/feature/Feature.tsx b/packages/fern-docs/ui/src/mdx/components/feature/Feature.tsx new file mode 100644 index 0000000000..2302f21f3c --- /dev/null +++ b/packages/fern-docs/ui/src/mdx/components/feature/Feature.tsx @@ -0,0 +1,21 @@ +import dynamic from "next/dynamic"; + +const LDFeature = dynamic( + () => import("./LDFeature").then((mod) => mod.LDFeature), + { ssr: true } +); + +export declare namespace Feature { + export interface Props { + flag: string; + flagDefaultValue?: T; + match?: T; + children: React.ReactNode; + } +} + +// TODO: This becomes an indirection point where we can use different feature flag implementations +// with different providers depending on config +export const Feature = (props: Feature.Props): React.ReactNode => ( + +); diff --git a/packages/fern-docs/ui/src/mdx/components/feature/FeatureFlagProvider.tsx b/packages/fern-docs/ui/src/mdx/components/feature/FeatureFlagProvider.tsx new file mode 100644 index 0000000000..105cee7ed2 --- /dev/null +++ b/packages/fern-docs/ui/src/mdx/components/feature/FeatureFlagProvider.tsx @@ -0,0 +1,32 @@ +import dynamic from "next/dynamic"; +import { FC, ReactNode } from "react"; +import { DocsProps } from "../../.."; + +const LDFeatureFlagProvider = dynamic(() => + import("./LDFeatureFlagProvider").then((mod) => mod.LDFeatureFlagProvider) +); + +interface FeatureFlagProviderProps { + pageProps: DocsProps | undefined; + children: ReactNode; +} + +export const FeatureFlagProvider: FC = ({ + pageProps, + children, +}) => { + const launchDarklyInfo = pageProps?.featureFlags?.launchDarkly; + + if (!launchDarklyInfo) { + return <>{children}; + } + + return ( + + {children} + + ); +}; diff --git a/packages/fern-docs/ui/src/mdx/components/feature/LDFeature.tsx b/packages/fern-docs/ui/src/mdx/components/feature/LDFeature.tsx new file mode 100644 index 0000000000..5b073fb281 --- /dev/null +++ b/packages/fern-docs/ui/src/mdx/components/feature/LDFeature.tsx @@ -0,0 +1,43 @@ +import { camelCase } from "es-toolkit/string"; +import { LDFlagSet, useFlags } from "launchdarkly-react-client-sdk"; +import { Feature } from "./Feature"; + +const ldFlagPredicate = ( + flagKey: string, + defaultValue: T +): ((flags: LDFlagSet) => T) => { + return (flags: LDFlagSet) => { + // Camel case the flag key here to match logic from LaunchDarkly's Gatsby plugin. + // They use snake-case keys in their UI but camelCase in their React SDK and do this to ease + // the developer experience; we're doing the same thing to be consistent with them. + // See https://github.com/launchdarkly/LaunchDarkly-Docs/blob/95cebf9ef4841da96ddfec9dd6e3ed76455025d0/src/flags/flagPredicate.ts#L6 + const camelKey = camelCase(flagKey); + const flagValue = flags[camelKey]; + + if (typeof flagValue === "undefined") { + return defaultValue; + } + + return flagValue as T; + }; +}; + +export const LDFeature: (props: Feature.Props) => React.ReactNode = ({ + flag, + flagDefaultValue, + match, + children, +}) => { + const flags = useFlags(); + const flagPredicate = ldFlagPredicate(flag, flagDefaultValue); + const flagValue = flagPredicate(flags); + + // If match is undefined, show content when flag evaluates to true + const neededValue = typeof match === "undefined" ? true : match; + + if (typeof flagValue !== "undefined" && flagValue === neededValue) { + return <>{children}; + } + + return null; +}; diff --git a/packages/fern-docs/ui/src/mdx/components/feature/LDFeatureFlagProvider.tsx b/packages/fern-docs/ui/src/mdx/components/feature/LDFeatureFlagProvider.tsx new file mode 100644 index 0000000000..526fde7204 --- /dev/null +++ b/packages/fern-docs/ui/src/mdx/components/feature/LDFeatureFlagProvider.tsx @@ -0,0 +1,46 @@ +import { LDProvider, useLDClient } from "launchdarkly-react-client-sdk"; +import { FC, ReactNode, useEffect } from "react"; + +interface Props { + clientSideId: string; + userContextEndpoint: string; + children: ReactNode; +} + +export const LDFeatureFlagProvider: FC = ({ + clientSideId, + userContextEndpoint, + children, +}) => { + return ( + + + {children} + + + ); +}; + +const IdentifyWrapper = ({ + children, + userContextEndpoint, +}: { + children: ReactNode; + userContextEndpoint: string; +}) => { + const ldClient = useLDClient(); + + useEffect(() => { + // TODO: have this context be set in page props maybe? + const getAndSetLdContext = async () => { + // TODO: switch from fetch to useApiRouteSWR + const response = await fetch(userContextEndpoint); + const data = await response.json(); + void ldClient?.identify(data); + }; + + void getAndSetLdContext(); + }, [userContextEndpoint, ldClient]); + + return <>{children}; +}; diff --git a/packages/fern-docs/ui/src/mdx/components/feature/index.ts b/packages/fern-docs/ui/src/mdx/components/feature/index.ts new file mode 100644 index 0000000000..739e2fd3a1 --- /dev/null +++ b/packages/fern-docs/ui/src/mdx/components/feature/index.ts @@ -0,0 +1 @@ +export * from "./Feature"; diff --git a/packages/fern-docs/ui/src/mdx/components/html/image.tsx b/packages/fern-docs/ui/src/mdx/components/html/image.tsx index 09709fb89f..856f789f1d 100644 --- a/packages/fern-docs/ui/src/mdx/components/html/image.tsx +++ b/packages/fern-docs/ui/src/mdx/components/html/image.tsx @@ -10,7 +10,7 @@ import { useContext, } from "react"; import Zoom from "react-medium-image-zoom"; -import { FILES_ATOM, useFeatureFlags } from "../../../atoms"; +import { FILES_ATOM, useEdgeFlags } from "../../../atoms"; import { FernImage } from "../../../components/FernImage"; import { useFrontmatter } from "../../../contexts/frontmatter"; import { toPixelValue } from "../../../util/to-pixel-value"; @@ -112,7 +112,7 @@ function useIsImageZoomDisabled({ enableZoom: boolean; }) { const isImageZoomDisabledContext = useContext(NoZoomContext); - const isImageZoomDisabledFeatureFlag = useFeatureFlags().isImageZoomDisabled; + const isImageZoomDisabledFeatureFlag = useEdgeFlags().isImageZoomDisabled; const { "no-image-zoom": isImageZoomDisabledFrontmatter, layout } = useFrontmatter(); diff --git a/packages/fern-docs/ui/src/mdx/components/index.tsx b/packages/fern-docs/ui/src/mdx/components/index.tsx index 9992bafc09..6a76860eb2 100644 --- a/packages/fern-docs/ui/src/mdx/components/index.tsx +++ b/packages/fern-docs/ui/src/mdx/components/index.tsx @@ -28,6 +28,7 @@ import { ClientLibraries } from "./client-libraries"; import { CodeBlock } from "./code/CodeBlock"; import { CodeGroup } from "./code/CodeGroup"; import { Column, ColumnGroup } from "./columns"; +import { Feature } from "./feature"; import { Frame } from "./frame"; import { A, HeadingRenderer, Image, Li, Ol, Strong, Ul } from "./html"; import { Table } from "./html-table"; @@ -41,10 +42,6 @@ import { Step, StepGroup } from "./steps"; import { TabGroup } from "./tabs"; import { Tooltip } from "./tooltip"; -const LaunchDarkly = dynamic(() => - import("./launchdarkly/LaunchDarkly").then((mod) => mod.LaunchDarkly) -); - const ElevenLabsWaveform = dynamic(() => import("./waveform/WaveformComplex").then((mod) => mod.default) ); @@ -66,10 +63,10 @@ const FERN_COMPONENTS = { ColumnGroup, EndpointRequestSnippet, EndpointResponseSnippet, + Feature, Frame, Icon: RemoteFontAwesomeIcon, If, - LaunchDarkly, Mermaid, ParamField, Step, diff --git a/packages/fern-docs/ui/src/mdx/components/launchdarkly/LaunchDarkly.tsx b/packages/fern-docs/ui/src/mdx/components/launchdarkly/LaunchDarkly.tsx deleted file mode 100644 index b433a6fbfb..0000000000 --- a/packages/fern-docs/ui/src/mdx/components/launchdarkly/LaunchDarkly.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { PropsWithChildren, ReactNode } from "react"; -import { useLaunchDarklyFlag } from "../../../atoms/launchdarkly"; -import { LinkPreloadApiRoute } from "../../../components/LinkPreload"; - -export interface LaunchDarklyProps { - flag: string; - equals?: boolean; - not?: boolean; -} - -export function LaunchDarkly({ - equals = true, - not = false, - flag, - children, -}: PropsWithChildren): ReactNode { - const show = useLaunchDarklyFlag(flag, equals, not); - - return ( - <> - - {show && children} - - ); -} diff --git a/packages/fern-docs/ui/src/mdx/components/launchdarkly/index.ts b/packages/fern-docs/ui/src/mdx/components/launchdarkly/index.ts deleted file mode 100644 index ef6f12ffb9..0000000000 --- a/packages/fern-docs/ui/src/mdx/components/launchdarkly/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./LaunchDarkly"; diff --git a/packages/fern-docs/ui/src/playground/PlaygroundRequestPreview.tsx b/packages/fern-docs/ui/src/playground/PlaygroundRequestPreview.tsx index 4f10db944e..12f84390a6 100644 --- a/packages/fern-docs/ui/src/playground/PlaygroundRequestPreview.tsx +++ b/packages/fern-docs/ui/src/playground/PlaygroundRequestPreview.tsx @@ -5,7 +5,7 @@ import { FC, useMemo } from "react"; import { PLAYGROUND_AUTH_STATE_ATOM, PLAYGROUND_AUTH_STATE_OAUTH_ATOM, - useFeatureFlags, + useEdgeFlags, } from "../atoms"; import { useStandardProxyEnvironment } from "../hooks/useStandardProxyEnvironment"; import { PlaygroundCodeSnippetResolverBuilder } from "./code-snippets/resolver"; @@ -24,9 +24,9 @@ export const PlaygroundRequestPreview: FC = ({ formState, requestType, }) => { - const { isSnippetTemplatesEnabled } = useFeatureFlags(); + const { isSnippetTemplatesEnabled } = useEdgeFlags(); const authState = useAtomValue(PLAYGROUND_AUTH_STATE_ATOM); - const { isFileForgeHackEnabled } = useFeatureFlags(); + const { isFileForgeHackEnabled } = useEdgeFlags(); const [oAuthValue, setOAuthValue] = useAtom(PLAYGROUND_AUTH_STATE_OAUTH_ATOM); const [baseUrl] = usePlaygroundBaseUrl(context.endpoint); diff --git a/packages/fern-docs/ui/src/playground/endpoint/PlaygroundEndpoint.tsx b/packages/fern-docs/ui/src/playground/endpoint/PlaygroundEndpoint.tsx index 671fc72576..b642eee218 100644 --- a/packages/fern-docs/ui/src/playground/endpoint/PlaygroundEndpoint.tsx +++ b/packages/fern-docs/ui/src/playground/endpoint/PlaygroundEndpoint.tsx @@ -21,7 +21,7 @@ import { PLAYGROUND_AUTH_STATE_OAUTH_ATOM, store, useBasePath, - useFeatureFlags, + useEdgeFlags, usePlaygroundEndpointFormState, } from "../../atoms"; import { useApiRoute } from "../../hooks/useApiRoute"; @@ -77,7 +77,7 @@ export const PlaygroundEndpoint = ({ usesApplicationJsonInFormDataValue, proxyShouldUseAppBuildwithfernCom, grpcEndpoints, - } = useFeatureFlags(); + } = useEdgeFlags(); const [response, setResponse] = useState>(notStartedLoading()); diff --git a/packages/fern-docs/ui/src/playground/endpoint/PlaygroundEndpointDesktopLayout.tsx b/packages/fern-docs/ui/src/playground/endpoint/PlaygroundEndpointDesktopLayout.tsx index 9889bd8fdd..e0295c4b37 100644 --- a/packages/fern-docs/ui/src/playground/endpoint/PlaygroundEndpointDesktopLayout.tsx +++ b/packages/fern-docs/ui/src/playground/endpoint/PlaygroundEndpointDesktopLayout.tsx @@ -1,5 +1,5 @@ import { ReactElement, ReactNode } from "react"; -import { useFeatureFlags } from "../../atoms"; +import { useEdgeFlags } from "../../atoms"; import { HorizontalSplitPane, VerticalSplitPane } from "../VerticalSplitPane"; interface PlaygroundEndpointDesktopLayoutProps { @@ -17,7 +17,7 @@ export function PlaygroundEndpointDesktopLayout({ responseCard, endpointId, }: PlaygroundEndpointDesktopLayoutProps): ReactElement { - const { grpcEndpoints } = useFeatureFlags(); + const { grpcEndpoints } = useEdgeFlags(); return ( ("0"); - const { grpcEndpoints } = useFeatureFlags(); + const { grpcEndpoints } = useEdgeFlags(); return (
diff --git a/packages/fern-docs/ui/src/playground/form/PlaygroundTypeReferenceForm.tsx b/packages/fern-docs/ui/src/playground/form/PlaygroundTypeReferenceForm.tsx index ef65f68237..89ed9fad43 100644 --- a/packages/fern-docs/ui/src/playground/form/PlaygroundTypeReferenceForm.tsx +++ b/packages/fern-docs/ui/src/playground/form/PlaygroundTypeReferenceForm.tsx @@ -13,7 +13,7 @@ import { FernTextarea, } from "@fern-docs/components"; import { ReactElement, memo, useCallback } from "react"; -import { useFeatureFlags } from "../../atoms"; +import { useEdgeFlags } from "../../atoms"; import { WithLabel } from "../WithLabel"; import { PlaygroundDiscriminatedUnionForm } from "./PlaygroundDescriminatedUnionForm"; import { PlaygroundElevenLabsVoiceIdForm } from "./PlaygroundElevenLabsVoiceIdForm"; @@ -42,7 +42,7 @@ interface PlaygroundTypeReferenceFormProps { export const PlaygroundTypeReferenceForm = memo((props) => { - const { hasVoiceIdPlaygroundForm } = useFeatureFlags(); + const { hasVoiceIdPlaygroundForm } = useEdgeFlags(); const { id, property, diff --git a/packages/fern-docs/ui/src/resolver/resolveDocsContent.ts b/packages/fern-docs/ui/src/resolver/resolveDocsContent.ts index d75b186fa3..8277ff2816 100644 --- a/packages/fern-docs/ui/src/resolver/resolveDocsContent.ts +++ b/packages/fern-docs/ui/src/resolver/resolveDocsContent.ts @@ -6,7 +6,7 @@ import type { } from "@fern-api/fdr-sdk/client/types"; import * as FernNavigation from "@fern-api/fdr-sdk/navigation"; import { ApiDefinitionLoader, MarkdownLoader } from "@fern-docs/cache"; -import type { FeatureFlags } from "@fern-docs/utils"; +import type { EdgeFlags } from "@fern-docs/utils"; import { mapValues } from "es-toolkit/object"; import type { MDX_SERIALIZER } from "../mdx/bundler"; import type { FernSerializeMdxOptions } from "../mdx/types"; @@ -34,7 +34,7 @@ interface ResolveDocsContentArgs { apisV2: Record; pages: Record; mdxOptions?: FernSerializeMdxOptions; - featureFlags: FeatureFlags; + edgeFlags: EdgeFlags; serializeMdx: MDX_SERIALIZER; engine: string; } @@ -52,7 +52,7 @@ export async function resolveDocsContent({ apisV2, pages, mdxOptions, - featureFlags, + edgeFlags, serializeMdx, engine, }: ResolveDocsContentArgs): Promise { @@ -74,9 +74,9 @@ export async function resolveDocsContent({ ...mapValues(apis, (api) => { return ApiDefinitionLoader.create(domain, api.id) .withMdxBundler(serializeMdx, engine) - .withFlags(featureFlags) + .withEdgeFlags(edgeFlags) .withApiDefinition( - ApiDefinitionV1ToLatest.from(api, featureFlags).migrate() + ApiDefinitionV1ToLatest.from(api, edgeFlags).migrate() ) .withEnvironment(process.env.NEXT_PUBLIC_FDR_ORIGIN) .withResolveDescriptions(); @@ -84,7 +84,7 @@ export async function resolveDocsContent({ ...mapValues(apisV2 ?? {}, (api) => { return ApiDefinitionLoader.create(domain, api.id) .withMdxBundler(serializeMdx, engine) - .withFlags(featureFlags) + .withEdgeFlags(edgeFlags) .withApiDefinition(api) .withEnvironment(process.env.NEXT_PUBLIC_FDR_ORIGIN) .withResolveDescriptions(); diff --git a/packages/fern-docs/ui/src/search/SearchDialog.tsx b/packages/fern-docs/ui/src/search/SearchDialog.tsx index 246f8b7563..dff284089a 100644 --- a/packages/fern-docs/ui/src/search/SearchDialog.tsx +++ b/packages/fern-docs/ui/src/search/SearchDialog.tsx @@ -8,8 +8,8 @@ import { IS_MOBILE_SCREEN_ATOM, SEARCH_DIALOG_OPEN_ATOM, useDomain, - useFeatureFlag, - useFeatureFlags, + useEdgeFlag, + useEdgeFlags, useIsSearchDialogOpen, useSidebarNodes, } from "../atoms"; @@ -25,7 +25,7 @@ import { InkeepCustomTrigger } from "./inkeep/InkeepCustomTrigger"; import { useSearchTrigger } from "./useSearchTrigger"; export const SearchDialog = (): ReactNode => { - const isSearchV2Enabled = useFeatureFlag("isSearchV2Enabled"); + const isSearchV2Enabled = useEdgeFlag("isSearchV2Enabled"); if (isSearchV2Enabled) { return false; } @@ -84,7 +84,7 @@ export const SearchSidebar: React.FC< const inputRef = useRef(null); const isMobileScreen = useAtomValue(IS_MOBILE_SCREEN_ATOM); - const { isNewSearchExperienceEnabled } = useFeatureFlags(); + const { isNewSearchExperienceEnabled } = useEdgeFlags(); if (!searchConfig.isAvailable || !isMobileScreen) { return children; diff --git a/packages/fern-docs/ui/src/search/SearchV2.tsx b/packages/fern-docs/ui/src/search/SearchV2.tsx index cfa015d53a..3bf161880c 100644 --- a/packages/fern-docs/ui/src/search/SearchV2.tsx +++ b/packages/fern-docs/ui/src/search/SearchV2.tsx @@ -35,7 +35,7 @@ import { THEME_SWITCH_ENABLED_ATOM, atomWithStorageString, useClosePlayground, - useFeatureFlags, + useEdgeFlags, useFernUser, useIsPlaygroundOpen, useSetTheme, @@ -67,7 +67,7 @@ const askAiAtom = atom(false); export function SearchV2(): ReactElement | false { const version = useAtomValue(CURRENT_VERSION_ATOM); - const { isAskAiEnabled } = useFeatureFlags(); + const { isAskAiEnabled } = useEdgeFlags(); const userToken = useAlgoliaUserToken(); const user = useFernUser(); diff --git a/packages/fern-docs/ui/src/search/algolia/AlgoliaSearchDialog.tsx b/packages/fern-docs/ui/src/search/algolia/AlgoliaSearchDialog.tsx index 4d57bd8511..c416509fc3 100644 --- a/packages/fern-docs/ui/src/search/algolia/AlgoliaSearchDialog.tsx +++ b/packages/fern-docs/ui/src/search/algolia/AlgoliaSearchDialog.tsx @@ -16,7 +16,7 @@ import { POSITION_SEARCH_DIALOG_OVER_HEADER_ATOM, SEARCH_DIALOG_OPEN_ATOM, useDomain, - useFeatureFlags, + useEdgeFlags, useIsSearchDialogOpen, useSidebarNodes, } from "../../atoms"; @@ -112,7 +112,7 @@ function FernInstantSearch({ () => createSearchPlaceholderWithVersion(activeVersion?.id, sidebar), [activeVersion, sidebar] ); - const { isNewSearchExperienceEnabled } = useFeatureFlags(); + const { isNewSearchExperienceEnabled } = useEdgeFlags(); return ( = ({ className, }) => { const domain = useDomain(); - const isWhitelabeled = useFeatureFlag("isWhitelabeled"); + const isWhitelabeled = useEdgeFlag("isWhitelabeled"); const hideBuiltWithFern = useContext(HideBuiltWithFernContext); const component = useRef(null); diff --git a/packages/fern-docs/ui/src/sidebar/SidebarSearchBar.tsx b/packages/fern-docs/ui/src/sidebar/SidebarSearchBar.tsx index 637b70941d..99266b0d88 100644 --- a/packages/fern-docs/ui/src/sidebar/SidebarSearchBar.tsx +++ b/packages/fern-docs/ui/src/sidebar/SidebarSearchBar.tsx @@ -4,7 +4,7 @@ import { DesktopSearchButton } from "@fern-docs/search-ui"; import clsx from "clsx"; import { Search } from "iconoir-react"; import dynamic from "next/dynamic"; -import { useFeatureFlag, useOpenSearchDialog } from "../atoms"; +import { useEdgeFlag, useOpenSearchDialog } from "../atoms"; import { useSearchConfig } from "../services/useSearchService"; const SearchV2 = dynamic( @@ -24,7 +24,7 @@ export declare namespace SidebarSearchBar { export const SidebarSearchBar: React.FC = memo( function UnmemoizedSidebarSearchBar({ className, hideKeyboardShortcutHint }) { - const isSearchV2Enabled = useFeatureFlag("isSearchV2Enabled"); + const isSearchV2Enabled = useEdgeFlag("isSearchV2Enabled"); if (!isSearchV2Enabled) { return ( =18'} - launchdarkly-js-client-sdk@3.4.0: - resolution: {integrity: sha512-3v1jKy1RECT0SG/3SGlyRO32vweoNxvWiJuIChRh/Zhk98cHpANuwameXVhwJ4WEDNZJTur73baaKAyatSP46A==} + launchdarkly-js-client-sdk@3.5.0: + resolution: {integrity: sha512-3dgxC9S8K2ix6qjdArjZGOJPtAytgfQTuE+vWgjWJK7725rpYbuqbHghIFr5B0+WyWyVBYANldjWd1JdtYLwsw==} + + launchdarkly-js-sdk-common@5.4.0: + resolution: {integrity: sha512-Kb3SDcB6S0HUpFNBZgtEt0YUV/fVkyg+gODfaOCJQ0Y0ApxLKNmmJBZOrPE2qIdzw536u4BqEjtaJdqJWCEElg==} - launchdarkly-js-sdk-common@5.3.0: - resolution: {integrity: sha512-NI5wFF8qhjtpRb4KelGdnwNIOf/boLlbLiseV7uf1jxSeoM/L30DAz87RT8VhYCSGCo4LedGILQFednI/MKFkA==} + launchdarkly-react-client-sdk@3.6.0: + resolution: {integrity: sha512-tGXc7CNngfwElsoLmvpt81NO+v5gH9xuCdIjYSi9BHlL4wk6mpJpuEJn0Kx8Q3D1mnNzAhX3YdJNXc1pk3fXbg==} + peerDependencies: + react: 18.3.1 + react-dom: 18.3.1 layout-base@1.0.2: resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} @@ -18046,7 +18052,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.5 '@babel/parser': 7.24.5 '@babel/types': 7.24.5 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -19668,7 +19674,7 @@ snapshots: dependencies: playwright: 1.47.1 - '@pmmmwh/react-refresh-webpack-plugin@0.5.13(react-refresh@0.14.2)(type-fest@4.21.0)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.13(react-refresh@0.14.2)(type-fest@4.21.0)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.5.7))': dependencies: ansi-html-community: 0.0.8 core-js-pure: 3.37.0 @@ -19678,12 +19684,12 @@ snapshots: react-refresh: 0.14.2 schema-utils: 3.3.0 source-map: 0.7.4 - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) optionalDependencies: type-fest: 4.21.0 webpack-hot-middleware: 2.26.1 - '@pmmmwh/react-refresh-webpack-plugin@0.5.13(react-refresh@0.14.2)(type-fest@4.21.0)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.5.7))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.13(react-refresh@0.14.2)(type-fest@4.21.0)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(esbuild@0.20.2))': dependencies: ansi-html-community: 0.0.8 core-js-pure: 3.37.0 @@ -19693,7 +19699,7 @@ snapshots: react-refresh: 0.14.2 schema-utils: 3.3.0 source-map: 0.7.4 - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) optionalDependencies: type-fest: 4.21.0 webpack-hot-middleware: 2.26.1 @@ -21234,7 +21240,7 @@ snapshots: transitivePeerDependencies: - webpack-sources - '@storybook/builder-webpack5@8.4.4(@swc/core@1.5.7)(esbuild@0.20.2)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2)': + '@storybook/builder-webpack5@8.4.4(@swc/core@1.5.7)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2)': dependencies: '@storybook/core-webpack': 8.4.4(storybook@8.4.4(prettier@3.4.2)) '@types/node': 22.5.5 @@ -21243,23 +21249,23 @@ snapshots: case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.3.1 constants-browserify: 1.0.0 - css-loader: 6.11.0(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) + css-loader: 6.11.0(webpack@5.94.0(@swc/core@1.5.7)) es-module-lexer: 1.5.2 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) - html-webpack-plugin: 5.6.0(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)) + html-webpack-plugin: 5.6.0(webpack@5.94.0(@swc/core@1.5.7)) magic-string: 0.30.12 path-browserify: 1.0.1 process: 0.11.10 semver: 7.6.3 storybook: 8.4.4(prettier@3.4.2) - style-loader: 3.3.4(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) - terser-webpack-plugin: 5.3.10(@swc/core@1.5.7)(esbuild@0.20.2)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) + style-loader: 3.3.4(webpack@5.94.0(@swc/core@1.5.7)) + terser-webpack-plugin: 5.3.10(@swc/core@1.5.7)(webpack@5.94.0(@swc/core@1.5.7)) ts-dedent: 2.2.0 url: 0.11.3 util: 0.12.5 util-deprecate: 1.0.2 - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) - webpack-dev-middleware: 6.1.3(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) + webpack: 5.94.0(@swc/core@1.5.7) + webpack-dev-middleware: 6.1.3(webpack@5.94.0(@swc/core@1.5.7)) webpack-hot-middleware: 2.26.1 webpack-virtual-modules: 0.6.2 optionalDependencies: @@ -21271,7 +21277,7 @@ snapshots: - uglify-js - webpack-cli - '@storybook/builder-webpack5@8.4.4(@swc/core@1.5.7)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2)': + '@storybook/builder-webpack5@8.4.4(esbuild@0.20.2)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2)': dependencies: '@storybook/core-webpack': 8.4.4(storybook@8.4.4(prettier@3.4.2)) '@types/node': 22.5.5 @@ -21280,23 +21286,23 @@ snapshots: case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.3.1 constants-browserify: 1.0.0 - css-loader: 6.11.0(webpack@5.94.0(@swc/core@1.5.7)) + css-loader: 6.11.0(webpack@5.94.0(esbuild@0.20.2)) es-module-lexer: 1.5.2 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)) - html-webpack-plugin: 5.6.0(webpack@5.94.0(@swc/core@1.5.7)) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.7.2)(webpack@5.94.0(esbuild@0.20.2)) + html-webpack-plugin: 5.6.0(webpack@5.94.0(esbuild@0.20.2)) magic-string: 0.30.12 path-browserify: 1.0.1 process: 0.11.10 semver: 7.6.3 storybook: 8.4.4(prettier@3.4.2) - style-loader: 3.3.4(webpack@5.94.0(@swc/core@1.5.7)) - terser-webpack-plugin: 5.3.10(@swc/core@1.5.7)(webpack@5.94.0(@swc/core@1.5.7)) + style-loader: 3.3.4(webpack@5.94.0(esbuild@0.20.2)) + terser-webpack-plugin: 5.3.10(esbuild@0.20.2)(webpack@5.94.0(esbuild@0.20.2)) ts-dedent: 2.2.0 url: 0.11.3 util: 0.12.5 util-deprecate: 1.0.2 - webpack: 5.94.0(@swc/core@1.5.7) - webpack-dev-middleware: 6.1.3(webpack@5.94.0(@swc/core@1.5.7)) + webpack: 5.94.0(esbuild@0.20.2) + webpack-dev-middleware: 6.1.3(webpack@5.94.0(esbuild@0.20.2)) webpack-hot-middleware: 2.26.1 webpack-virtual-modules: 0.6.2 optionalDependencies: @@ -21392,7 +21398,7 @@ snapshots: dependencies: storybook: 8.4.4(prettier@3.4.2) - '@storybook/nextjs@8.4.4(@fern-api/next@14.2.9-fork.2(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0))(@swc/core@1.5.7)(esbuild@0.20.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0)(storybook@8.4.4(prettier@3.4.2))(type-fest@4.21.0)(typescript@5.7.2)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2))': + '@storybook/nextjs@8.4.4(@fern-api/next@14.2.9-fork.2(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0))(@swc/core@1.5.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0)(storybook@8.4.4(prettier@3.4.2))(type-fest@4.21.0)(typescript@5.7.2)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.5.7))': dependencies: '@babel/core': 7.26.0 '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.0) @@ -21407,31 +21413,31 @@ snapshots: '@babel/preset-react': 7.25.9(@babel/core@7.26.0) '@babel/preset-typescript': 7.26.0(@babel/core@7.26.0) '@babel/runtime': 7.26.0 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.13(react-refresh@0.14.2)(type-fest@4.21.0)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) - '@storybook/builder-webpack5': 8.4.4(@swc/core@1.5.7)(esbuild@0.20.2)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) - '@storybook/preset-react-webpack': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(@swc/core@1.5.7)(esbuild@0.20.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.13(react-refresh@0.14.2)(type-fest@4.21.0)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.5.7)) + '@storybook/builder-webpack5': 8.4.4(@swc/core@1.5.7)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) + '@storybook/preset-react-webpack': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(@swc/core@1.5.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) '@storybook/react': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) '@storybook/test': 8.4.4(storybook@8.4.4(prettier@3.4.2)) '@types/node': 22.5.5 '@types/semver': 7.5.8 - babel-loader: 9.1.3(@babel/core@7.26.0)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) - css-loader: 6.11.0(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) + babel-loader: 9.1.3(@babel/core@7.26.0)(webpack@5.94.0(@swc/core@1.5.7)) + css-loader: 6.11.0(webpack@5.94.0(@swc/core@1.5.7)) find-up: 5.0.0 image-size: 1.1.1 loader-utils: 3.2.1 next: '@fern-api/next@14.2.9-fork.2(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0)' - node-polyfill-webpack-plugin: 2.0.1(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) + node-polyfill-webpack-plugin: 2.0.1(webpack@5.94.0(@swc/core@1.5.7)) pnp-webpack-plugin: 1.7.0(typescript@5.7.2) postcss: 8.4.31 - postcss-loader: 8.1.1(postcss@8.4.31)(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) + postcss-loader: 8.1.1(postcss@8.4.31)(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-refresh: 0.14.2 resolve-url-loader: 5.0.0 - sass-loader: 13.3.3(sass@1.77.0)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) + sass-loader: 13.3.3(sass@1.77.0)(webpack@5.94.0(@swc/core@1.5.7)) semver: 7.6.3 storybook: 8.4.4(prettier@3.4.2) - style-loader: 3.3.4(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) + style-loader: 3.3.4(webpack@5.94.0(@swc/core@1.5.7)) styled-jsx: 5.1.6(@babel/core@7.26.0)(react@18.3.1) ts-dedent: 2.2.0 tsconfig-paths: 4.2.0 @@ -21439,7 +21445,7 @@ snapshots: optionalDependencies: sharp: 0.33.3 typescript: 5.7.2 - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) transitivePeerDependencies: - '@rspack/core' - '@swc/core' @@ -21459,7 +21465,7 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/nextjs@8.4.4(@fern-api/next@14.2.9-fork.2(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0))(@swc/core@1.5.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0)(storybook@8.4.4(prettier@3.4.2))(type-fest@4.21.0)(typescript@5.7.2)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.5.7))': + '@storybook/nextjs@8.4.4(@fern-api/next@14.2.9-fork.2(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0))(esbuild@0.20.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0)(storybook@8.4.4(prettier@3.4.2))(type-fest@4.21.0)(typescript@5.7.2)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(esbuild@0.20.2))': dependencies: '@babel/core': 7.26.0 '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.0) @@ -21474,31 +21480,31 @@ snapshots: '@babel/preset-react': 7.25.9(@babel/core@7.26.0) '@babel/preset-typescript': 7.26.0(@babel/core@7.26.0) '@babel/runtime': 7.26.0 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.13(react-refresh@0.14.2)(type-fest@4.21.0)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.5.7)) - '@storybook/builder-webpack5': 8.4.4(@swc/core@1.5.7)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) - '@storybook/preset-react-webpack': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(@swc/core@1.5.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.13(react-refresh@0.14.2)(type-fest@4.21.0)(webpack-hot-middleware@2.26.1)(webpack@5.94.0(esbuild@0.20.2)) + '@storybook/builder-webpack5': 8.4.4(esbuild@0.20.2)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) + '@storybook/preset-react-webpack': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(esbuild@0.20.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) '@storybook/react': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) '@storybook/test': 8.4.4(storybook@8.4.4(prettier@3.4.2)) '@types/node': 22.5.5 '@types/semver': 7.5.8 - babel-loader: 9.1.3(@babel/core@7.26.0)(webpack@5.94.0(@swc/core@1.5.7)) - css-loader: 6.11.0(webpack@5.94.0(@swc/core@1.5.7)) + babel-loader: 9.1.3(@babel/core@7.26.0)(webpack@5.94.0(esbuild@0.20.2)) + css-loader: 6.11.0(webpack@5.94.0(esbuild@0.20.2)) find-up: 5.0.0 image-size: 1.1.1 loader-utils: 3.2.1 next: '@fern-api/next@14.2.9-fork.2(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0)' - node-polyfill-webpack-plugin: 2.0.1(webpack@5.94.0(@swc/core@1.5.7)) + node-polyfill-webpack-plugin: 2.0.1(webpack@5.94.0(esbuild@0.20.2)) pnp-webpack-plugin: 1.7.0(typescript@5.7.2) postcss: 8.4.31 - postcss-loader: 8.1.1(postcss@8.4.31)(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)) + postcss-loader: 8.1.1(postcss@8.4.31)(typescript@5.7.2)(webpack@5.94.0(esbuild@0.20.2)) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-refresh: 0.14.2 resolve-url-loader: 5.0.0 - sass-loader: 13.3.3(sass@1.77.0)(webpack@5.94.0(@swc/core@1.5.7)) + sass-loader: 13.3.3(sass@1.77.0)(webpack@5.94.0(esbuild@0.20.2)) semver: 7.6.3 storybook: 8.4.4(prettier@3.4.2) - style-loader: 3.3.4(webpack@5.94.0(@swc/core@1.5.7)) + style-loader: 3.3.4(webpack@5.94.0(esbuild@0.20.2)) styled-jsx: 5.1.6(@babel/core@7.26.0)(react@18.3.1) ts-dedent: 2.2.0 tsconfig-paths: 4.2.0 @@ -21506,7 +21512,7 @@ snapshots: optionalDependencies: sharp: 0.33.3 typescript: 5.7.2 - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) transitivePeerDependencies: - '@rspack/core' - '@swc/core' @@ -21526,11 +21532,11 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/preset-react-webpack@8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(@swc/core@1.5.7)(esbuild@0.20.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2)': + '@storybook/preset-react-webpack@8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(@swc/core@1.5.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2)': dependencies: '@storybook/core-webpack': 8.4.4(storybook@8.4.4(prettier@3.4.2)) '@storybook/react': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)) '@types/node': 22.5.5 '@types/semver': 7.5.8 find-up: 5.0.0 @@ -21542,7 +21548,7 @@ snapshots: semver: 7.6.3 storybook: 8.4.4(prettier@3.4.2) tsconfig-paths: 4.2.0 - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: @@ -21553,11 +21559,11 @@ snapshots: - uglify-js - webpack-cli - '@storybook/preset-react-webpack@8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(@swc/core@1.5.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2)': + '@storybook/preset-react-webpack@8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(esbuild@0.20.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2)': dependencies: '@storybook/core-webpack': 8.4.4(storybook@8.4.4(prettier@3.4.2)) '@storybook/react': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.4.2))(typescript@5.7.2) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.94.0(esbuild@0.20.2)) '@types/node': 22.5.5 '@types/semver': 7.5.8 find-up: 5.0.0 @@ -21569,7 +21575,7 @@ snapshots: semver: 7.6.3 storybook: 8.4.4(prettier@3.4.2) tsconfig-paths: 4.2.0 - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: @@ -21601,7 +21607,7 @@ snapshots: dependencies: storybook: 8.4.4(prettier@3.4.2) - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7))': dependencies: debug: 4.3.7 endent: 2.1.0 @@ -21611,11 +21617,11 @@ snapshots: react-docgen-typescript: 2.2.2(typescript@5.7.2) tslib: 2.8.1 typescript: 5.7.2 - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) transitivePeerDependencies: - supports-color - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.94.0(esbuild@0.20.2))': dependencies: debug: 4.3.7 endent: 2.1.0 @@ -21625,7 +21631,7 @@ snapshots: react-docgen-typescript: 2.2.2(typescript@5.7.2) tslib: 2.8.1 typescript: 5.7.2 - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) transitivePeerDependencies: - supports-color @@ -21767,6 +21773,11 @@ snapshots: mini-svg-data-uri: 1.4.4 tailwindcss: 3.4.17(ts-node@10.9.2(@swc/core@1.5.7)(@types/node@18.19.33)(typescript@5.7.2)) + '@tailwindcss/forms@0.5.7(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.7.2)))': + dependencies: + mini-svg-data-uri: 1.4.4 + tailwindcss: 3.4.17(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.7.2)) + '@tailwindcss/typography@0.5.13(tailwindcss@3.4.17(ts-node@10.9.2(@swc/core@1.5.7)(@types/node@18.19.33)(typescript@5.7.2)))': dependencies: lodash.castarray: 4.4.0 @@ -21775,6 +21786,14 @@ snapshots: postcss-selector-parser: 6.0.10 tailwindcss: 3.4.17(ts-node@10.9.2(@swc/core@1.5.7)(@types/node@18.19.33)(typescript@5.7.2)) + '@tailwindcss/typography@0.5.13(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.7.2)))': + dependencies: + lodash.castarray: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + postcss-selector-parser: 6.0.10 + tailwindcss: 3.4.17(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.7.2)) + '@tanem/svg-injector@10.1.68': dependencies: '@babel/runtime': 7.26.0 @@ -24059,19 +24078,19 @@ snapshots: transitivePeerDependencies: - supports-color - babel-loader@9.1.3(@babel/core@7.26.0)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)): + babel-loader@9.1.3(@babel/core@7.26.0)(webpack@5.94.0(@swc/core@1.5.7)): dependencies: '@babel/core': 7.26.0 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) - babel-loader@9.1.3(@babel/core@7.26.0)(webpack@5.94.0(@swc/core@1.5.7)): + babel-loader@9.1.3(@babel/core@7.26.0)(webpack@5.94.0(esbuild@0.20.2)): dependencies: '@babel/core': 7.26.0 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) babel-plugin-istanbul@6.1.1: dependencies: @@ -24878,7 +24897,7 @@ snapshots: css-functions-list@3.2.2: {} - css-loader@6.11.0(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)): + css-loader@6.11.0(webpack@5.94.0(@swc/core@1.5.7)): dependencies: icss-utils: 5.1.0(postcss@8.4.31) postcss: 8.4.31 @@ -24889,9 +24908,9 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) - css-loader@6.11.0(webpack@5.94.0(@swc/core@1.5.7)): + css-loader@6.11.0(webpack@5.94.0(esbuild@0.20.2)): dependencies: icss-utils: 5.1.0(postcss@8.4.31) postcss: 8.4.31 @@ -24902,7 +24921,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) css-select@4.3.0: dependencies: @@ -25224,6 +25243,10 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.3.4: + dependencies: + ms: 2.1.2 + debug@4.3.4(supports-color@5.5.0): dependencies: ms: 2.1.2 @@ -25365,7 +25388,7 @@ snapshots: callsite: 1.0.0 camelcase: 6.3.0 cosmiconfig: 7.1.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4 deps-regex: 0.2.0 findup-sync: 5.0.0 ignore: 5.3.1 @@ -26551,7 +26574,7 @@ snapshots: cross-spawn: 7.0.5 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)): dependencies: '@babel/code-frame': 7.26.2 chalk: 4.1.2 @@ -26566,9 +26589,9 @@ snapshots: semver: 7.6.3 tapable: 2.2.1 typescript: 5.7.2 - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.7.2)(webpack@5.94.0(esbuild@0.20.2)): dependencies: '@babel/code-frame': 7.26.2 chalk: 4.1.2 @@ -26583,7 +26606,7 @@ snapshots: semver: 7.6.3 tapable: 2.2.1 typescript: 5.7.2 - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) form-data@2.5.1: dependencies: @@ -27277,7 +27300,7 @@ snapshots: html-void-elements@3.0.0: {} - html-webpack-plugin@5.6.0(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)): + html-webpack-plugin@5.6.0(webpack@5.94.0(@swc/core@1.5.7)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -27285,9 +27308,9 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) - html-webpack-plugin@5.6.0(webpack@5.94.0(@swc/core@1.5.7)): + html-webpack-plugin@5.6.0(webpack@5.94.0(esbuild@0.20.2)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -27295,7 +27318,7 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) htmlparser2@6.1.0: dependencies: @@ -28464,17 +28487,25 @@ snapshots: dependencies: package-json: 10.0.0 - launchdarkly-js-client-sdk@3.4.0: + launchdarkly-js-client-sdk@3.5.0: dependencies: escape-string-regexp: 4.0.0 - launchdarkly-js-sdk-common: 5.3.0 + launchdarkly-js-sdk-common: 5.4.0 - launchdarkly-js-sdk-common@5.3.0: + launchdarkly-js-sdk-common@5.4.0: dependencies: base64-js: 1.5.1 fast-deep-equal: 2.0.1 uuid: 8.3.2 + launchdarkly-react-client-sdk@3.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + hoist-non-react-statics: 3.3.2 + launchdarkly-js-client-sdk: 3.5.0 + lodash.camelcase: 4.3.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + layout-base@1.0.2: {} layout-base@2.0.1: {} @@ -29739,7 +29770,7 @@ snapshots: node-int64@0.4.0: {} - node-polyfill-webpack-plugin@2.0.1(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)): + node-polyfill-webpack-plugin@2.0.1(webpack@5.94.0(@swc/core@1.5.7)): dependencies: assert: 2.1.0 browserify-zlib: 0.2.0 @@ -29766,9 +29797,9 @@ snapshots: url: 0.11.3 util: 0.12.5 vm-browserify: 1.1.2 - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) - node-polyfill-webpack-plugin@2.0.1(webpack@5.94.0(@swc/core@1.5.7)): + node-polyfill-webpack-plugin@2.0.1(webpack@5.94.0(esbuild@0.20.2)): dependencies: assert: 2.1.0 browserify-zlib: 0.2.0 @@ -29795,7 +29826,7 @@ snapshots: url: 0.11.3 util: 0.12.5 vm-browserify: 1.1.2 - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) node-releases@2.0.18: {} @@ -30343,6 +30374,14 @@ snapshots: postcss: 8.4.31 ts-node: 10.9.2(@swc/core@1.5.7)(@types/node@18.19.33)(typescript@5.7.2) + postcss-load-config@4.0.2(postcss@8.4.31)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.7.2)): + dependencies: + lilconfig: 3.1.3 + yaml: 2.4.2 + optionalDependencies: + postcss: 8.4.31 + ts-node: 10.9.2(@types/node@18.19.33)(typescript@5.7.2) + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.4.31)(tsx@4.19.2)(yaml@2.4.2): dependencies: lilconfig: 3.1.1 @@ -30352,25 +30391,25 @@ snapshots: tsx: 4.19.2 yaml: 2.4.2 - postcss-loader@8.1.1(postcss@8.4.31)(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)): + postcss-loader@8.1.1(postcss@8.4.31)(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)): dependencies: cosmiconfig: 9.0.0(typescript@5.7.2) jiti: 1.21.0 postcss: 8.4.31 semver: 7.6.3 optionalDependencies: - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) transitivePeerDependencies: - typescript - postcss-loader@8.1.1(postcss@8.4.31)(typescript@5.7.2)(webpack@5.94.0(@swc/core@1.5.7)): + postcss-loader@8.1.1(postcss@8.4.31)(typescript@5.7.2)(webpack@5.94.0(esbuild@0.20.2)): dependencies: cosmiconfig: 9.0.0(typescript@5.7.2) jiti: 1.21.0 postcss: 8.4.31 semver: 7.6.3 optionalDependencies: - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) transitivePeerDependencies: - typescript @@ -31542,17 +31581,17 @@ snapshots: safer-buffer@2.1.2: {} - sass-loader@13.3.3(sass@1.77.0)(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)): + sass-loader@13.3.3(sass@1.77.0)(webpack@5.94.0(@swc/core@1.5.7)): dependencies: neo-async: 2.6.2 - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) optionalDependencies: sass: 1.77.0 - sass-loader@13.3.3(sass@1.77.0)(webpack@5.94.0(@swc/core@1.5.7)): + sass-loader@13.3.3(sass@1.77.0)(webpack@5.94.0(esbuild@0.20.2)): dependencies: neo-async: 2.6.2 - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) optionalDependencies: sass: 1.77.0 @@ -32168,14 +32207,14 @@ snapshots: '@tokenizer/token': 0.3.0 peek-readable: 4.1.0 - style-loader@3.3.4(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)): - dependencies: - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) - style-loader@3.3.4(webpack@5.94.0(@swc/core@1.5.7)): dependencies: webpack: 5.94.0(@swc/core@1.5.7) + style-loader@3.3.4(webpack@5.94.0(esbuild@0.20.2)): + dependencies: + webpack: 5.94.0(esbuild@0.20.2) + style-to-js@1.1.3: dependencies: style-to-object: 0.4.1 @@ -32271,7 +32310,7 @@ snapshots: cosmiconfig: 9.0.0(typescript@5.7.2) css-functions-list: 3.2.2 css-tree: 2.3.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4 fast-glob: 3.3.2 fastest-levenshtein: 1.0.16 file-entry-cache: 8.0.0 @@ -32433,6 +32472,33 @@ snapshots: transitivePeerDependencies: - ts-node + tailwindcss@3.4.17(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.7.2)): + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.7 + lilconfig: 3.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.4.31 + postcss-import: 15.1.0(postcss@8.4.31) + postcss-js: 4.0.1(postcss@8.4.31) + postcss-load-config: 4.0.2(postcss@8.4.31)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.7.2)) + postcss-nested: 6.2.0(postcss@8.4.31) + postcss-selector-parser: 6.1.2 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + tapable@2.2.1: {} tar-stream@1.6.2: @@ -32495,6 +32561,17 @@ snapshots: optionalDependencies: '@swc/core': 1.5.7 + terser-webpack-plugin@5.3.10(esbuild@0.20.2)(webpack@5.94.0(esbuild@0.20.2)): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.2 + terser: 5.31.0 + webpack: 5.94.0(esbuild@0.20.2) + optionalDependencies: + esbuild: 0.20.2 + terser@5.31.0: dependencies: '@jridgewell/source-map': 0.3.6 @@ -32725,6 +32802,25 @@ snapshots: optionalDependencies: '@swc/core': 1.5.7 + ts-node@10.9.2(@types/node@18.19.33)(typescript@5.7.2): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 18.19.33 + acorn: 8.14.0 + acorn-walk: 8.3.2 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.7.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optional: true + ts-pattern@5.0.5: {} ts-pnp@1.2.0(typescript@5.7.2): @@ -33515,7 +33611,7 @@ snapshots: - bufferutil - utf-8-validate - webpack-dev-middleware@6.1.3(webpack@5.94.0(@swc/core@1.5.7)(esbuild@0.20.2)): + webpack-dev-middleware@6.1.3(webpack@5.94.0(@swc/core@1.5.7)): dependencies: colorette: 2.0.20 memfs: 3.5.3 @@ -33523,9 +33619,9 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.2.0 optionalDependencies: - webpack: 5.94.0(@swc/core@1.5.7)(esbuild@0.20.2) + webpack: 5.94.0(@swc/core@1.5.7) - webpack-dev-middleware@6.1.3(webpack@5.94.0(@swc/core@1.5.7)): + webpack-dev-middleware@6.1.3(webpack@5.94.0(esbuild@0.20.2)): dependencies: colorette: 2.0.20 memfs: 3.5.3 @@ -33533,7 +33629,7 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.2.0 optionalDependencies: - webpack: 5.94.0(@swc/core@1.5.7) + webpack: 5.94.0(esbuild@0.20.2) webpack-hot-middleware@2.26.1: dependencies: @@ -33605,6 +33701,36 @@ snapshots: - esbuild - uglify-js + webpack@5.94.0(esbuild@0.20.2): + dependencies: + '@types/estree': 1.0.6 + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/wasm-edit': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + acorn: 8.14.0 + acorn-import-attributes: 1.9.5(acorn@8.14.0) + browserslist: 4.24.2 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.17.1 + es-module-lexer: 1.5.2 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.10(esbuild@0.20.2)(webpack@5.94.0(esbuild@0.20.2)) + watchpack: 2.4.1 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3