Skip to main content

stacks-plugins

Use when working with the Stacks preload chain and Bun plugins - the env plugin, the framework preloader, how auto-imports get injected into globalThis, why a command does or does not see framework globals, the bun-plugin-stx static-serve plugin, or writing a Bun plugin. Covers bunfig.toml preload and storage/framework/defaults/resources/plugins/preloader.ts.

Informations de source

Dépôt
stacksjs/stacks
Dernière activité de la source
29 août 2026 à 17:05
Langue détectée de SKILL.md
anglais
Étoiles
631
Forks
20

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
stacks-plugins
description
Use when working with the Stacks preload chain and Bun plugins - the env plugin, the framework preloader, how auto-imports get injected into globalThis, why a command does or does not see framework globals, the bun-plugin-stx static-serve plugin, or writing a Bun plugin. Covers bunfig.toml preload and storage/framework/defaults/resources/plugins/preloader.ts.
license
MIT
compatibility
Bun >= 1.3.0, TypeScript
allowed-tools
Read Edit Write Bash Grep Glob
# Stacks Plugins and the Preload Chain Stacks has **no `@stacksjs/plugins` package**. "Plugins" here means Bun's native plugin API plus the two modules `bunfig.toml` preloads before any Stacks code runs. If you are chasing "why is `User` undefined in this command" or "why did `.env` not decrypt", this is the skill. ## Key Paths - Preload declaration: `bunfig.toml` (`preload`, at the root and under `[test]`) - Env plugin: `storage/framework/core/env/plugin.ts` - Framework preloader: `storage/framework/defaults/resources/plugins/preloader.ts` - Static-serve plugin: `bunfig.toml`, `[serve.static] plugins = ["bun-plugin-stx"]` ## The preload chain `bunfig.toml` preloads two modules, **in this order**: ```toml preload = [ "./storage/framework/core/env/plugin.ts", "./storage/framework/defaults/resources/plugins/preloader.ts", ] ``` 1. **Env plugin** loads `.env` and decrypts dotenvx-style encrypted values, so everything downstream reads plaintext from `process.env`. 2. **Preloader** loads env files for the resolved environment, then injects the framework's server auto-imports into `globalThis`. Order is load-bearing: the preloader reads decrypted secrets, so it has to run second. Tests preload a different pair - the env plugin and `tests/setup.ts` - so the suite gets production env semantics without the auto-import graph. ## What the preloader does ### 1. Resolves the environment Before loading any `.env` file it works out `APP_ENV`, because that decides *which* file gets decrypted: - `deploy staging` and `deploy --staging` both resolve to `staging`. Both forms are handled; CI uses the flag form. - `cloud:remove`, `cloud:destroy`, `cloud:cleanup`, `undeploy` force `production`. - Bare `deploy` defaults to `production`. ### 2. Loads and decrypts env files Gated on **`isRepl` / `isPostinstall` only** - never on the fast-command list below. Fast commands (`migrate`, `build`, `seed`, ...) genuinely need decrypted config; gating them here caused stacksjs/stacks#2048, where an encrypted `.env.<env>` silently never decrypted even with the key present. Postinstall skips because `@stacksjs/env` may not be linked yet mid-install. ### 3. Injects auto-imports into `globalThis` Loads ~24 framework packages plus everything in `app/Jobs/` and `resources/functions/`, assigning every named export onto `globalThis`. That is why `await User.find(1)` and `response.json(...)` work in an action with no import statement. See `stacks-auto-imports` for the full manifest. A `protectedGlobals` set guards the runtime: `process`, `fetch`, `Promise`, `Bun`, `console` and friends are never overwritten, whatever a package exports. ## The fast-command skip (the usual gotcha) Auto-import injection is **skipped** when the first CLI argument matches: ``` dev build test lint migrate fresh seed generate make key:generate scaffold:crud version help --version -v --help -h ``` Prefix matches count, so `generate:migrations` skips along with `generate`. Two reasons: cold-start speed, and correctness. Codegen commands must not pull the router and ORM graph in before `bun-query-builder` can diff schemas - a broken `@stacksjs/bun-router` install used to make `generate:migrations` exit 1 with no output at all, because the preloader died loading `@stacksjs/router`. **Consequence:** inside those commands, framework globals do not exist. Import what you need explicitly. The REPL skips too (`!process.argv[1]`), as does anything running under `npm_lifecycle_event === 'postinstall'`. ### Opting back in The preloader exports `loadAutoImports()` so a server entrypoint can pull the graph in deliberately: ```ts const { loadAutoImports } = await import('../../../defaults/resources/plugins/preloader.ts') await loadAutoImports() ``` `dev/api.ts` does exactly this. Bun consumes `--watch`, so a directly-run server script sees an empty `argv.slice(2)` and would otherwise be indistinguishable from a bare invocation. ## Writing a Bun plugin Use Bun's native API directly - there is no framework wrapper to import: ```ts import { plugin } from 'bun' plugin({ name: 'my-loader', setup(build) { build.onLoad({ filter: /\.custom$/ }, async (args) => { const contents = await Bun.file(args.path).text() return { contents: transform(contents), loader: 'ts' } }) }, }) ``` Register it by adding the module to `preload` in `bunfig.toml`. A plugin only affects the process that preloaded it. ## Gotchas - **No `@stacksjs/plugins` package.** Import `plugin` from `bun`. - **Preload order matters.** Env decryption has to precede the preloader. - **Fast commands have no globals.** If a `make:*` or `generate:*` command needs a framework symbol, import it - do not rely on auto-imports. - **`bun-plugin-stx` is a static-serve plugin**, wired through `[serve.static] plugins` in `bunfig.toml`. The preloader's own `import 'bun-plugin-stx'` line is commented out; stx compilation in the dev server runs through the stx package, not that import. - **Preloader failures are silent per package.** Each import sits in its own `try {} catch {}`, so a package that fails to build leaves its globals undefined instead of crashing the process. A mysteriously undefined global is usually an unbuilt package - check `storage/framework/core/<pkg>/dist`. - **Adding a global?** Export it from a package already in the preloader's list, or from `resources/functions/`, then run `buddy generate --types` so the declarations match the runtime.
Voir sur GitHub