diff --git a/examples/configurable-chart/package.json b/examples/configurable-chart/package.json index 6eb74dc..870e60a 100644 --- a/examples/configurable-chart/package.json +++ b/examples/configurable-chart/package.json @@ -7,7 +7,8 @@ "check": "tsc --noEmit", "dev": "vite --host 127.0.0.1", "build": "bun run build:wasm && vite build --outDir build", - "verify": "bun verify.ts" + "verify": "bun verify.ts", + "package": "bun ../../tools/packaging/browser.ts" }, "devDependencies": { "@types/bun": "1.3.14", diff --git a/examples/configurable-chart/vite.config.ts b/examples/configurable-chart/vite.config.ts index 0267770..70538b2 100644 --- a/examples/configurable-chart/vite.config.ts +++ b/examples/configurable-chart/vite.config.ts @@ -54,4 +54,4 @@ const localEphemeris = (): Plugin => { }; }; -export default defineConfig({ plugins: [localEphemeris()] }); +export default defineConfig(({ mode }) => ({ plugins: [localEphemeris()], publicDir: mode === 'distribution' ? false : 'public', build: { license: mode === 'distribution' ? { fileName: 'licenses/javascript.md' } : false } })); diff --git a/tools/packaging/README.md b/tools/packaging/README.md new file mode 100644 index 0000000..db6c367 --- /dev/null +++ b/tools/packaging/README.md @@ -0,0 +1,11 @@ +# Browser packaging + +Normal builds and tests do not generate attribution. For distribution install +cargo-about 0.9.2 and rustup's rust-docs component for the pinned toolchain, then +run `bun run package` in examples/configurable-chart. Dependencies must already +be installed. The command builds the browser app into ignored +target/distribution/browser, with cargo-about and Vite license output. +Missing prerequisites or unresolved licenses fail packaging. Upstream license +retrieval may require network access. Ship the entire directory, including +licenses and ATTRIBUTION.txt. Supply ephemeris data separately at /ephemeris.bin. +No dependency license files or generated reports are committed. diff --git a/tools/packaging/about.toml b/tools/packaging/about.toml new file mode 100644 index 0000000..53a3d6d --- /dev/null +++ b/tools/packaging/about.toml @@ -0,0 +1,3 @@ +accepted = ["MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC", "Unicode-3.0", "Zlib", "BSL-1.0", "Unlicense", "MPL-2.0"] +ignore-dev-dependencies = true +ignore-build-dependencies = true diff --git a/tools/packaging/browser.ts b/tools/packaging/browser.ts new file mode 100644 index 0000000..574653c --- /dev/null +++ b/tools/packaging/browser.ts @@ -0,0 +1,25 @@ +import { execFileSync } from 'node:child_process'; +import { mkdirSync, readFileSync, writeFileSync, cpSync, rmSync } from 'node:fs'; +import { resolve, join } from 'node:path'; +const root = resolve(import.meta.dir, '../..'); +const app = join(root, 'examples/configurable-chart'); +const out = join(root, 'target/distribution/browser'); +const run = (args: string[], cwd = root) => execFileSync(args[0], args.slice(1), { cwd, stdio: 'inherit' }); +const about = process.env.CARGO_ABOUT ?? 'cargo-about'; +if (execFileSync(about, ['--version'], {encoding:'utf8'}).trim() !== 'cargo-about 0.9.2') throw Error('Install cargo-about 0.9.2'); +const sysroot = execFileSync('rustc', ['--print','sysroot'], {cwd:root,encoding:'utf8'}).trim(); +const standard = readFileSync(join(sysroot,'share/doc/rust/COPYRIGHT-library.html')); +run(['bun','run','build:wasm'], app); +rmSync(out, {recursive:true,force:true}); +run(['bun','x','--no-install','vite','build','--mode','distribution','--outDir',out], app); +const licenses = join(out,'licenses');mkdirSync(licenses,{recursive:true}); +run([about,'generate','--locked','--fail','--manifest-path','examples/configurable-chart/wasm/Cargo.toml','--target','wasm32-unknown-unknown','--config','tools/packaging/about.toml','--output-file',join(licenses,'rust.txt'),'tools/packaging/licenses.hbs']); +cpSync(join(root,'LICENSE'),join(licenses,'project.txt')); +cpSync(join(root,'THIRD_PARTY_NOTICES.md'),join(licenses,'adapted-code.md')); +writeFileSync(join(licenses,'rust-standard-library.html'),standard); +const vite = readFileSync(join(app,'node_modules/vite/LICENSE.md'),'utf8').split('# Licenses of bundled dependencies')[0]; +writeFileSync(join(licenses,'vite.txt'),vite); +writeFileSync(join(out,'ATTRIBUTION.txt'),'Licenses: licenses/project.txt, adapted-code.md, rust.txt, javascript.md, vite.txt and rust-standard-library.html.\nMPL source is available at the exact-version crate URLs in rust.txt under MPL-2.0.\n'); +const index = join(out, 'index.html'); +writeFileSync(index, readFileSync(index,'utf8').replace('', '

Attribution

')); +console.log(`Browser distribution: ${out}`); diff --git a/tools/packaging/licenses.hbs b/tools/packaging/licenses.hbs new file mode 100644 index 0000000..cf16299 --- /dev/null +++ b/tools/packaging/licenses.hbs @@ -0,0 +1,6 @@ +{{#each licenses}} +{{name}} +{{#each used_by}}{{crate.name}} {{crate.version}} — https://static.crates.io/crates/{{crate.name}}/{{crate.name}}-{{crate.version}}.crate +{{/each}} +{{{text}}} +{{/each}} \ No newline at end of file