tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

bundle-assets.py (2250B)


      1 #!/usr/bin/env python3
      2 """Bundle production entrypoints while preserving their import.meta.url bases."""
      3 import argparse
      4 import json
      5 from pathlib import Path
      6 import shutil
      7 import subprocess
      8 
      9 ENTRIES = ['dist/app.js', 'dist/wasm-worker.js', 'dist/local-module-worker.js',
     10            'runtime/haskell/client.mjs', 'runtime/haskell/worker.mjs']
     11 
     12 
     13 def bundle(root, probe):
     14     root = root.resolve()
     15     support = root / 'nix-support'
     16     support.mkdir(exist_ok=True)
     17     shutil.copyfile(root / 'runtime/haskell/pins.mjs', support / 'haskell-pins.mjs')
     18     shutil.copyfile(probe, root / 'dist/probe-api.js')
     19     graphs = {}
     20     for entry in [*ENTRIES, 'dist/probe-api.js']:
     21         output = 'bundled/' + entry
     22         subprocess.run(['esbuild', entry, '--bundle', '--format=esm',
     23                         '--platform=browser', '--target=es2020',
     24                         '--legal-comments=inline', '--outfile=' + output,
     25                         '--metafile=graph.json'], cwd=root, check=True)
     26         graph = json.loads((root / 'graph.json').read_text())
     27         # Computed URL imports retain explicit lazy runtime boundaries. All
     28         # statically resolved imports must be contained in their entrypoint.
     29         assert all(not row['imports'] for row in graph['outputs'].values())
     30         graphs[entry] = graph
     31     (support / 'bundle-graphs.json').write_text(json.dumps(graphs, indent=2) + '\n')
     32     (root / 'graph.json').unlink()
     33     for name in ['dist', 'runtime']:
     34         for path in (root / name).rglob('*'):
     35             if path.suffix in ['.js', '.mjs']:
     36                 path.unlink()
     37     for entry in ENTRIES:
     38         shutil.move(root / 'bundled' / entry, root / entry)
     39     shutil.move(root / 'bundled/dist/probe-api.js', support / 'probe-api.js')
     40     shutil.rmtree(root / 'bundled')
     41     # Empty module directories would otherwise imply unshipped entrypoints.
     42     for path in sorted((root / 'runtime').rglob('*'), reverse=True):
     43         if path.is_dir() and not any(path.iterdir()):
     44             path.rmdir()
     45 
     46 
     47 if __name__ == '__main__':
     48     parser = argparse.ArgumentParser(description=__doc__)
     49     parser.add_argument('root', type=Path)
     50     parser.add_argument('probe', type=Path)
     51     args = parser.parse_args()
     52     bundle(args.root, args.probe)