webapp-scaffold/bin/inject-hashed-filenames.py
Uwe Schuster 55968fbd73 v0.1.0: fetch/postprocess/inject scripts + vite config factories
Bootstraps the shared frontend build glue for webapp-template-derived
projects:

  bin/fetch-openapi.sh         — pull Swagger JSON from a running backend
  bin/postprocess-openapi.py   — fix oatpp 1.3 rough edges before orval
  bin/inject-hashed-filenames.py — rewrite HTML tags, config-driven
  src/vite-config.ts           — defineAdminConfig / defineGuestConfig
  templates/orval.config.template.ts — starting point for derived repos

Package name @uschuster/webapp-scaffold. Consumed as a devDependency
through the internal Forgejo npm registry; binaries exposed for use in
package.json scripts. createCoreFetch + i18n deferred to v0.2 / v0.3.

Closes fewo-webapp#414

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 22:06:58 +02:00

76 lines
2.3 KiB
Python
Executable file

#!/usr/bin/env python3
"""Rewrite HTML script tags to point at Vite's hashed production bundle.
Usage:
inject-hashed-filenames.py CONFIG_JSON [BUILD_DIR]
CONFIG_JSON is a path to a JSON file listing the entries to rewrite. The
schema mirrors the two hard-coded entries fewo-webapp had baked into an
earlier version of this script:
[
{
"manifest": "static/dist/.vite/manifest.json",
"html": "static/index.html",
"old_src": "/static/dist/app.js"
},
{
"manifest": "static/guest/dist/.vite/manifest.json",
"html": "static/guest/index.html",
"old_src": "/guest/dist/guest-app.js"
}
]
All paths are resolved relative to BUILD_DIR (defaults to the repo root
containing the config file's parent chain → `$PWD`).
"""
import json
import os
import sys
def inject(manifest_path: str, html_path: str, old_src: str) -> None:
if not os.path.exists(manifest_path):
print(f"skip: no manifest at {manifest_path}")
return
if not os.path.exists(html_path):
print(f"skip: no html at {html_path}")
return
with open(manifest_path) as f:
manifest = json.load(f)
for entry in manifest.values():
if not entry.get("isEntry"):
continue
hashed = entry["file"]
new_src = f"{os.path.dirname(old_src)}/{hashed}"
with open(html_path) as f:
html = f.read()
if old_src not in html:
print(f"skip: {old_src!r} not in {html_path}")
return
with open(html_path, "w") as f:
f.write(html.replace(old_src, new_src))
print(f"{old_src} -> {new_src}")
return
print(f"skip: no isEntry row in {manifest_path}")
def main() -> int:
if len(sys.argv) < 2:
print("usage: inject-hashed-filenames.py CONFIG_JSON [BUILD_DIR]", file=sys.stderr)
return 2
cfg_path = sys.argv[1]
build_dir = sys.argv[2] if len(sys.argv) > 2 else os.getcwd()
with open(cfg_path) as f:
entries = json.load(f)
for e in entries:
inject(
os.path.join(build_dir, e["manifest"]),
os.path.join(build_dir, e["html"]),
e["old_src"],
)
return 0
if __name__ == "__main__":
sys.exit(main())