Driver decisions (cards BUILD-OUTPUT-IS-ONE-FOLDER, BUILD-PLUGIN-STUDIO-IS-THE-OUTPUT-FRONT-PAGE).
- public/ holds only <tree>/ and a generated README.md. The build no longer writes public/index.html,
public/assets/ or public/__gallery/; `rm -rf public && bun run build` recreates exactly these two.
- The Plugin Studio is <tree>/index.html (tree-base "."), replacing the staging-forge chooser; nothing
is written above the tree. check:staging-lang, which tested that chooser, is retired with it.
- Assets are gathered in a temp directory and the fetched allowlist staged into <tree>/assets/ as
before. fonts/, images/, brand/ and legacy/ existed ONLY in public/assets: they are sources and move
to data/ (git mv). Poster previews keep their tracked sources in plugin-designs/*/assets/previews
(all 378 verified present).
- __gallery/ is archived out of public/ (a copy kept in the umbrella's _qa-cycle/archive) and out of
the build; generate-gallery renders only on request, into a directory you name, never public/.
- Native shells load the output folder: capacitor webDir public/<tree> (cap copy needs an index.html
there), Tauri frontendDist + window url relative to it. internal/sync-app-shells.mjs keeps both in
step with the tree's name on every build, so the coming rename stays one config line; the Capacitor
start page resolves its leaf tree-relative.
- dropin.include now lists only extras (README.md): the tree is always shipped and never named twice;
excludes are tree-relative ({tree}/...). clean.mjs removes the old root entries from existing
checkouts; the build lock and public/.gitignore's rules move out of public/.
- check:wp-embed read the BUILT manifest from gates:pre, before the build, so a from-scratch build
could never pass; it runs in gates:post and reads the tree name from config.
- Stale bundles refreshed by the clean build (key-cities, template-bundle, wall-of-people-groups);
the CLI doc's quoted scripts re-synced; capability exemplars regenerated; the '#' note leaves
check:stale-sweep-claim's command (it was already in //scripts).
Proof: rm -rf public && bun run build -> public/ = README.md + doxa-maps/; check:sri, check:drop,
check:parse, check:public-hygiene, check:quoted-scripts, check:capability-exemplars PASS; all 57 pages
(the front page + 56 leaves) mount under /doxa-maps/ on this tree. check:facet-cascade is red as on main.
71 lines
3.8 KiB
JavaScript
71 lines
3.8 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* sync-app-shells.mjs — point the native app shells at the OUTPUT FOLDER, from the tree's name.
|
|
*
|
|
* public/ holds only the output folder (Driver decision, card BUILD-OUTPUT-IS-ONE-FOLDER), so the app
|
|
* shells load THAT folder as their web root:
|
|
* capacitor.config.json "webDir": "public/<tree>"
|
|
* `cap copy` hard-fails unless webDir holds an index.html; the tree's front page is its
|
|
* index.html (the Plugin Studio), and set-app-start-page then installs the app's start page.
|
|
* deployment/src-tauri/tauri.conf.json build.frontendDist "../../public/<tree>"
|
|
* windows[].url relative to that folder
|
|
* The window url used to carry the tree's name ("doxa-maps/doxa-maps-spa/…"), so renaming the
|
|
* tree opened a BLANK desktop window (check:tauri caught it in the zz-maps rename proof).
|
|
*
|
|
* Both files are hand-formatted JSON, so only those values are replaced in place — nothing else
|
|
* moves. Idempotent. generate-tree runs this after writing the tree, so a rename stays ONE line
|
|
* (vite.doxa-maps-build-config.json "name").
|
|
*
|
|
* USAGE node internal/sync-app-shells.mjs [--check] --check: exit 1 if a file is out of date.
|
|
*/
|
|
import { readFileSync, writeFileSync, existsSync } from 'node:fs'
|
|
import { resolve, dirname } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { TREE_NAME } from './_tree-name.mjs'
|
|
|
|
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
|
|
|
/** Returns [{ file, changed: bool, notes: [] }]; writes unless check. */
|
|
export function syncAppShells({ check = false } = {}) {
|
|
const out = []
|
|
// ── Capacitor ──
|
|
const cap = resolve(ROOT, 'capacitor.config.json')
|
|
if (existsSync(cap)) {
|
|
const src = readFileSync(cap, 'utf8')
|
|
const want = `public/${TREE_NAME}`
|
|
const next = src.replace(/("webDir"\s*:\s*)"[^"]*"/, `$1"${want}"`)
|
|
out.push({ file: 'capacitor.config.json', changed: next !== src, notes: [`webDir -> ${want}`] })
|
|
if (next !== src && !check) { JSON.parse(next); writeFileSync(cap, next) }
|
|
}
|
|
// ── Tauri ──
|
|
const tauri = resolve(ROOT, 'deployment', 'src-tauri', 'tauri.conf.json')
|
|
if (existsSync(tauri)) {
|
|
const src = readFileSync(tauri, 'utf8')
|
|
const conf = JSON.parse(src)
|
|
const want = `../../public/${TREE_NAME}`
|
|
let next = src.replace(/("frontendDist"\s*:\s*)"[^"]*"/, `$1"${want}"`)
|
|
const notes = [`frontendDist -> ${want}`]
|
|
// A window url that still starts with a tree folder (any name that is a sibling of the bundles, i.e.
|
|
// the first segment is not a bundle) is made relative to the tree.
|
|
for (const w of (conf.app && conf.app.windows) || []) {
|
|
if (!w.url || /^[a-z]+:/i.test(w.url)) continue
|
|
const segs = w.url.split('/')
|
|
if (segs.length > 1 && !existsSync(resolve(ROOT, 'public', TREE_NAME, segs[0])) && existsSync(resolve(ROOT, 'public', TREE_NAME, ...segs.slice(1)))) {
|
|
const rel = segs.slice(1).join('/')
|
|
next = next.replace(`"url": "${w.url}"`, `"url": "${rel}"`)
|
|
notes.push(`window url ${w.url} -> ${rel}`)
|
|
}
|
|
}
|
|
out.push({ file: 'deployment/src-tauri/tauri.conf.json', changed: next !== src, notes })
|
|
if (next !== src && !check) { JSON.parse(next); writeFileSync(tauri, next) }
|
|
}
|
|
return out
|
|
}
|
|
|
|
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
const check = process.argv.includes('--check')
|
|
const res = syncAppShells({ check })
|
|
for (const r of res) console.log(` ${r.changed ? (check ? 'STALE' : 'wrote') : 'ok '} ${r.file} (${r.notes.join('; ')})`)
|
|
if (check && res.some((r) => r.changed)) { console.log('APP-SHELLS: FAIL — run node internal/sync-app-shells.mjs (generate-tree does it on every build).'); process.exit(1) }
|
|
console.log(`APP-SHELLS: ${check ? 'PASS — both shells load' : 'synced to'} public/${TREE_NAME}/`)
|
|
}
|