Skip to content

Commit

Permalink
Merge pull request #107 from armada-ths/hampus/feature-flag
Browse files Browse the repository at this point in the history
Hampus/feature flag
  • Loading branch information
hampfh authored Nov 9, 2024
2 parents 06d657d + 789914f commit b7cde5d
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 43 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@tanstack/react-query": "^5.20.1",
"@turf/center-of-mass": "^7.0.0",
"@vercel/analytics": "^1.2.2",
"@vercel/flags": "^2.3.0",
"@vercel/flags": "^2.5.1",
"@vercel/speed-insights": "^1.0.10",
"@vercel/toolbar": "^0.1.14",
"class-variance-authority": "^0.7.0",
Expand Down Expand Up @@ -60,13 +60,13 @@
"devDependencies": {
"@eslint/js": "^9.8.0",
"@total-typescript/ts-reset": "^0.5.1",
"@types/geojson": "^7946.0.14",
"@types/js-cookie": "^3.0.6",
"@types/luxon": "^3.4.2",
"@types/mapbox__mapbox-gl-draw": "^1.4.7",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/geojson": "^7946.0.14",
"@types/mapbox__mapbox-gl-draw": "^1.4.7",
"autoprefixer": "^10.0.1",
"eslint": "^9.8.0",
"eslint-config-next": "14.1.0",
Expand Down
22 changes: 11 additions & 11 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions src/app/.well-known/vercel/flags/route.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { type ApiData } from "@vercel/flags"
import { NextResponse } from "next/server"
import { verifyAccess, type ApiData } from "@vercel/flags"
import { NextRequest, NextResponse } from "next/server"
import { FEATURE_FLAG_DEFINITIONS } from "../../../../feature_flags"

export async function GET() {
export async function GET(request: NextRequest) {
const access = await verifyAccess(request.headers.get("Authorization"))
if (!access) return NextResponse.json(null, { status: 401 })

const apiData = {
definitions: FEATURE_FLAG_DEFINITIONS
}

return NextResponse.json<ApiData>(apiData)
}
2 changes: 1 addition & 1 deletion src/app/student/events/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default async function EventDetailsPage({
}: {
params: { id: string }
}) {
if (!feature("EVENT_PAGE")) {
if (!(await feature("EVENT_PAGE"))) {
return notFound()
}

Expand Down
2 changes: 1 addition & 1 deletion src/app/student/events/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { fetchEvents } from "@/components/shared/hooks/api/useEvents"
import { notFound } from "next/navigation"

export default async function StudentEventPage() {
if (!feature("EVENT_PAGE")) {
if (!(await feature("EVENT_PAGE"))) {
return notFound()
}
const events = await fetchEvents()
Expand Down
2 changes: 1 addition & 1 deletion src/app/student/map/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { notFound } from "next/navigation"
import { Suspense } from "react"

export default async function Page() {
if (!feature("MAP_PAGE")) {
if (!(await feature("MAP_PAGE"))) {
return notFound()
}

Expand Down
35 changes: 12 additions & 23 deletions src/components/shared/feature.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,18 @@
import featureFlags from "@/feature_flags"
import featureFlags, { FEATURE_FLAGS } from "@/feature_flags"
import { decrypt, FlagOverridesType } from "@vercel/flags"
import { cookies } from "next/headers"

export function feature(feature: keyof typeof featureFlags) {
const cookie = cookies()

const result = cookie.get("vercel-flag-overrides")
if (result != null) {
return parseCookie(feature, result.value)
export async function features() {
const overrideCookie = cookies().get("vercel-flag-overrides")?.value
const overrides = overrideCookie
? await decrypt<FlagOverridesType>(overrideCookie)
: {}
return {
...FEATURE_FLAGS,
...overrides
}
return false
}

function parseCookie(
feature: keyof typeof featureFlags,
rawOverrides: string | undefined
) {
const overrides =
rawOverrides == null
? {}
: (JSON.parse(rawOverrides) as Record<string, boolean>)

if (overrides[feature] != null) {
return overrides[feature]
} else if (featureFlags[feature] != null) {
return featureFlags[feature]
}
return false
export async function feature(feature: keyof typeof featureFlags) {
return (await features())[feature] ?? false
}
16 changes: 16 additions & 0 deletions src/components/shared/hooks/useFeature.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { features } from "@/components/shared/feature"
import FEATURE_FLAGS from "@/feature_flags"
import { useQuery } from "@tanstack/react-query"

export function useFeature(feature?: keyof typeof FEATURE_FLAGS) {
const { data, isLoading } = useQuery({
queryKey: ["feature-flags"],
queryFn: async () => await features()
})

return {
isLoading,
enabled: feature ? data?.[feature] : null,
flags: data
}
}

0 comments on commit b7cde5d

Please sign in to comment.