Download the PHP package phpdot/bun without Composer
On this page you can find all versions of the php package phpdot/bun. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package bun
phpdot/bun
The asset pipeline and JavaScript bridge for the PHPdot ecosystem. A version-pinned
Bun binary is installed once into your project, invisibly; the npm
ecosystem is reached through the console you already use; and one command turns the TypeScript and
CSS you author in resources/ into hashed, manifest-tracked assets in public/build. Nothing
JavaScript ever lands in the project root.
Table of Contents
- Requirements
- Installation
- Usage
- Where things live
- Console commands
- Building assets: TypeScript + Tailwind CSS
- Using the built assets in templates
- The
Bunservice
- Configuration
- Architecture
- Testing
- License
Requirements
| Requirement | Constraint |
|---|---|
| PHP | >= 8.5 |
ext-mbstring |
* |
nyholm/psr7 |
^1.8 |
phpdot/console |
^0.5 |
psr/http-client |
^1.0 |
psr/http-factory |
^1.0 |
psr/http-message |
^1.1 \|\| ^2.0 |
symfony/console |
^8.0 |
symfony/http-client |
^8.0 |
symfony/process |
^8.0 |
phpdot/package and phpdot/container are require-dev + suggest entries, phpdot/config a
suggest entry: in a PHPdot application they scaffold config/bun.php, fill its directories and
wire the services automatically; a plain PHP project constructs BunConfig by hand.
ext-pcntl is suggested — it forwards SIGINT/SIGTERM to long-lived children (run, --watch).
ext-curl is suggested — symfony/http-client uses its curl transport for runtime downloads when present.
Installation
In a PHPdot application that is the whole install: config/bun.php is generated, its three
directories are filled with portable absolute paths, and the Bun binary downloads itself on first use.
No Node, no nvm, no global tooling.
Usage
Where things live
Two configured directories, plus the JavaScript yard derived from one of them — all absolute:
| directory | default | holds |
|---|---|---|
resourcesDir |
resources |
your sources — TypeScript, CSS, and the build recipe build.php; nothing is ever generated here |
outputDir |
public/build |
built js/, css/, assets/ and manifest.json; wiped on every build |
| home (derived) | resources/.bun |
everything JavaScript, never configured: the Bun binary (runtime/), package.json, bun.lock, node_modules/, tsconfig.json, build intermediates (build/) |
The JavaScript manifest is committed; the heavy state is not. Add this to your .gitignore:
Everything else under resources/.bun is developer-machine state. A fresh clone is just
bun:resources:build: the binary downloads from the pin, bun install restores node_modules
from the committed lockfile, and the recipe runs.
Console commands
bun:build exposes bun's raw bundler flags for one-off builds; the pipeline above is the everyday path.
Building assets: TypeScript + Tailwind CSS
1. Install the tooling — it lands in resources/.bun, never in the project root:
2. Author your sources in resources/:
3. Write the recipe — resources/build.php, your file. It declares what to build; the pipeline
knows how:
The bridge() line exists because tailwind resolves @import "tailwindcss" from the input file's own
directory: a bridge inside resources/.bun/build sits beside node_modules, names the package, and pulls
your stylesheet in by path. Your CSS never names a package. Steps run in declaration order as one
fail-fast flow — the first failing step fails the build and nothing after it runs. bunx() runs any
installed tool from resources/.bun — tailwind, postcss, sass; run() runs one of your own scripts —
an icon extractor, a code generator:
A script that imports npm packages must live under home — stage it with bridge() as above — because
from elsewhere bun silently resolves its bare imports from the public registry; a script using only
Node builtins can stay in resources/. The watch: argument is one declaration for both modes: those
extra arguments are added only under --watch, where the step keeps running as the tool's own watcher.
A build never sees them, so a watch flag can never hang a one-shot build. For a watcher with no build
phase at all — a dev server, a codegen loop — use $recipe->bunxWatch('some-tool', ['serve']) or
$recipe->runWatch($script, ['serve']).
4. Build:
The pipeline wipes public/build, installs from the committed lockfile when node_modules is
missing, runs your steps — installed tools and your own scripts, each verified, fail-fast —
bundles the entries (minified, split,
content-hashed), writes manifest.json, and prepends @charset "UTF-8" to every built stylesheet.
With --watch, entry names stay stable so the manifest remains valid all session, and any step with
watch: arguments keeps running as a side process beside bun's own watcher.
Bare imports such as import { nanoid } from 'nanoid' resolve through resources/.bun/tsconfig.json,
which the first build writes with a paths mapping to node_modules and the @build/* alias. After
that the file is yours — add targets, libs, strictness.
Using the built assets in templates
The manifest keys every output by the authored entry, relative to resources/. The Twig extension
is your application's, and it is not auto-discovered: phpdot/template discovers extensions
only from classes inside installed packages, never from application code. Write the few lines, then
register the extension yourself before the first render — rebind View::class in your application's
DI, fetch the shared environment, and addExtension() behind a hasExtension() guard:
→ /build/js/platform-297bcrg3.js and /build/css/platform-dzwezbt3.css. Set
'baseUrl' => 'https://cdn.example.com/build' and the same calls emit CDN URLs; the hashes are the
cache-busting.
The Bun service
Everything the commands do is available as an injected service:
Every method returns bun's exit code, output streamed through.
Configuration
config/bun.php, generated once and yours thereafter:
The directories must be absolute — a relative path is refused at load with the remedy in the message.
The dirname(__DIR__) form keeps the file portable across machines.
Architecture
The Bun service is the façade. It asks the runtime layer for the platform's binary — downloaded from
the npm registry over PSR-18 on first use, integrity-verified, executed and version-checked, memoized
for the process — then delegates every operation through a single ProcessRunnerInterface seam. The
resources layer sits above it: a Recipe declares what to build, the AssetPipeline runs the stages,
and the Manifest maps authored entries to hashed URLs.
Testing
Integration tests that download the real binary and run real builds are gated behind BUN_LIVE=1.
License
MIT — see LICENSE.
phpdot/bun wraps Bun (oven-sh/bun), which is MIT licensed. The binary is downloaded per project from the npm registry and is never redistributed inside this package.
This repository is a read-only mirror. The canonical source lives in phpdot/monorepo; pull requests and issues are handled there: pulls · issues.
All versions of bun with dependencies
nyholm/psr7 Version ^1.8
php Version >=8.5
phpdot/console Version ^0.5
psr/http-client Version ^1.0
psr/http-factory Version ^1.0
psr/http-message Version ^1.1 || ^2.0
symfony/console Version ^8.0
symfony/http-client Version ^8.0
symfony/process Version ^8.0