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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ OPENAI_BASE_URL=xxx
GOOGLE_CLIENT_ID=xxx
GOOGLE_CLIENT_SECRET=xxx
GOOGLE_HOSTED_DOMAIN=

# The feature flags.
FEATURE_AI_CHAT=true
4 changes: 4 additions & 0 deletions src/routes/(main)/(protected)/+layout.server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { error, redirect } from '@sveltejs/kit';

import { env } from '$env/dynamic/private';
import { db, type UserFindUniqueArgs, type UserGetPayload } from '$lib/server/db';

import type { LayoutServerLoad } from './$types';
Expand Down Expand Up @@ -39,5 +40,8 @@ export const load: LayoutServerLoad = async (event) => {
username: user.name,
csrfToken: event.locals.session.csrfToken(),
onboarded,
featureFlags: {
aiChat: env.FEATURE_AI_CHAT === 'true',
},
};
};
8 changes: 6 additions & 2 deletions src/routes/(main)/(protected)/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,9 @@
/>
{/if}

<ChatWidget onclick={handleChatWidgetClick} />
{#if page.data.featureFlags.aiChat}
<ChatWidget onclick={handleChatWidgetClick} />
{/if}
</div>
</div>
{/if}
Expand Down Expand Up @@ -327,6 +329,8 @@
</Modal>
{/if}

<ChatView isopen={isChatViewOpen} onclose={handleChatViewClose} />
{#if page.data.featureFlags.aiChat}
<ChatView isopen={isChatViewOpen} onclose={handleChatViewClose} />
{/if}

<OnboardingView isopen={isOnboardingViewOpen} onclose={handleOnboardingViewClose} />
20 changes: 17 additions & 3 deletions src/routes/(main)/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type Handle, redirect } from '@sveltejs/kit';
import { type Handle, json, redirect } from '@sveltejs/kit';
import { sequence } from '@sveltejs/kit/hooks';

import { env } from '$env/dynamic/private';
import { HOME_PATH, nanoid } from '$lib/helpers/index.js';
import { learnerAuth } from '$lib/server/auth/index.js';
import { logger } from '$lib/server/logger.js';
Expand All @@ -9,13 +10,25 @@ import { logger } from '$lib/server/logger.js';
* A handle that adds a request ID to the response headers and attaches a scoped logger to the
* event. Downstream handles are expected to use the scoped logger for logging.
*/
const requestLoggingHandle: Handle = async ({ event, resolve }) => {
const requestLoggingHandle: Handle = ({ event, resolve }) => {
const requestId = nanoid();

event.setHeaders({ 'X-Request-Id': requestId });
event.locals.logger = logger.child({ requestId });

return await resolve(event);
return resolve(event);
};

/**
* A handle that gates API routes behind feature flags.
* Returns 403 for disabled features before any further processing.
*/
const featureFlagHandle: Handle = ({ event, resolve }) => {
if (event.url.pathname.startsWith('/api/messages') && env.FEATURE_AI_CHAT !== 'true') {
return json(null, { status: 403 });
}

return resolve(event);
};

/**
Expand Down Expand Up @@ -52,6 +65,7 @@ const routeProtectionHandle: Handle = async ({ event, resolve }) => {

export const handle: Handle = sequence(
requestLoggingHandle,
featureFlagHandle,
learnerAuth.handle,
routeProtectionHandle,
);
Loading