Dev server: serve assets from data/ and under the tree base, so a fresh clone's plugins get their data
Some checks are pending
build-gate / build (push) Waiting to run
Some checks are pending
build-gate / build (push) Waiting to run
Opening every plugin in the studio under the dev server on a fresh worktree, 13 of them mounted with empty data: every table, boundary and people-groups file 404'd. Two causes. - The dev asset lookup read public/assets (a mirror generate-tree writes, absent on a fresh clone) and plugin-designs/*/data, but never data/, the tracked source that mirror is copied from. It now falls back to data/<rel>, which is what DX gets when they clone. - Plugins nested in the studio resolve assets against the tree base the studio hands them (/__plugin-gallery/), as they do against <tree>/assets in the built tree, but only /assets/ was served. Both prefixes are served now. After: the same sweep shows the data 404s gone from all 13.
This commit is contained in:
parent
8415e8e112
commit
bf7e0e6464
1 changed files with 16 additions and 5 deletions
|
|
@ -6,7 +6,7 @@
|
|||
* galleryModel(discoverSpaRegistry())
|
||||
* GET /__plugin-gallery/manifest.json that model, manifest-shaped (the page fetches it live)
|
||||
* GET /__plugin-gallery/registry.json the discovery registry, machine-readable (smoke tools)
|
||||
* GET /assets/<rel> shared asset root (see resolveDevAsset)
|
||||
* GET /assets/<rel> (and /__plugin-gallery/assets/<rel>) shared asset root (see resolveDevAsset)
|
||||
* Wire-up: plugins: [vue(), cssInjectedByJsPlugin(), autoSpaDevPlugin(token)] in vite.config.js.
|
||||
* Verify: bun run smoke:gallery (internal/plugin-gallery-smoke.mjs — every element must boot)
|
||||
*/
|
||||
|
|
@ -26,7 +26,7 @@ import { readBuildConfig, renderGallery } from '../generate-gallery.mjs'
|
|||
// resources-map, cities-map, poster walls, tables) fetch `assetsBase + '/tables/*.json'`
|
||||
// and `'/boundaries/*.geojson'`. publicDir is false ON PURPOSE (a bundle build must never
|
||||
// inline public/), so dev has to serve the asset tree explicitly, the way the built site
|
||||
// does: public/assets first (exactly what generate-tree ships), else the per-bundle source
|
||||
// does: public/assets first (exactly what generate-tree ships), else the tracked data/ source, else the per-bundle source
|
||||
// of truth plugin-designs/<bundle>/data/<rel> when public/ has been cleaned.
|
||||
const DEV_ASSET_MIME = {
|
||||
'.json': 'application/json; charset=utf-8', '.geojson': 'application/geo+json; charset=utf-8',
|
||||
|
|
@ -39,6 +39,12 @@ export function resolveDevAsset(rel, root = REPO_ROOT) {
|
|||
const isFile = (p) => existsSync(p) && statSync(p).isFile()
|
||||
const shipped = resolve(root, 'public', 'assets', rel)
|
||||
if (isFile(shipped)) return shipped
|
||||
// data/<rel> is the TRACKED source of truth public/assets mirrors (see .gitignore): generate-tree
|
||||
// writes the mirror, so on a fresh clone — which is what DX receives — public/assets holds almost
|
||||
// nothing and every table, boundary and people-groups file 404'd under the dev server until the
|
||||
// first full build. Measured 2026-09-25 across the studio: 13 plugins mounted with empty data.
|
||||
const source = resolve(root, 'data', rel)
|
||||
if (isFile(source)) return source
|
||||
const profiles = resolve(root, 'plugin-designs')
|
||||
for (const name of readdirSync(profiles)) {
|
||||
if (name.startsWith('_') || name.startsWith('.')) continue
|
||||
|
|
@ -232,12 +238,17 @@ export function autoSpaDevPlugin(token = '') {
|
|||
// /assets/* — see resolveDevAsset. A miss is a REAL 404, never Vite's HTML
|
||||
// fallback: HTML-for-JSON made three maps die silently at JSON.parse before
|
||||
// they ever created a map, with no console error and no error card.
|
||||
if (path.startsWith('/assets/')) {
|
||||
// <tree>/assets/* too: a plugin nested in a cap-5 shell resolves its assets against the tree base
|
||||
// the shell hands it (plugin-studio passes /__plugin-gallery/), exactly as it would against
|
||||
// <tree>/assets in the built tree. Only /assets/ was served, so every nested data table 404'd.
|
||||
const assetPrefix = path.startsWith('/assets/') ? '/assets/'
|
||||
: path.startsWith('/__plugin-gallery/assets/') ? '/__plugin-gallery/assets/' : ''
|
||||
if (assetPrefix) {
|
||||
let rel = ''
|
||||
try { rel = decodeURIComponent(path.slice('/assets/'.length)) } catch { rel = '' }
|
||||
try { rel = decodeURIComponent(path.slice(assetPrefix.length)) } catch { rel = '' }
|
||||
if (!rel || rel.split('/').includes('..')) { res.statusCode = 400; return res.end('bad asset path') }
|
||||
const file = resolveDevAsset(rel)
|
||||
if (!file) return json(res, { error: 'asset not found', asset: rel, looked: ['public/assets/', 'plugin-designs/*/data/'] }, 404)
|
||||
if (!file) return json(res, { error: 'asset not found', asset: rel, looked: ['public/assets/', 'data/', 'plugin-designs/*/data/'] }, 404)
|
||||
res.statusCode = 200
|
||||
res.setHeader('Content-Type', DEV_ASSET_MIME[extname(file).toLowerCase()] || 'application/octet-stream')
|
||||
res.setHeader('Cache-Control', 'no-cache')
|
||||
|
|
|
|||
Loading…
Reference in a new issue