fix(ui): serve SPA bundle from root, add cache-busting query, expose files API and include default CSS manager styles

This commit is contained in:
2026-01-10 13:51:41 +00:00
parent febf480b60
commit f02460e532
12 changed files with 89 additions and 42 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

28
changelog.md Normal file
View File

@@ -0,0 +1,28 @@
# Changelog
## 2026-01-10 - 1.0.4 - fix(ui)
serve SPA bundle from root, add cache-busting query, expose files API and include default CSS manager styles
- Changed HTML script src to use absolute path /bundle.js so the SPA loads correctly when served from various routes.
- Added cache-busting by appending ?v=${project.version} to /bundle.js in served index.html to avoid stale client bundles.
- Made the /api/files/:org/:package endpoint available (removed dev-only gating) so package file listing is accessible in non-dev modes, with permission check retained.
- Added cssManager.defaultStyles to the opencdn-mainpage element to ensure default design system styles are included.
## 2026-01-04 - 1.0.3 - maintenance
Consolidated maintenance updates.
- Minor maintenance and housekeeping ("update" commits).
- Duplicate update commits merged; no further detail provided in commit messages.
- No explicit functional changes described.
## 2022-01-06 - 1.0.11.0.3 - core fixes & release tags
Summary of early releases: core fixes and several non-descriptive release/tag commits.
- fix(core): update — core fixes applied (appears in 1.0.1 and 1.0.2).
- Non-descriptive release/tag commits for 1.0.2 and 1.0.3 (messages: "1.0.2", "1.0.3")—no details provided.
- These commits appear to be small fixes and housekeeping around the initial 1.0.x releases.
## 2022-01-05 - unknown - initial
Initial project commit.
- Project initialized ("Initial commit").

View File

@@ -14,7 +14,7 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="./bundle.js"></script>
<script type="module" src="/bundle.js"></script>
<script>
window.addEventListener('DOMContentLoaded', () => {
const appContainer = document.getElementById('app');

8
ts/00_commitinfo_data.ts Normal file
View File

@@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @push.rocks/commitinfo
*/
export const commitinfo = {
name: '@serve.zone/opencdn',
version: '1.0.4',
description: 'A CDN that serves files directly from npm packages'
}

File diff suppressed because one or more lines are too long

View File

@@ -133,51 +133,49 @@ export class UiPublicServer {
}
});
// API endpoint for file listing (dev mode)
if (this.options.mode === 'dev') {
expressApplication.get('/api/files/:org/:package', async (req, res) => {
const packageName = `${req.params.org}/${req.params.package}`;
const version = (req.query.version as string) || '';
const distTag = (req.query.disttag as string) || '';
// API endpoint for file listing
expressApplication.get('/api/files/:org/:package', async (req, res) => {
const packageName = `${req.params.org}/${req.params.package}`;
const version = (req.query.version as string) || '';
const distTag = (req.query.disttag as string) || '';
if (!this.options.allowedPackages.includes(packageName)) {
res.status(403).json({ error: 'Package not allowed' });
return;
}
if (!this.options.allowedPackages.includes(packageName)) {
res.status(403).json({ error: 'Package not allowed' });
return;
}
const baseDirectory = this.getPackageBaseDirectory(packageName);
const registry = this.getPackageRegistry(packageName);
const baseDirectory = this.getPackageBaseDirectory(packageName);
const registry = this.getPackageRegistry(packageName);
try {
const result = await registry.getFilesFromPackage(
packageName,
plugins.path.join(baseDirectory),
{ version, distTag }
);
try {
const result = await registry.getFilesFromPackage(
packageName,
plugins.path.join(baseDirectory),
{ version, distTag }
);
const files = result.map(smartfile => {
return smartfile.path.replace(plugins.path.join('package', baseDirectory), '');
});
const files = result.map(smartfile => {
return smartfile.path.replace(plugins.path.join('package', baseDirectory), '');
});
// Get package info for versions
const packageInfo = await registry.getPackageInfo(packageName).catch(() => null);
const versions = packageInfo?.allVersions?.slice(-20).reverse().map(v => v.version) || [];
// Get package info for versions
const packageInfo = await registry.getPackageInfo(packageName).catch(() => null);
const versions = packageInfo?.allVersions?.slice(-20).reverse().map(v => v.version) || [];
res.json({ files, versions });
} catch (err) {
res.status(404).json({ error: 'Package not found' });
}
});
res.json({ files, versions });
} catch (err) {
res.status(404).json({ error: 'Package not found' });
}
});
// Peek route serves the SPA
expressApplication.get('/peek/*', async (req, res) => {
await this.serveIndexHtml(req, res);
});
// Peek route serves the SPA
expressApplication.get('/peek/*', async (req, res) => {
await this.serveIndexHtml(req, res);
});
expressApplication.get('/peek', async (req, res) => {
await this.serveIndexHtml(req, res);
});
}
expressApplication.get('/peek', async (req, res) => {
await this.serveIndexHtml(req, res);
});
// Main package serving route
expressApplication.use('/', async (req, res) => {
@@ -229,6 +227,9 @@ export class UiPublicServer {
const configScript = `<script>window.__OPENCDN_CONFIG__ = ${JSON.stringify(config)};</script>`;
html = html.replace('</head>', `${configScript}\n</head>`);
// Add version query parameter to bundle.js for cache busting
html = html.replace('/bundle.js', `/bundle.js?v=${this.projectinfo.version}`);
res.setHeader('content-type', embeddedFile.contentType);
res.setHeader('cache-control', 'no-cache');
res.status(200).send(html);

View File

@@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @push.rocks/commitinfo
*/
export const commitinfo = {
name: '@serve.zone/opencdn',
version: '1.0.4',
description: 'A CDN that serves files directly from npm packages'
}

View File

@@ -4,6 +4,7 @@ import {
html,
customElement,
type TemplateResult,
cssManager,
css,
state,
} from '@design.estate/dees-element';
@@ -31,6 +32,7 @@ export class OpencdnMainpage extends DeesElement {
// Shadcn-like color palette
public static styles = [
cssManager.defaultStyles,
css`
:host {
--background: #09090b;