@teacss/bun 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +97 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021-PRESENT Anthony Fu <https://github.com/antfu>
|
|
4
|
+
Copyright (c) 2026-PRESENT Billgo <hi@billgo.me>
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# @teacss/bun
|
|
2
|
+
|
|
3
|
+
**Bun build plugin for TeaCSS.**
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
The plugin emits `virtual:teacss.css`, resolves CSS-entry configuration, and
|
|
8
|
+
transforms TeaCSS CSS directives.
|
|
9
|
+
|
|
10
|
+
Use this package when an application or build tool runs through `Bun.build`,
|
|
11
|
+
including programmatic watch builds. It owns Bun's plugin and watcher
|
|
12
|
+
lifecycles; use `@teacss/cli` for standalone CSS output, or the matching
|
|
13
|
+
framework integration when another build system owns the module graph.
|
|
14
|
+
|
|
15
|
+
For an application using the stable facade import, install the adapter beside
|
|
16
|
+
`teacss`:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
bun add teacss
|
|
20
|
+
bun add -d @teacss/bun
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { pluginTeacss } from "teacss/bun";
|
|
27
|
+
|
|
28
|
+
await Bun.build({
|
|
29
|
+
entrypoints: ["./src/index.ts"],
|
|
30
|
+
outdir: "./dist",
|
|
31
|
+
plugins: [pluginTeacss()],
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`pluginTeacss()` is the one-shot `Bun.build` integration. Bun 1.3 does not
|
|
36
|
+
expose watch-dependency registration or invalidation through its JavaScript
|
|
37
|
+
plugin API. For a programmatic watch build, use `watchTeacssBuild`; it watches
|
|
38
|
+
the Bun module graph together with the CSS entry, resolved config dependencies,
|
|
39
|
+
and positive `@source` roots:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { watchTeacssBuild } from "teacss/bun";
|
|
43
|
+
|
|
44
|
+
const session = await watchTeacssBuild(
|
|
45
|
+
{
|
|
46
|
+
entrypoints: ["./src/index.ts"],
|
|
47
|
+
outdir: "./dist",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
configOrPath: "./index.css",
|
|
51
|
+
onError: (error) => console.error(error),
|
|
52
|
+
},
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
await session.dispose();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The session exposes the latest successful `result`, background `error`, and
|
|
59
|
+
successful-build `version`. An initial build or config failure still returns an
|
|
60
|
+
active session: `result` is `undefined`, `version` is `0`, and `error` contains
|
|
61
|
+
the failure until a watched change succeeds. With `throw: false`, an
|
|
62
|
+
unsuccessful Bun result likewise calls only `onError` and does not replace the
|
|
63
|
+
last successful result, version, or module inputs.
|
|
64
|
+
|
|
65
|
+
A successful config reload replaces stale watch roots; a failed reload keeps
|
|
66
|
+
the last successful configuration active while watching the failed attempt's
|
|
67
|
+
dependencies for recovery. Callback failures are logged without changing build
|
|
68
|
+
state. Known watch roots are installed before each build, newly discovered
|
|
69
|
+
module roots receive a stabilizing rebuild, and failed native watchers are
|
|
70
|
+
replaced on the next attempt. Writes outside the tracked config, source, module,
|
|
71
|
+
and entry inputs do not force stabilization. Concurrent `dispose()` calls share
|
|
72
|
+
one completion and wait for all in-flight builds and callbacks. A callback may
|
|
73
|
+
also `await session.dispose()` to stop its own session; that reentrant call
|
|
74
|
+
cannot wait for the invoking callback itself, while disposal started outside a
|
|
75
|
+
callback still waits for the callback to finish.
|
|
76
|
+
|
|
77
|
+
`Bun.build` added JavaScript metafile support in Bun 1.3.6. On older supported
|
|
78
|
+
Bun versions, the helper omits that option and continues watching entry,
|
|
79
|
+
TeaCSS config, and `@source` roots, but it cannot discover additional
|
|
80
|
+
module-graph inputs outside those roots.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import "virtual:teacss.css";
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```css
|
|
87
|
+
@preset "standard";
|
|
88
|
+
@source "./src/**/*.{ts,tsx}";
|
|
89
|
+
@teacss;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Status
|
|
93
|
+
|
|
94
|
+
Pre-1.0. Install `@teacss/bun` beside `teacss`, then use the stable
|
|
95
|
+
`teacss/bun` facade subpath in applications. Source transformers such as
|
|
96
|
+
`:css:` compile-class are not run here. Integration authors may import
|
|
97
|
+
`@teacss/bun` directly when they intentionally do not use the facade.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { UserConfig, UserConfigDefaults } from "@teacss/core";
|
|
2
|
+
import { BuildConfig, BuildOutput, BunPlugin } from "bun";
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Bun plugin for TeaCSS. Use it with `Bun.build` (or a `bunfig.toml` preload):
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { pluginTeacss } from "@teacss/bun";
|
|
9
|
+
* await Bun.build({ entrypoints: ["./src/index.ts"], plugins: [pluginTeacss()] });
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* - `import "virtual:teacss.css"` (or `"teacss.css"`) resolves to the generated
|
|
13
|
+
* utilities — scanned from the project's content (the CSS entry's `@source`,
|
|
14
|
+
* else the default globs).
|
|
15
|
+
* - every `.css` gets `@apply` / `@screen` / `theme()` / `icon()` inlined (the
|
|
16
|
+
* directive transformer fast-bails when none are present).
|
|
17
|
+
*
|
|
18
|
+
* Configuration comes from the CSS entry (`index.css` with `@preset` / `@source`
|
|
19
|
+
* / `@custom`) or an inline `UserConfig` — there is no `teacss.config.*` file.
|
|
20
|
+
* Like `@teacss/rsbuild`, this path does not run source transformers (so the
|
|
21
|
+
* `:css:` compile-class transform is not applied here).
|
|
22
|
+
*/
|
|
23
|
+
declare function pluginTeacss(configOrPath?: UserConfig<object> | string, defaults?: UserConfigDefaults): BunPlugin;
|
|
24
|
+
interface WatchTeacssBuildOptions {
|
|
25
|
+
/** CSS entry file, discovery root, or inline configuration. */
|
|
26
|
+
configOrPath?: UserConfig<object> | string;
|
|
27
|
+
/** Defaults merged below the resolved TeaCSS configuration. */
|
|
28
|
+
defaults?: UserConfigDefaults;
|
|
29
|
+
/** Filesystem event coalescing delay. @default 50 */
|
|
30
|
+
debounce?: number;
|
|
31
|
+
onBuild?: (result: BuildOutput) => void | Promise<void>;
|
|
32
|
+
onError?: (error: unknown) => void | Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
interface TeacssBuildWatchSession {
|
|
35
|
+
/** Latest background rebuild error, cleared by the next successful build. */
|
|
36
|
+
readonly error: unknown | undefined;
|
|
37
|
+
/** Latest successful build result, or undefined until the first success. */
|
|
38
|
+
readonly result: BuildOutput | undefined;
|
|
39
|
+
/** Number of successful builds. */
|
|
40
|
+
readonly version: number;
|
|
41
|
+
/** Stop this session without affecting other watch sessions. */
|
|
42
|
+
dispose(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Rebuild with Bun when either Bun's module graph or TeaCSS's graph-external
|
|
46
|
+
* config and `@source` inputs change. Bun 1.3's plugin API has no dependency
|
|
47
|
+
* registration or invalidation hook, so watch ownership lives in this helper.
|
|
48
|
+
*/
|
|
49
|
+
declare function watchTeacssBuild(buildConfig: BuildConfig, options?: WatchTeacssBuildOptions): Promise<TeacssBuildWatchSession>;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { TeacssBuildWatchSession, WatchTeacssBuildOptions, pluginTeacss, watchTeacssBuild };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{AsyncLocalStorage as e}from"node:async_hooks";import{existsSync as t,statSync as n,watch as r}from"node:fs";import{readFile as i,stat as a}from"node:fs/promises";import{dirname as o,isAbsolute as s,normalize as c,relative as l,resolve as u,sep as d}from"node:path";import f from"node:process";import p from"@teacss/directives";import{applyTransformerPipeline as m,createContext as h,defaultFilesystemGlobs as g}from"@teacss/runtime";import{DEFAULT_SOURCE_IGNORE as _,generateSources as v,readSourceFile as y}from"@teacss/runtime/source-generation";import{glob as b,isDynamicPattern as x}from"tinyglobby";function S(e,t){let n=l(e,t);return n===``||n!==`..`&&!n.startsWith(`..${d}`)&&!s(n)}function C(e){let t=Array.from(new Set(Array.from(e,c))).sort((e,t)=>e.length-t.length||e.localeCompare(t)),n=[];for(let e of t)n.some(t=>S(t,e))||n.push(e);return n}function ee(e,t){let n=t;for(;x(n);){let e=o(n);if(e===n)break;n=e}return u(e,n)}var te=class{createWatcher;onChange;onError;#e=!1;#t=new Map;constructor(e,t,n){this.createWatcher=e,this.onChange=t,this.onError=n}get roots(){return[...this.#t.keys()]}covers(e){for(let t of this.#t.keys())if(S(t,e))return!0;return!1}reconcile(e){if(this.#e)return;let t=C(e),n=new Set(t),r=new Map;try{for(let e of t){if(this.#t.has(e))continue;let t;try{t=this.createWatcher(e,(t,n)=>{this.onChange(n==null?void 0:u(e,n.toString()))});let n=t;t.on(`error`,t=>{this.#t.get(e)===n&&(this.#t.delete(e),this.closeWatcher(n)),this.onError(t)}),r.set(e,t)}catch(e){throw t&&this.closeWatcher(t),e}}}catch(e){for(let e of r.values())this.closeWatcher(e);throw e}if(this.#e){for(let e of r.values())this.closeWatcher(e);return}let i=new Map;for(let e of t){let t=this.#t.get(e)??r.get(e);t&&i.set(e,t)}let a=this.#t;this.#t=i;for(let[e,t]of a)n.has(e)||this.closeWatcher(t)}dispose(){if(this.#e)return;this.#e=!0;let e=this.#t;this.#t=new Map;for(let t of e.values())this.closeWatcher(t)}closeWatcher(e){try{e.close()}catch(e){this.onError(e)}}};function ne(e,t,n=Bun.version){let r={...e};return delete r.metafile,Bun.semver.satisfies(n,`>=1.3.6`)&&(r.metafile=!0),{...r,plugins:t}}const w=/^(?:virtual:)?teacss\.css$/,T=/\.css$/,E=`teacss`;function D(e,t={}){return{name:`teacss`,async setup(n){let r=h(e,{...t,transformers:[...t.transformers??[],p()]}),a=n.config.root??f.cwd();await r.updateRoot(a);let s=new Set,c=new Set,l=!0;function u(){let e=r.getConfigFileList()[0];return e?o(e):a}async function d(e){let t=e();s.add(t);try{return await t}finally{s.delete(t)}}n.onStart(async()=>{if(l){l=!1;return}await Promise.allSettled(s);for(let e of c)await r.extract(``,e);c.clear(),await r.reloadConfig()}),n.onResolve({filter:w},()=>({path:`teacss.css`,namespace:E})),n.onLoad({filter:/.*/,namespace:E},()=>d(async()=>{let e=await b((await r.getConfig()).content?.filesystem??g,{cwd:u(),absolute:!0,ignore:_}),t=e.map(y),{css:n}=await v(r.generator,e,t,{minify:!1});return{contents:n,loader:`css`}})),n.onLoad({filter:T},e=>d(async()=>{let t=await i(e.path,`utf8`);return c.add(e.path),{contents:(await m(r,t,e.path))?.code??t,loader:`css`}}))}}}function re(e){let r=e;for(n(r,{throwIfNoEntry:!1})?.isFile()&&(r=o(r));!t(r);){let e=o(r);if(e===r)break;r=e}return r}function ie(e){return`${e.mtimeMs}:${e.ctimeMs}:${e.size}:${e.ino}`}async function O(n,i={}){let c=u(n.root??f.cwd()),l=n.entrypoints.map(e=>s(e)?e:u(c,e)),{configOrPath:d,defaults:p={},debounce:m=50,onBuild:v,onError:y}=i,x=h(d,p),S=new Set,C=!1,w=!1,T,E,O=!1,k,A=!1,j=!1,M=0,N=!1,P=``,F=new Set,I,L,R=0,z=new Set,B=new e;function V(){let e=x.getConfigFileList()[0];return e?o(e):c}async function H(){return await b(x.generator.config.content?.filesystem??g,{cwd:V(),absolute:!0,ignore:_})}function ae(e){let t=e.content?.filesystem;if(!t)return e;let n=V();return{...e,content:{...e.content,filesystem:t.map(e=>e.startsWith(`!`)?`!${u(n,e.slice(1))}`:u(n,e))}}}function U(e,t,n){if(!t)return Promise.resolve();let r={active:!0},i;return i=B.run(r,()=>Promise.resolve().then(()=>t(n)).catch(t=>console.error(`[@teacss/bun] watch ${e} callback failed:`,t)).finally(()=>{r.active=!1,z.delete(i)})),z.add(i),i}async function oe(){for(;z.size>0;)await Promise.all(z)}function W(e){return w?Promise.resolve():(I=e,U(`error`,y,e))}function se(e,t=S){let n=new Set([...x.getConfigFileList(),...l,...t,...e]);if(typeof d!=`object`){let e=typeof d==`string`?u(c,d):c;n.add(e)}let r=V();for(let e of x.generator.config.content?.filesystem??g)e.startsWith(`!`)||n.add(ee(r,e));return n}function G(e,t=S){return new Set([...x.getConfigFileList(),...l,...t,...e])}async function K(e){let t=new Set(e.flatMap(e=>[...e])),n=new Map(await Promise.all([...t].map(async e=>{try{return[e,`${e}:${ie(await a(e))}`]}catch(t){if(t.code===`ENOENT`)return[e,`${e}:missing`];throw t}})));return e.map(e=>[...e].sort().map(e=>n.get(e)).join(`|`))}async function ce(e,t=S){return(await K([G(e,t)]))[0]}let q=new te((e,t)=>r(e,{recursive:!0},t),e=>{if(e!==void 0&&F.has(e)&&M++,!A){j=!0;return}$()},e=>{W(e),A?$():j=!0});function J(e,t=S){return F=G(e,t),q.reconcile(Array.from(se(e,t),re))}function Y(e,t,n){return AggregateError([e,t],n)}function X(e,n){return new Set(Object.keys(e.metafile?.inputs??{}).map(e=>s(e)?e:u(c,e)).filter(e=>!n||t(e)))}async function Z(e,t=S){if(w)return;let n=e,r=[];try{r=await H()}catch(e){n=Y(n,e,`TeaCSS build and source discovery failed`)}if(!w){try{J(r,t)}catch(e){n=Y(n,e,`TeaCSS build and watcher reconciliation failed`)}await W(n)}}async function le(){if(w)return;let e=M;if(C?await x.reloadConfig():(C=!0,await x.updateRoot(c)),w)return;let t=await H();if(w||(J(t),w))return;let r=await ce(t);if(w)return;let i=N;if(N=!1,!i&&R>0&&I===void 0&&r===P)return;let a=ae(await x.getConfig());if(w)return;let o=[...(n.plugins??[]).filter(e=>e.name!==`teacss`),D(a)],s=await Bun.build(ne(n,o));if(w)return;if(!s.success){await Z(s,new Set([...S,...X(s,!1)]));return}let l=X(s,!0),u=await H();if(w)return;let d=[...l].some(e=>!q.covers(e));if(J(u,l),w)return;let[f,p]=await K([G(u),G(u,l)]);if(w)return;let m=d||f!==r||M!==e;L=s,I=void 0,R++,S=l,P=p,await U(`build`,v,s),m&&(N=!0,A?O=!0:j=!0)}async function Q(){try{await le()}catch(e){await Z(e)}}async function ue(){do O=!1,await Q();while(O&&!w)}function $(){w||(E&&clearTimeout(E),E=setTimeout(()=>{E=void 0,O=!0,k||=ue().finally(()=>{k=void 0,O&&!w&&$()})},m))}function de(){w=!0,E&&clearTimeout(E),E=void 0,q.dispose()}return await Q(),A=!0,j&&$(),{get error(){return I},get result(){return L},get version(){return R},dispose(){return B.getStore()?.active?(de(),Promise.resolve()):(T??=(async()=>{de(),await k,await oe()})(),T)}}}export{D as pluginTeacss,O as watchTeacssBuild};
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@teacss/bun",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Bun plugin for TeaCSS — generate utilities and inline @apply via Bun.build.",
|
|
5
|
+
"homepage": "https://css.teasim.com",
|
|
6
|
+
"funding": "https://github.com/sponsors/billgo",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "Billgo <hi@billgo.me>",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"type": "module",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./dist/index.js",
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "bunx tsdown --config tsdown.config.mts",
|
|
22
|
+
"dev": "tsdown --watch"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@teacss/core": "0.3.0",
|
|
26
|
+
"@teacss/directives": "0.3.0",
|
|
27
|
+
"@teacss/runtime": "0.3.0",
|
|
28
|
+
"tinyglobby": "^0.2.17"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@teacss/preset-standard": "0.3.0",
|
|
32
|
+
"bun-types": "^1.3.14"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"bun": ">=1.1.0",
|
|
36
|
+
"node": ">=22.12.0"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
}
|
|
41
|
+
}
|