Closed mootoday closed 2 weeks ago
I figured it out, documenting it here in case anyone else stumbles across this.
src/app.d.ts
import type { Unleash } from "unleash-client";
declare global {
namespace App {
// interface Error {}
interface Locals {
unleashClient: Unleash | undefined;
}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};
src/hooks.server.ts
import { sequence } from "@sveltejs/kit/hooks";
import { destroy, startUnleash, type Unleash } from "unleash-client";
import { UNLEASH_API_KEY } from "$env/static/private";
let unleashClient: Unleash;
let isUnleashClientError = false;
const handleFeatureFlags: Handle = async ({ event, resolve }) => {
if (!unleashClient && !isUnleashClientError) {
try {
unleashClient = await startUnleash({
url: "<YOUR_API_URL>",
appName: "<YOUR_APP_NAME>",
customHeaders: {
Authorization: UNLEASH_API_KEY,
},
skipInstanceCountWarning: true, // I haven't figured out why this is needed
});
} catch (error: unknown) {
isUnleashClientError = true;
destroy();
console.error("Failed to start the unleash client: ", error);
}
}
event.locals.unleashClient = unleashClient ?? undefined;
return resolve(event);
};
export const handle = sequence(..., handleFeatureFlags)
src/routes/+layout.server.ts
import type { LayoutServerLoad } from "./$types";
export const load: LayoutServerLoad = async ({ locals }) => {
let ff = {};
if (locals.unleashClient) {
ff = locals.unleashClient
.getFeatureToggleDefinitions()
.map(({ name }) => name)
.reduce(
(result, flag) => ({
...result,
[flag]: locals.unleashClient?.isEnabled(flag, { userId: <CURRENT_USER_ID> }),
}),
{}
);
}
return {
ff,
};
};
src/routes/+layout.svelte
<script lang="ts">
import { FlagProvider } from "@unleash/proxy-client-svelte";
const ffConfig = {
url: "YOUR_FRONTEND_API_URL",
clientKey: dev
? "default:development.xyz"
: "default:production.xyz",
refreshInterval: 15,
appName: "<YOUR_APP_NAME>",
context: {
userId: <CURRENT_USER_ID>,
},
};
</script>
<FlagProvider config={ffConfig}>
<slot />
</FlagProvider>
src/lib/components/feature-flag.svelte
<script lang="ts">
import { browser } from "$app/environment";
import { page } from "$app/stores";
import { useFlag } from "@unleash/proxy-client-svelte";
import { writable, type Writable } from "svelte/store";
export let name: string;
let isEnabled: Writable<boolean>;
if (browser) {
isEnabled = useFlag(name);
} else {
isEnabled = writable($page.data.ff[name]);
}
</script>
{#if $isEnabled}
<slot />
{/if}
Now anywhere in your app, you can use the <FeatureFlag name="">
component like this:
src/routes/+page.svelte
<script lang="ts">
import FeatureFlag from "$lib/components/feature-flag.svelte";
</script>
<FeatureFlag name="test-one">Feature flag is enabled</FeatureFlag>
Thank you 🙏
Hi 👋,
In the SvelteKit tutorial, the conclusion paragraph mentions the following:
From what I can tell, the code in the tutorial and in this repo here doesn't work on the server. I'm looking into it, but wanted to post and see if I missed anything.