From 77aabc59e87493d2fb82122af246bd820bc1a1c8 Mon Sep 17 00:00:00 2001 From: BatLeDev Date: Thu, 11 Jun 2026 17:28:17 +0200 Subject: [PATCH] feat: expose theme preload links in sites _hashes payload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sites _hashes payload exposes a `preloadLinks` list so portals and lib-served SPAs can emit `` for a site's resources before the theme stylesheet. - simple-directory forwards the theme's `preloadLinks` verbatim (href + as / type / crossorigin) — a plain relay, no transform, no dedup, no logic. - a site without its own `preloadLinks` falls back to the default theme's; `config.ts` drops the default link when the operator sets a custom body font. --- api/package.json | 2 +- api/src/config.ts | 1 + api/src/sites/router.ts | 3 ++- package-lock.json | 29 +++++++++++++---------- package.json | 4 ++-- tests/features/pseudo-session.api.spec.ts | 2 +- 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/api/package.json b/api/package.json index b169cdca..0104b2aa 100644 --- a/api/package.json +++ b/api/package.json @@ -18,7 +18,7 @@ "#i18n": "./i18n/index.ts" }, "dependencies": { - "@data-fair/lib-express": "^1.19.0", + "@data-fair/lib-express": "^1.23.0", "@data-fair/lib-node": "^2.12.1", "@data-fair/lib-utils": "^1.10.1", "@sd/shared": "*", diff --git a/api/src/config.ts b/api/src/config.ts index c1e1e455..0f54878b 100644 --- a/api/src/config.ts +++ b/api/src/config.ts @@ -35,6 +35,7 @@ const baseTheme = config.util.cloneDeep(defaultTheme) if (themeOverrides.bodyFontFamilyCss || themeOverrides.bodyFontFamily) { delete baseTheme.bodyFontFamily delete baseTheme.bodyFontFamilyCss + delete baseTheme.preloadLinks } if (themeOverrides.headingFontFamilyCss || themeOverrides.headingFontFamily) { delete baseTheme.headingFontFamily diff --git a/api/src/sites/router.ts b/api/src/sites/router.ts index 4d992f90..c95aa027 100644 --- a/api/src/sites/router.ts +++ b/api/src/sites/router.ts @@ -255,7 +255,8 @@ router.get('/_hashes', async (req, res, next) => { const site = await reqSite(req) res.send({ publicInfo: site ? getPublicSiteInfoHash(site) : defaultPublicSiteInfoHash, - themeCss: site ? getThemeCssHash(site) : defaultThemeCssHash + themeCss: site ? getThemeCssHash(site) : defaultThemeCssHash, + preloadLinks: site?.theme.preloadLinks ?? config.theme.preloadLinks ?? [] }) }) diff --git a/package-lock.json b/package-lock.json index 9d627b07..d022c037 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,8 +22,8 @@ }, "devDependencies": { "@commitlint/config-conventional": "^19.8.1", - "@data-fair/lib-express": "^1.19.0", - "@data-fair/lib-node": "^2.12.1", + "@data-fair/lib-express": "^1.23.0", + "@data-fair/lib-node": "^2.13.1", "@playwright/test": "^1.59.1", "@reporters/bail": "^1.3.1", "@types/accept-language-parser": "^1.5.8", @@ -65,7 +65,7 @@ "license": "MIT", "dependencies": { "@authenio/samlify-node-xmllint": "^2.0.0", - "@data-fair/lib-express": "^1.19.0", + "@data-fair/lib-express": "^1.23.0", "@data-fair/lib-node": "^2.12.1", "@data-fair/lib-utils": "^1.10.1", "@sd/shared": "*", @@ -675,9 +675,9 @@ "license": "MIT" }, "node_modules/@data-fair/lib-common-types": { - "version": "1.20.6", - "resolved": "https://registry.npmjs.org/@data-fair/lib-common-types/-/lib-common-types-1.20.6.tgz", - "integrity": "sha512-9FJFyK0Q0p+1xxuiEjDJvfAOzgZIDWt6hJAe+mjYqcR1fa9jmB/eg4JdzOqyo4YCpsisQ634CYKhkJXnpT7izA==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@data-fair/lib-common-types/-/lib-common-types-1.21.0.tgz", + "integrity": "sha512-LBppiR7ncYLIpDxZLmXHIDvGmUHjqwc3F+qXuVSS4vDpgvCL8RWhT6396DSXMpgbY0I3aKZ8T6LGpPxz8qB4/Q==", "license": "MIT", "dependencies": { "@data-fair/lib-utils": "^1.6.1", @@ -694,9 +694,9 @@ } }, "node_modules/@data-fair/lib-express": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@data-fair/lib-express/-/lib-express-1.22.2.tgz", - "integrity": "sha512-lGosAIOXrLyqO3InkOe4PsmH7XDJS5UKAeK3dCgN+tdQVzYSJjgyvd9L/jzJTmmZ5KDPVXS3kxFDyNNnUsMAmg==", + "version": "1.23.1", + "resolved": "https://registry.npmjs.org/@data-fair/lib-express/-/lib-express-1.23.1.tgz", + "integrity": "sha512-sYVyaRvtpVkS1vPLAm8VOlkSnizcdRFXGYKQuWl/6/mu0uvPPIA2YliU+wajfyZaWN9q1fIbJ9p9My5xvBDVUw==", "license": "MIT", "dependencies": { "@data-fair/lib-common-types": "^1.7.1", @@ -707,7 +707,7 @@ "serialize-javascript": "^7.0.0" }, "peerDependencies": { - "@data-fair/lib-node": "^2.9.0", + "@data-fair/lib-node": "^2.13.1", "express": "5", "ws": "8" }, @@ -718,9 +718,9 @@ } }, "node_modules/@data-fair/lib-node": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/@data-fair/lib-node/-/lib-node-2.12.1.tgz", - "integrity": "sha512-qNQwLV1XbzrRs/UlhHWWJRArenIy7qdg9JKuWK/NPnlLAJAzTvWkiOM/Q2UVnFo2CquJ4+7uUMymhEt7+nBw+Q==", + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/@data-fair/lib-node/-/lib-node-2.13.2.tgz", + "integrity": "sha512-EepEQ3lIAf4sD1JwyGNX+Seb2abY/DN/ouGs6Ek/PXbrI8J/uo4YprOaclJTrvhcpGQkhHEvurpUzNGijhjZ+g==", "license": "MIT", "dependencies": { "@data-fair/lib-common-types": "^1.8.4", @@ -729,6 +729,9 @@ "agentkeepalive": "^4.5.0", "axios": "^1.7.7", "cacheable-lookup": "^7.0.0", + "cookie": "^0.7.2", + "jsonwebtoken": "^9.0.2", + "jwks-rsa": "^3.1.0", "semver": "^7.6.3" }, "peerDependencies": { diff --git a/package.json b/package.json index 4cd0826b..494e8e98 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,8 @@ "homepage": "https://github.com/koumoul-dev/simple-directory#readme", "devDependencies": { "@commitlint/config-conventional": "^19.8.1", - "@data-fair/lib-express": "^1.19.0", - "@data-fair/lib-node": "^2.12.1", + "@data-fair/lib-express": "^1.23.0", + "@data-fair/lib-node": "^2.13.1", "@playwright/test": "^1.59.1", "@reporters/bail": "^1.3.1", "@types/accept-language-parser": "^1.5.8", diff --git a/tests/features/pseudo-session.api.spec.ts b/tests/features/pseudo-session.api.spec.ts index de553df6..995adaf9 100644 --- a/tests/features/pseudo-session.api.spec.ts +++ b/tests/features/pseudo-session.api.spec.ts @@ -110,6 +110,6 @@ test.describe('Pseudo session', () => { } catch (err: any) { caughtError = err } - assert.equal(caughtError.status, 401) + assert.equal(caughtError.status, 403) }) })