From 2aa7a3fcd4f31f68b715032776b35616a1d25639 Mon Sep 17 00:00:00 2001 From: Alex van der Valk <21194068+alexvdvalk@users.noreply.github.com> Date: Tue, 28 Oct 2025 12:34:27 +0000 Subject: [PATCH 1/6] rename env variables to keep on server. Clean up some types --- cms/sveltekit/.env.example | 7 +- .../components/layout/NavigationBar.svelte | 1 - cms/sveltekit/src/lib/directus/directus.ts | 10 +- cms/sveltekit/src/lib/directus/forms.ts | 12 +- .../src/lib/directus/generateDirectusTypes.ts | 2 +- .../src/lib/types/directus-schema.ts | 116 ++++++------------ .../src/routes/[...permalink]/+page.svelte | 2 +- 7 files changed, 51 insertions(+), 99 deletions(-) diff --git a/cms/sveltekit/.env.example b/cms/sveltekit/.env.example index 9e3b943c..ceac67af 100644 --- a/cms/sveltekit/.env.example +++ b/cms/sveltekit/.env.example @@ -1,6 +1,7 @@ PUBLIC_DIRECTUS_URL=http://localhost:8055 -PUBLIC_DIRECTUS_TOKEN=STATIC_TOKEN_FROM_Webmaster_account PUBLIC_SITE_URL=http://localhost:3000 PUBLIC_DIRECTUS_FORM_TOKEN=STATIC_TOKEN_FROM_Frontend_Bot_User_account -DRAFT_MODE_SECRET=your-draft-mode-secret -PUBLIC_ENABLE_VISUAL_EDITING=true \ No newline at end of file +PUBLIC_ENABLE_VISUAL_EDITING=true + +DIRECTUS_SERVER_TOKEN=STATIC_TOKEN_FROM_Webmaster_account +DRAFT_MODE_SECRET=your-draft-mode-secret \ No newline at end of file diff --git a/cms/sveltekit/src/lib/components/layout/NavigationBar.svelte b/cms/sveltekit/src/lib/components/layout/NavigationBar.svelte index 8ac2d099..59617717 100644 --- a/cms/sveltekit/src/lib/components/layout/NavigationBar.svelte +++ b/cms/sveltekit/src/lib/components/layout/NavigationBar.svelte @@ -7,7 +7,6 @@ import SearchModal from '../ui/SearchModal.svelte'; import LightSwitch from './LightSwitch.svelte'; import { PUBLIC_DIRECTUS_URL } from '$env/static/public'; - import { goto } from '$app/navigation'; import { ChevronDown, Menu } from '@lucide/svelte'; import * as Collapsible from '$lib/components/ui/collapsible'; import setAttr from '$lib/directus/visualEditing'; diff --git a/cms/sveltekit/src/lib/directus/directus.ts b/cms/sveltekit/src/lib/directus/directus.ts index e68e1dd1..9aac46a5 100644 --- a/cms/sveltekit/src/lib/directus/directus.ts +++ b/cms/sveltekit/src/lib/directus/directus.ts @@ -16,8 +16,8 @@ import { PUBLIC_DIRECTUS_URL } from '$env/static/public'; // Helper for retrying fetch requests const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); -const fetchRetry = async (fetch: Function, count: number, ...args: any[]) => { - const response = await fetch(...args); +const fetchRetry = async (f: typeof fetch, count: number, ...args: any[]) => { + const response = await f(...args as Parameters); if (count > 2 || response.status !== 429) return response; @@ -33,11 +33,11 @@ const queue = new Queue({ intervalCap: 10, interval: 500, carryoverConcurrencyCo const directusUrl = PUBLIC_DIRECTUS_URL; -const getDirectus = (fetch: Function) => { +const getDirectus = (f: typeof fetch) => { const directus = createDirectus(directusUrl, { globals: { - fetch: (...args) => queue.add(() => fetchRetry(fetch, 0, ...args)) + fetch: (...args) => queue.add(() => fetchRetry(f, 0, ...args)) } }).with(rest()); @@ -46,7 +46,7 @@ const getDirectus = (fetch: Function) => { export const useDirectus = () => ({ // directus: directus as RestClient, - getDirectus: getDirectus as (fetch: Function) => RestClient, + getDirectus: getDirectus as (f: typeof fetch) => RestClient, readItems, readItem, readSingleton, diff --git a/cms/sveltekit/src/lib/directus/forms.ts b/cms/sveltekit/src/lib/directus/forms.ts index e38db60f..043b2fe2 100644 --- a/cms/sveltekit/src/lib/directus/forms.ts +++ b/cms/sveltekit/src/lib/directus/forms.ts @@ -1,10 +1,6 @@ import { useDirectus } from './directus'; import { PUBLIC_DIRECTUS_FORM_TOKEN } from '$env/static/public'; -interface SubmissionValue { - field: string; - value?: string; - file?: string; -} +import type { FormSubmission, FormSubmissionValue } from '$lib/types/directus-schema'; export const submitForm = async ( formId: string, @@ -20,7 +16,7 @@ export const submitForm = async ( } try { - const submissionValues: SubmissionValue[] = []; + const submissionValues: Array> = []; for (const field of fields) { const value = data[field.name]; @@ -47,9 +43,9 @@ export const submitForm = async ( } } - const payload = { + const payload: Partial = { form: formId, - values: submissionValues + values: submissionValues as unknown as FormSubmissionValue[] }; await directus.request(withToken(TOKEN, createItem('form_submissions', payload))); diff --git a/cms/sveltekit/src/lib/directus/generateDirectusTypes.ts b/cms/sveltekit/src/lib/directus/generateDirectusTypes.ts index c16a762b..dcab8552 100644 --- a/cms/sveltekit/src/lib/directus/generateDirectusTypes.ts +++ b/cms/sveltekit/src/lib/directus/generateDirectusTypes.ts @@ -5,7 +5,7 @@ config(); async function generateTypes() { const directusUrl = process.env.PUBLIC_DIRECTUS_URL; - const directusToken = process.env.PUBLIC_DIRECTUS_TOKEN; + const directusToken = process.env.DIRECTUS_SERVER_TOKEN; if (!directusUrl || !directusToken) { console.error( diff --git a/cms/sveltekit/src/lib/types/directus-schema.ts b/cms/sveltekit/src/lib/types/directus-schema.ts index 2b2b100e..71990705 100644 --- a/cms/sveltekit/src/lib/types/directus-schema.ts +++ b/cms/sveltekit/src/lib/types/directus-schema.ts @@ -1,30 +1,31 @@ + export interface ExtensionSeoMetadata { - title?: string; - meta_description?: string; - og_image?: string; - additional_fields?: Record; - sitemap?: { - change_frequency: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'; - priority: string; - }; - no_index?: boolean; - no_follow?: boolean; + title?: string; + meta_description?: string; + og_image?: string; + additional_fields?: Record; + sitemap?: { + change_frequency: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'; + priority: string; + }; + no_index?: boolean; + no_follow?: boolean; } export interface AiPrompt { /** @primaryKey */ id: string; + sort?: number | null; /** @description Unique name for the prompt. Use names like "create-article" or "generate-product-description". @required */ name: string; + /** @description Is this prompt published and available to use? */ + status?: 'draft' | 'in_review' | 'published'; /** @description Briefly explain what this prompt does in 1-2 sentences. */ description?: string | null; - /** @description Instructions that shape how the AI responds. */ - system_prompt?: string | null; /** @description Optional: Define the conversation structure between users and AI. Used to add context and improve outputs. */ messages?: Array<{ role: 'user' | 'assistant'; text: string }> | null; - sort?: number | null; - /** @description Is this prompt published and available to use? */ - status?: 'draft' | 'in_review' | 'published'; + /** @description Instructions that shape how the AI responds. */ + system_prompt?: string | null; date_created?: string | null; user_created?: DirectusUser | string | null; date_updated?: string | null; @@ -94,7 +95,7 @@ export interface BlockGallery { date_updated?: string | null; user_updated?: DirectusUser | string | null; /** @description Images to include in the image gallery. */ - items?: DirectusFile[] | string[] | null; + items?: BlockGalleryItem[] | string[]; } export interface BlockGalleryItem { @@ -212,16 +213,7 @@ export interface FormField { /** @description Unique field identifier, not shown to users (lowercase, hyphenated) */ name?: string | null; /** @description Input type for the field */ - type?: - | 'text' - | 'textarea' - | 'checkbox' - | 'checkbox_group' - | 'radio' - | 'file' - | 'select' - | 'hidden' - | null; + type?: 'text' | 'textarea' | 'checkbox' | 'checkbox_group' | 'radio' | 'file' | 'select' | 'hidden' | null; /** @description Text label shown to form users. */ label?: string | null; /** @description Default text shown in empty input. */ @@ -304,19 +296,7 @@ export interface Globals { /** @primaryKey */ id: string; /** @description Social media profile URLs */ - social_links?: Array<{ - url: string; - service: - | 'facebook' - | 'instagram' - | 'linkedin' - | 'x' - | 'vimeo' - | 'youtube' - | 'github' - | 'discord' - | 'docker'; - }> | null; + social_links?: Array<{ url: string; service: 'facebook' | 'instagram' | 'linkedin' | 'x' | 'vimeo' | 'youtube' | 'github' | 'discord' | 'docker' }> | null; /** @description Short phrase describing the site. */ tagline?: string | null; /** @description Main site title */ @@ -331,10 +311,10 @@ export interface Globals { openai_api_key?: string | null; /** @description The public URL for this Directus instance. Used in Flows. */ directus_url?: string | null; - /** @description Accent color for the website (used on buttons, links, etc). */ - accent_color?: string | null; /** @description Main logo shown on the site (for dark mode). */ logo_dark_mode?: DirectusFile | string | null; + /** @description Accent color for the website (used on buttons, links, etc). */ + accent_color?: string | null; date_created?: string | null; user_created?: DirectusUser | string | null; date_updated?: string | null; @@ -389,15 +369,7 @@ export interface PageBlock { /** @description The id of the page that this block belongs to. */ page?: Page | string | null; /** @description The data for the block. */ - item?: - | BlockHero - | BlockRichtext - | BlockForm - | BlockPost - | BlockGallery - | BlockPricing - | string - | null; + item?: BlockHero | BlockRichtext | BlockForm | BlockPost | BlockGallery | BlockPricing | string | null; /** @description The collection (type of block). */ collection?: string | null; /** @description Temporarily hide this block on the website without having to remove it from your page. */ @@ -505,12 +477,7 @@ export interface DirectusCollection { display_template?: string | null; hidden?: boolean; singleton?: boolean; - translations?: Array<{ - language: string; - translation: string; - singular: string; - plural: string; - }> | null; + translations?: Array<{ language: string; translation: string; singular: string; plural: string }> | null; archive_field?: string | null; archive_app_filter?: boolean; archive_value?: string | null; @@ -712,31 +679,12 @@ export interface DirectusSettings { public_background?: DirectusFile | string | null; public_note?: string | null; auth_login_attempts?: number | null; - auth_password_policy?: - | null - | `/^.{8,}$/` - | `/(?=^.{8,}$)(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()_+}{';'?>.<,])(?!.*\\s).*$/` - | null; + auth_password_policy?: null | `/^.{8,}$/` | `/(?=^.{8,}$)(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()_+}{';'?>.<,])(?!.*\\s).*$/` | null; storage_asset_transform?: 'all' | 'none' | 'presets' | null; - storage_asset_presets?: Array<{ - key: string; - fit: 'contain' | 'cover' | 'inside' | 'outside'; - width: number; - height: number; - quality: number; - withoutEnlargement: boolean; - format: 'auto' | 'jpeg' | 'png' | 'webp' | 'tiff' | 'avif'; - transforms: 'json'; - }> | null; + storage_asset_presets?: Array<{ key: string; fit: 'contain' | 'cover' | 'inside' | 'outside'; width: number; height: number; quality: number; withoutEnlargement: boolean; format: 'auto' | 'jpeg' | 'png' | 'webp' | 'tiff' | 'avif'; transforms: 'json' }> | null; custom_css?: string | null; storage_default_folder?: DirectusFolder | string | null; - basemaps?: Array<{ - name: string; - type: 'raster' | 'tile' | 'style'; - url: string; - tileSize: number; - attribution: string; - }> | null; + basemaps?: Array<{ name: string; type: 'raster' | 'tile' | 'style'; url: string; tileSize: number; attribution: string }> | null; mapbox_key?: string | null; module_bar?: 'json' | null; project_descriptor?: string | null; @@ -755,9 +703,16 @@ export interface DirectusSettings { public_registration_verify_email?: boolean; public_registration_role?: DirectusRole | string | null; public_registration_email_filter?: 'json' | null; + visual_editor_urls?: Array<{ url: string }> | null; + accepted_terms?: boolean | null; + project_id?: string | null; + mcp_enabled?: boolean; + mcp_allow_deletes?: boolean; + mcp_prompts_collection?: string | null; + mcp_system_prompt_enabled?: boolean; + mcp_system_prompt?: string | null; /** @description Settings for the Command Palette Module. */ command_palette_settings?: Record | null; - visual_editor_urls?: Array<{ url: string }> | null; } export interface DirectusUser { @@ -788,6 +743,7 @@ export interface DirectusUser { theme_light?: string | null; theme_light_overrides?: 'json' | null; theme_dark_overrides?: 'json' | null; + text_direction?: 'auto' | 'ltr' | 'rtl'; /** @description Blog posts this user has authored. */ posts?: Post[] | string[]; policies?: DirectusAccess[] | string[]; @@ -1038,4 +994,4 @@ export enum CollectionNames { directus_translations = 'directus_translations', directus_versions = 'directus_versions', directus_extensions = 'directus_extensions' -} +} \ No newline at end of file diff --git a/cms/sveltekit/src/routes/[...permalink]/+page.svelte b/cms/sveltekit/src/routes/[...permalink]/+page.svelte index b9a39259..6dbf1f7c 100644 --- a/cms/sveltekit/src/routes/[...permalink]/+page.svelte +++ b/cms/sveltekit/src/routes/[...permalink]/+page.svelte @@ -45,7 +45,7 @@ {data.title || ''} - +
From 38a3e1baca9b7c0ee6fb8f245e60ee6de7f7fa91 Mon Sep 17 00:00:00 2001 From: Alex van der Valk <21194068+alexvdvalk@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:20:55 +0000 Subject: [PATCH 2/6] add better types for sveltekit fetch function --- cms/sveltekit/src/lib/directus/directus.ts | 10 +++++----- cms/sveltekit/src/lib/directus/fetchers.ts | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/cms/sveltekit/src/lib/directus/directus.ts b/cms/sveltekit/src/lib/directus/directus.ts index 9aac46a5..8712a2d2 100644 --- a/cms/sveltekit/src/lib/directus/directus.ts +++ b/cms/sveltekit/src/lib/directus/directus.ts @@ -16,8 +16,8 @@ import { PUBLIC_DIRECTUS_URL } from '$env/static/public'; // Helper for retrying fetch requests const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); -const fetchRetry = async (f: typeof fetch, count: number, ...args: any[]) => { - const response = await f(...args as Parameters); +const fetchRetry = async (sveltekitFetch: typeof fetch, count: number, ...args: any[]) => { + const response = await sveltekitFetch(...args as Parameters); if (count > 2 || response.status !== 429) return response; @@ -33,11 +33,11 @@ const queue = new Queue({ intervalCap: 10, interval: 500, carryoverConcurrencyCo const directusUrl = PUBLIC_DIRECTUS_URL; -const getDirectus = (f: typeof fetch) => { +const getDirectus = (sveltekitFetch: typeof fetch) => { const directus = createDirectus(directusUrl, { globals: { - fetch: (...args) => queue.add(() => fetchRetry(f, 0, ...args)) + fetch: (...args) => queue.add(() => fetchRetry(sveltekitFetch, 0, ...args)) } }).with(rest()); @@ -46,7 +46,7 @@ const getDirectus = (f: typeof fetch) => { export const useDirectus = () => ({ // directus: directus as RestClient, - getDirectus: getDirectus as (f: typeof fetch) => RestClient, + getDirectus: getDirectus as (sveltekitFetch: typeof fetch) => RestClient, readItems, readItem, readSingleton, diff --git a/cms/sveltekit/src/lib/directus/fetchers.ts b/cms/sveltekit/src/lib/directus/fetchers.ts index 36ec219e..1863aa7d 100644 --- a/cms/sveltekit/src/lib/directus/fetchers.ts +++ b/cms/sveltekit/src/lib/directus/fetchers.ts @@ -10,10 +10,10 @@ import { type QueryFilter, aggregate, readItem, readSingleton } from '@directus/ export const fetchPageData = async ( permalink: string, postPage = 1, - fetch: RequestEvent['fetch'] + sveltekitFetch: typeof fetch ) => { const { getDirectus, readItems } = useDirectus(); - const directus = getDirectus(fetch); + const directus = getDirectus(sveltekitFetch); const pageData = await directus.request( readItems('pages', { @@ -170,9 +170,9 @@ export const fetchPageData = async ( /** * Fetches global site data, header navigation, and footer navigation. */ -export const fetchSiteData = async (fetch: RequestEvent['fetch']) => { +export const fetchSiteData = async (sveltekitFetch: typeof fetch) => { const { getDirectus } = useDirectus(); - const directus = getDirectus(fetch); + const directus = getDirectus(sveltekitFetch); try { const [globals, headerNavigation, footerNavigation] = await Promise.all([ @@ -242,10 +242,10 @@ export const fetchSiteData = async (fetch: RequestEvent['fetch']) => { export const fetchPostBySlug = async ( slug: string, options: { draft?: boolean }, - fetch: RequestEvent['fetch'] + sveltekitFetch: typeof fetch ) => { const { getDirectus, readItems } = useDirectus(); - const directus = getDirectus(fetch); + const directus = getDirectus(sveltekitFetch); try { const filter: QueryFilter = options?.draft @@ -278,9 +278,9 @@ export const fetchPostBySlug = async ( /** * Fetches related blog posts excluding the given ID. */ -export const fetchRelatedPosts = async (excludeId: string, fetch: RequestEvent['fetch']) => { +export const fetchRelatedPosts = async (excludeId: string, sveltekitFetch: typeof fetch) => { const { getDirectus, readItems } = useDirectus(); - const directus = getDirectus(fetch); + const directus = getDirectus(sveltekitFetch); try { const relatedPosts = await directus.request( @@ -301,9 +301,9 @@ export const fetchRelatedPosts = async (excludeId: string, fetch: RequestEvent[' /** * Fetches author details by ID. */ -export const fetchAuthorById = async (authorId: string, fetch: RequestEvent['fetch']) => { +export const fetchAuthorById = async (authorId: string, sveltekitFetch: typeof fetch) => { const { getDirectus, readUser } = useDirectus(); - const directus = getDirectus(fetch); + const directus = getDirectus(sveltekitFetch); try { const author = await directus.request( From cb894b41f79fccaf3091c758ba5be59984424a15 Mon Sep 17 00:00:00 2001 From: Alex van der Valk <21194068+alexvdvalk@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:22:29 +0000 Subject: [PATCH 3/6] remove unrequired import --- cms/sveltekit/src/lib/directus/fetchers.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/cms/sveltekit/src/lib/directus/fetchers.ts b/cms/sveltekit/src/lib/directus/fetchers.ts index 1863aa7d..aba6472a 100644 --- a/cms/sveltekit/src/lib/directus/fetchers.ts +++ b/cms/sveltekit/src/lib/directus/fetchers.ts @@ -1,5 +1,4 @@ import { error } from '@sveltejs/kit'; -import type { RequestEvent } from '@sveltejs/kit'; import { type BlockPost, type PageBlock, type Post, type Schema } from '../types/directus-schema'; import { useDirectus } from './directus'; import { type QueryFilter, aggregate, readItem, readSingleton } from '@directus/sdk'; From d218ecbcdabce3e02af69c982eff4cbc9d06a93c Mon Sep 17 00:00:00 2001 From: Alex van der Valk <21194068+alexvdvalk@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:54:27 +0000 Subject: [PATCH 4/6] remove fetch param in favour of getRequestEvent --- cms/sveltekit/src/lib/directus/directus.ts | 9 +++++--- cms/sveltekit/src/lib/directus/fetchers.ts | 22 +++++++++---------- .../src/routes/[...permalink]/+page.server.ts | 2 +- .../src/routes/blog/[slug]/+page.server.ts | 6 ++--- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/cms/sveltekit/src/lib/directus/directus.ts b/cms/sveltekit/src/lib/directus/directus.ts index 8712a2d2..b5b2ce00 100644 --- a/cms/sveltekit/src/lib/directus/directus.ts +++ b/cms/sveltekit/src/lib/directus/directus.ts @@ -13,6 +13,8 @@ import type { RestClient } from '@directus/sdk'; import Queue from 'p-queue'; import type { Schema } from '../types/directus-schema'; import { PUBLIC_DIRECTUS_URL } from '$env/static/public'; +import { getRequestEvent } from '$app/server'; + // Helper for retrying fetch requests const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); @@ -33,11 +35,12 @@ const queue = new Queue({ intervalCap: 10, interval: 500, carryoverConcurrencyCo const directusUrl = PUBLIC_DIRECTUS_URL; -const getDirectus = (sveltekitFetch: typeof fetch) => { +const getDirectus = () => { + const { fetch } = getRequestEvent(); const directus = createDirectus(directusUrl, { globals: { - fetch: (...args) => queue.add(() => fetchRetry(sveltekitFetch, 0, ...args)) + fetch: (...args) => queue.add(() => fetchRetry(fetch, 0, ...args)) } }).with(rest()); @@ -46,7 +49,7 @@ const getDirectus = (sveltekitFetch: typeof fetch) => { export const useDirectus = () => ({ // directus: directus as RestClient, - getDirectus: getDirectus as (sveltekitFetch: typeof fetch) => RestClient, + getDirectus: getDirectus as () => RestClient, readItems, readItem, readSingleton, diff --git a/cms/sveltekit/src/lib/directus/fetchers.ts b/cms/sveltekit/src/lib/directus/fetchers.ts index aba6472a..7165eddc 100644 --- a/cms/sveltekit/src/lib/directus/fetchers.ts +++ b/cms/sveltekit/src/lib/directus/fetchers.ts @@ -9,10 +9,9 @@ import { type QueryFilter, aggregate, readItem, readSingleton } from '@directus/ export const fetchPageData = async ( permalink: string, postPage = 1, - sveltekitFetch: typeof fetch ) => { const { getDirectus, readItems } = useDirectus(); - const directus = getDirectus(sveltekitFetch); + const directus = getDirectus(); const pageData = await directus.request( readItems('pages', { @@ -169,9 +168,9 @@ export const fetchPageData = async ( /** * Fetches global site data, header navigation, and footer navigation. */ -export const fetchSiteData = async (sveltekitFetch: typeof fetch) => { +export const fetchSiteData = async () => { const { getDirectus } = useDirectus(); - const directus = getDirectus(sveltekitFetch); + const directus = getDirectus(); try { const [globals, headerNavigation, footerNavigation] = await Promise.all([ @@ -241,10 +240,9 @@ export const fetchSiteData = async (sveltekitFetch: typeof fetch) => { export const fetchPostBySlug = async ( slug: string, options: { draft?: boolean }, - sveltekitFetch: typeof fetch ) => { const { getDirectus, readItems } = useDirectus(); - const directus = getDirectus(sveltekitFetch); + const directus = getDirectus(); try { const filter: QueryFilter = options?.draft @@ -277,9 +275,9 @@ export const fetchPostBySlug = async ( /** * Fetches related blog posts excluding the given ID. */ -export const fetchRelatedPosts = async (excludeId: string, sveltekitFetch: typeof fetch) => { +export const fetchRelatedPosts = async (excludeId: string) => { const { getDirectus, readItems } = useDirectus(); - const directus = getDirectus(sveltekitFetch); + const directus = getDirectus(); try { const relatedPosts = await directus.request( @@ -300,9 +298,9 @@ export const fetchRelatedPosts = async (excludeId: string, sveltekitFetch: typeo /** * Fetches author details by ID. */ -export const fetchAuthorById = async (authorId: string, sveltekitFetch: typeof fetch) => { +export const fetchAuthorById = async (authorId: string) => { const { getDirectus, readUser } = useDirectus(); - const directus = getDirectus(sveltekitFetch); + const directus = getDirectus(); try { const author = await directus.request( @@ -323,7 +321,7 @@ export const fetchAuthorById = async (authorId: string, sveltekitFetch: typeof f */ export const fetchPaginatedPosts = async (limit: number, page: number) => { const { getDirectus, readItems } = useDirectus(); - const directus = getDirectus(fetch); + const directus = getDirectus(); try { const response = await directus.request( readItems('posts', { @@ -347,7 +345,7 @@ export const fetchPaginatedPosts = async (limit: number, page: number) => { */ export const fetchTotalPostCount = async (): Promise => { const { getDirectus } = useDirectus(); - const directus = getDirectus(fetch); + const directus = getDirectus(); try { const response = await directus.request( diff --git a/cms/sveltekit/src/routes/[...permalink]/+page.server.ts b/cms/sveltekit/src/routes/[...permalink]/+page.server.ts index f1ce283a..61dfeb35 100644 --- a/cms/sveltekit/src/routes/[...permalink]/+page.server.ts +++ b/cms/sveltekit/src/routes/[...permalink]/+page.server.ts @@ -2,6 +2,6 @@ import { fetchPageData } from '$lib/directus/fetchers'; import type { PageServerLoad } from './$types'; export const load = (async (event) => { - const data = await fetchPageData(event.url.pathname, 1, event.fetch); + const data = await fetchPageData(event.url.pathname, 1); return data; }) satisfies PageServerLoad; diff --git a/cms/sveltekit/src/routes/blog/[slug]/+page.server.ts b/cms/sveltekit/src/routes/blog/[slug]/+page.server.ts index bdad207a..7ceeb0c8 100644 --- a/cms/sveltekit/src/routes/blog/[slug]/+page.server.ts +++ b/cms/sveltekit/src/routes/blog/[slug]/+page.server.ts @@ -7,7 +7,7 @@ import { DRAFT_MODE_SECRET } from '$env/static/private'; export const load = (async (event) => { const draft = event.url.searchParams.get('draft') === 'true' && event.url.searchParams.get('token') === DRAFT_MODE_SECRET; const slug = event.params.slug; - const post = await fetchPostBySlug(slug, { draft }, event.fetch); + const post = await fetchPostBySlug(slug, { draft }); if (!post) { error(404, { @@ -16,8 +16,8 @@ export const load = (async (event) => { } // TODO optimize this to run in parallel const ogImage = post.image ? getDirectusAssetURL(post.image) : null; - const relatedPosts = await fetchRelatedPosts(post.id, event.fetch); - const author = post.author ? await fetchAuthorById(post.author as string, event.fetch) : null; + const relatedPosts = await fetchRelatedPosts(post.id); + const author = post.author ? await fetchAuthorById(post.author as string) : null; return { post, From 48081429d79ad28f44110e233290dbd10cde2363 Mon Sep 17 00:00:00 2001 From: Alex van der Valk <21194068+alexvdvalk@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:03:52 +0000 Subject: [PATCH 5/6] add check if using Directus SDK on the client side --- cms/sveltekit/src/lib/directus/directus.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cms/sveltekit/src/lib/directus/directus.ts b/cms/sveltekit/src/lib/directus/directus.ts index b5b2ce00..937e93de 100644 --- a/cms/sveltekit/src/lib/directus/directus.ts +++ b/cms/sveltekit/src/lib/directus/directus.ts @@ -14,6 +14,7 @@ import Queue from 'p-queue'; import type { Schema } from '../types/directus-schema'; import { PUBLIC_DIRECTUS_URL } from '$env/static/public'; import { getRequestEvent } from '$app/server'; +import { browser } from '$app/environment'; // Helper for retrying fetch requests @@ -36,7 +37,16 @@ const queue = new Queue({ intervalCap: 10, interval: 500, carryoverConcurrencyCo const directusUrl = PUBLIC_DIRECTUS_URL; const getDirectus = () => { - const { fetch } = getRequestEvent(); + + let fetch = globalThis.fetch; + if (!browser) { + // server side, so using sveltekit optimized fetch + // https://svelte.dev/docs/kit/load#Making-fetch-requests + const { fetch: sveltekitFetch } = getRequestEvent(); + fetch = sveltekitFetch; + } else { + // client side, so sticking with default fetch + } const directus = createDirectus(directusUrl, { globals: { From e0dbd291fc5d2722b088b81f52cc347e416b8d68 Mon Sep 17 00:00:00 2001 From: Alex van der Valk <21194068+alexvdvalk@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:05:21 +0000 Subject: [PATCH 6/6] add addional link to recently released getRequestEvent() function --- cms/sveltekit/src/lib/directus/directus.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/cms/sveltekit/src/lib/directus/directus.ts b/cms/sveltekit/src/lib/directus/directus.ts index 937e93de..dee6dbdb 100644 --- a/cms/sveltekit/src/lib/directus/directus.ts +++ b/cms/sveltekit/src/lib/directus/directus.ts @@ -42,6 +42,7 @@ const getDirectus = () => { if (!browser) { // server side, so using sveltekit optimized fetch // https://svelte.dev/docs/kit/load#Making-fetch-requests + // https://svelte.dev/docs/kit/$app-server#getRequestEvent const { fetch: sveltekitFetch } = getRequestEvent(); fetch = sveltekitFetch; } else {