{"_rev":"4-aabf88fe747f41d65e95ffbe97b4a9ae","time":{"created":"2026-06-28T08:18:57.340Z","modified":"2026-06-28T08:18:57.849Z","0.1.4":"2026-06-25T11:26:23.433Z","0.1.5":"2026-06-28T08:18:57.648Z"},"_id":"@canetoad/usdc-converter","name":"@canetoad/usdc-converter","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.5":{"name":"@canetoad/usdc-converter","version":"0.1.5","description":"Browser USDA/USDZ to binary USDC conversion for Canetoad AR exports.","type":"module","license":"PolyForm-Noncommercial-1.0.0","sideEffects":false,"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./three":{"types":"./dist/three.d.ts","import":"./dist/three.js"},"./wasm":{"types":"./wasm/toad_usdc_converter_wasm.d.ts","import":"./wasm/toad_usdc_converter_wasm.js"},"./wasm/toad_usdc_converter_wasm_bg.wasm":"./wasm/toad_usdc_converter_wasm_bg.wasm"},"scripts":{"clean":"rm -rf dist wasm rust/pkg rust/target","build":"bun run build:wasm && bun run build:ts","build:wasm":"PATH=\"$HOME/.cargo/bin:$PATH\" wasm-pack build rust --release --target web --out-dir ../wasm --out-name toad_usdc_converter_wasm && rm -f wasm/.gitignore","build:ts":"tsc -p tsconfig.json","test":"bun run build && vitest run","typecheck":"bun run build:wasm && bun run typecheck:ts","typecheck:ts":"tsc -p tsconfig.json --noEmit","pack:dry":"bun run build && npm pack --dry-run","release:notes":"node scripts/release-notes.mjs","release:validate":"node scripts/validate-release.mjs","smoke:package-consumer":"node scripts/smoke-package-consumer.mjs"},"keywords":["usd","usda","usdc","usdz","webassembly","threejs"],"peerDependencies":{"three":">=0.176.0 <1"},"peerDependenciesMeta":{"three":{"optional":true}},"publishConfig":{"access":"public","provenance":true},"devDependencies":{"@types/three":"0.176.0","fflate":"^0.8.2","three":"0.176.0","typescript":"^6.0.3","vite":"^8.1.0","vitest":"^4.0.18","wasm-pack":"^0.15.0"},"gitHead":"d09ed9ff490106d5647fdb8f962a02852bcd9347","_id":"@canetoad/usdc-converter@0.1.5","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-YYQX+nsGREWUnDLoXwrc9G1kMQqsg0GtNBGPnor9ScmorVk+NMLp5e2YnAnBsyF21U4N0o0aDVqfiJDZcCq/og==","shasum":"49be68f542434be0bdf0f04152ba96ed3604e7b9","tarball":"https://registry.npmjs.org/@canetoad/usdc-converter/-/usdc-converter-0.1.5.tgz","fileCount":18,"unpackedSize":1045823,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFOXbdiaHQMxtqOakVpaVUtTwhT4tJ/UZ0bLlEJtfHCjAiAc3RZLc877pxxb37shf69BQCyjzz+dexNwIme3jmH4Eg=="}]},"_npmUser":{"name":"lewi","email":"freiberg.lewis@gmail.com"},"directories":{},"maintainers":[{"name":"lewi","email":"freiberg.lewis@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/usdc-converter_0.1.5_1782634737494_0.7854015411028903"},"_hasShrinkwrap":false}},"maintainers":[{"name":"lewi","email":"freiberg.lewis@gmail.com"}],"description":"Browser USDA/USDZ to binary USDC conversion for Canetoad AR exports.","keywords":["usd","usda","usdc","usdz","webassembly","threejs"],"license":"PolyForm-Noncommercial-1.0.0","readme":"# @canetoad/usdc-converter\n\nBrowser-first USDA/USDZ to binary USDC conversion for Canetoad AR exports.\n\nThe package wraps the native Rust `openusd` crate in WebAssembly. It avoids the\nheavy OpenUSD C++/Emscripten path while still using a real USDC crate writer.\n\n## Why this path\n\n- `three/examples/jsm/exporters/USDZExporter` writes a USDZ package whose root\n  layer is ASCII USDA.\n- OpenUSD C++ can write USDC, but a browser build means shipping a large custom\n  wasm bundle and dealing with Emscripten integration.\n- TinyUSDZ has useful WASM work, but its USDC writer is still documented as\n  experimental.\n- `openusd` 0.5.0 is pure Rust and currently advertises read/write support for\n  `.usda`, `.usdc`, and `.usdz`, which makes a compact wasm wrapper feasible.\n\n## Install\n\n```bash\nbun add @canetoad/usdc-converter\n```\n\nThe base converter entrypoint has no runtime dependency on Three.js. If you use\nthe `@canetoad/usdc-converter/three` helper, install Three.js in the consuming\napp as well:\n\n```bash\nbun add three\n```\n\n## Usage\n\n```ts\nimport { exportThreeSceneToUsdzBlob } from \"@canetoad/usdc-converter/three\";\n\nconst blob = await exportThreeSceneToUsdzBlob(threeScene);\nconst url = URL.createObjectURL(blob);\n```\n\nOn iPhone/iPad, use the blob URL as an AR Quick Look link:\n\n```html\n<a rel=\"ar\" href=\"blob:...\">Open in AR</a>\n```\n\nFor lower-level control, convert the output of Three's `USDZExporter` directly:\n\n```ts\nimport { convertUsdzToBinaryUsdz } from \"@canetoad/usdc-converter\";\n\nconst asciiUsdz = await exporter.parseAsync(threeScene);\nconst binaryUsdz = await convertUsdzToBinaryUsdz(asciiUsdz);\n```\n\n`convertUsdzToBinaryUsdz()` preserves the first/root USD layer as text and\nconverts non-root ASCII USD layers from `.usda` or ASCII `.usd` to `.usdc`. It\nrewrites root-layer asset references that point at converted layers and copies\nnon-USD assets unchanged. Keeping the root/material layer as USDA avoids a\nRealityKit material-resolution failure observed with Rust-written binary root\nlayers, while still shrinking the heavy geometry layers.\n\nPackages that contain existing binary non-root USD layers plus ASCII non-root USD\nlayers that need conversion are rejected for now, because references inside\nexisting binary layers cannot be rewritten safely without a broader authoring\npass.\n\nIf your bundler does not serve package wasm assets from `import.meta.url`, pass\nthe wasm bytes or URL explicitly:\n\n```ts\nawait initToadUsdcConverter(wasmBytes);\n```\n\n## API\n\n- `initToadUsdcConverter(input?)`: initializes the wasm module. By default it\n  loads `wasm/toad_usdc_converter_wasm_bg.wasm` relative to the package module.\n  Pass wasm bytes or a wasm URL when your bundler cannot serve that package asset\n  from `import.meta.url`.\n- `convertUsdaToUsdc(source)`: converts a USDA string, `Blob`, or `Response` to a\n  raw `.usdc` `Uint8Array`. Accepts `{ wasm }` as an optional second argument.\n- `convertUsdzToBinaryUsdz(source)`: converts non-root ASCII USD layers in a\n  USDZ archive to binary USDC and returns a compact USDZ `Uint8Array`. Accepts\n  `ArrayBuffer`, `ArrayBufferView`, `Blob`, `Response`, or `Uint8Array`, plus\n  `{ wasm }` as an optional second argument.\n- `inspectUsdz(source)`: returns root-layer metadata for quick verification.\n  Accepts the same byte inputs and optional `{ wasm }` argument as\n  `convertUsdzToBinaryUsdz`.\n- `isUsdc(source)`: checks for the `PXR-USDC` magic bytes. Accepts the same byte\n  inputs and optional `{ wasm }` argument as `convertUsdzToBinaryUsdz`.\n\nThe `@canetoad/usdc-converter/three` entrypoint adds:\n\n- `exportThreeSceneToBinaryUsdz(scene, options?)`: runs Three's `USDZExporter`\n  and returns compact USDZ bytes with a USDA root and binary USDC geometry\n  layers. Options are Three `USDZExporterOptions` plus optional `wasm`,\n  `exporter`, and `textureUtils`.\n- `exportThreeSceneToUsdzBlob(scene, options?)`: same conversion, returned as a\n  `model/vnd.usdz+zip` `Blob` for browser links/downloads.\n\n## Build\n\n```bash\nbun install\nbun run build\nbun run typecheck\nbun run test\nnpm pack --dry-run\n```\n\nThe build requires Rust with the `wasm32-unknown-unknown` target:\n\n```bash\nrustup target add wasm32-unknown-unknown\n```\n\n`bun run typecheck` builds the generated WASM TypeScript bindings first. After\n`wasm/` already exists locally, `bun run typecheck:ts` runs the faster\nTypeScript-only check.\n\n## Validation\n\nThe Rust `openusd` crate is vendored because crates.io `0.5.0` writes SDF\nchild-list token vectors in a way Apple USD tools ignore. That produced USDC\nlayers with valid metadata but no visible prim hierarchy. The vendored patch\nuses `TokenVector` for child-list fields such as `primChildren` and\n`propertyChildren`, while leaving authored `token[]` attributes such as\n`xformOpOrder` as normal token arrays.\n\nOn macOS, `bun run test` uses `/usr/bin/usdchecker --arkit` and `/usr/bin/usdcat`\nto verify that generated USDZ files are ARKit-valid and that prims survive the\nconversion.\n\nThe converter also normalizes a Three `USDZExporter` material quirk before\nwriting USDC: texture shader inputs that Three authors as `token` are rewritten\nto the UsdShade types RealityKit follows (`string inputs:varname` and\n`float2 inputs:in.connect`). Apple's `usdchecker --arkit` can still report\nsuccess when those fields are left as `token`, but Quick Look renders the\nmaterial without its texture after binary conversion.\n\n## Runtime And Publishing\n\n`@canetoad/usdc-converter` is ESM-only and targets modern browsers and\nbundlers that can load WebAssembly package assets. Releases are published\npublicly to npm with provenance enabled through GitHub trusted publishing.\n\n## License\n\nPolyForm Noncommercial License 1.0.0. See `LICENSE` for license terms and\nrequired notices. The vendored `openusd` crate keeps its own license under\n`rust/vendor/openusd/LICENSE`.\n","readmeFilename":"README.md"}