typebulb 0.9.1 → 0.9.3
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/README.md +7 -2
- package/dist/index.js +197 -176
- package/dist/render.d.ts +13 -2
- package/dist/render.js +90 -37
- package/dist/servers.d.ts +65 -0
- package/dist/servers.js +1 -0
- package/package.json +7 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export interface BulbServer {
|
|
2
|
+
/** OS process id of the dev server. */
|
|
3
|
+
pid: number
|
|
4
|
+
/** Bound loopback port. */
|
|
5
|
+
port: number
|
|
6
|
+
/** http://localhost:<port>. */
|
|
7
|
+
url: string
|
|
8
|
+
/** Absolute path to the .bulb.md being served. */
|
|
9
|
+
file: string
|
|
10
|
+
/** Epoch ms the server began listening. */
|
|
11
|
+
startedAt: number
|
|
12
|
+
/** Launched with --trust (filesystem / AI / server.ts enabled)? */
|
|
13
|
+
trust?: boolean
|
|
14
|
+
/** Human label of a privileged capability this untrusted server denied (set by the gate). */
|
|
15
|
+
denied?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Launch (or re-attach to) a standalone `typebulb` dev server for `file`. Idempotent
|
|
19
|
+
* per file: a live server already serving it is returned, not re-spawned. Always silent
|
|
20
|
+
* (no console window); detached so it outlives the caller. `trust` passes --trust. */
|
|
21
|
+
export declare function launchBulbServer(file: string, opts?: { cwd?: string; open?: boolean; trust?: boolean }): Promise<BulbServer>
|
|
22
|
+
|
|
23
|
+
/** Every live dev server, oldest first. Dead entries are pruned on read. */
|
|
24
|
+
export declare function listBulbServers(): Promise<BulbServer[]>
|
|
25
|
+
|
|
26
|
+
/** Stop a server by pid (SIGTERM + deregister). Idempotent. */
|
|
27
|
+
export declare function stopBulbServer(pid: number): Promise<void>
|
|
28
|
+
|
|
29
|
+
/** New console bytes of a server (its `<pid>.log`) since `offset`; returns the text and
|
|
30
|
+
* the new offset. A trim past the cap resyncs from 0. Absent file ⇒ empty. */
|
|
31
|
+
export declare function readServerLog(pid: number, offset?: number): { text: string; offset: number }
|
|
32
|
+
|
|
33
|
+
/** Absolute path of a server's console log, sibling of its registry entry. */
|
|
34
|
+
export declare function serverLogPath(pid: number): string
|
|
35
|
+
|
|
36
|
+
export interface BulbFileInfo {
|
|
37
|
+
/** Absolute path to the .bulb.md. */
|
|
38
|
+
path: string
|
|
39
|
+
/** The bulb's `name:` frontmatter title, or the filename stem when unnamed. */
|
|
40
|
+
name: string
|
|
41
|
+
/** File mtime (epoch ms); 0 if it vanished mid-walk. */
|
|
42
|
+
mtime: number
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Every `*.bulb.md` under `cwd` (dot-dirs and node_modules skipped, depth-bounded),
|
|
46
|
+
* each with its frontmatter name (or filename stem) and mtime. */
|
|
47
|
+
export declare function listBulbFiles(cwd: string): BulbFileInfo[]
|
|
48
|
+
|
|
49
|
+
/** The bulb's `name:` from its leading frontmatter, or undefined if absent. */
|
|
50
|
+
export declare function bulbName(source: string): string | undefined
|
|
51
|
+
|
|
52
|
+
/** A filesystem-safe slug from the bulb's name; 'bulb' when unnamed. */
|
|
53
|
+
export declare function slugifyBulbName(source: string): string
|
|
54
|
+
|
|
55
|
+
/** The source with its leading `---` frontmatter block stripped. */
|
|
56
|
+
export declare function stripFrontmatter(source: string): string
|
|
57
|
+
|
|
58
|
+
/** Is this bulb remembered as Trusted in the CLI's per-machine trust store? */
|
|
59
|
+
export declare function isBulbTrusted(file: string): boolean
|
|
60
|
+
|
|
61
|
+
/** Set or clear a bulb's remembered trust (written only by user/agent action, never bulb code). */
|
|
62
|
+
export declare function setBulbTrusted(file: string, trust: boolean): void
|
|
63
|
+
|
|
64
|
+
/** Every remembered-trusted bulb path (absolute, normalized). */
|
|
65
|
+
export declare function listTrustedBulbs(): string[]
|
package/dist/servers.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{spawn as y}from"child_process";import{readdir as F,readFile as E,writeFile as tr,unlink as a,mkdir as nr}from"fs/promises";import{mkdirSync as sr,writeFileSync as or,appendFileSync as ar,readFileSync as L}from"fs";import*as s from"path";import{join as f,resolve as x}from"path";import{homedir as P}from"os";function c(){let r=process.env.TYPEBULB_SERVERS_DIR;return r?f(r,".."):f(P(),".typebulb")}function o(){return process.env.TYPEBULB_SERVERS_DIR||f(c(),"servers")}function m(r){let e=x(r);return(process.platform==="win32"?e.toLowerCase():e).replace(/\\/g,"/")}function N(r){return s.join(o(),`${r}.json`)}function l(r){return s.join(o(),`${r}.log`)}function T(r,e=0){try{let t=L(l(r)),n=e>=0&&e<=t.length?e:0;return{text:t.subarray(n).toString("utf8"),offset:t.length}}catch{return{text:"",offset:0}}}function D(r){try{return process.kill(r,0),!0}catch(e){return e.code==="EPERM"}}async function j(r){await a(N(r)).catch(()=>{}),await a(l(r)).catch(()=>{})}async function d(){let r;try{r=await F(o())}catch{return[]}let e=[];return await Promise.all(r.map(async t=>{if(!t.endsWith(".json"))return;let n=s.join(o(),t),i;try{i=JSON.parse(await E(n,"utf8"))}catch{await a(n).catch(()=>{});return}i&&typeof i.pid=="number"&&D(i.pid)?e.push(i):(await a(n).catch(()=>{}),i?.pid&&await a(l(i.pid)).catch(()=>{}))})),e.sort((t,n)=>t.startedAt-n.startedAt)}async function _(r){try{process.kill(r,"SIGTERM")}catch{}await j(r)}var A=r=>new Promise(e=>setTimeout(e,r));async function O(r,e={}){let t=e.cwd??process.cwd(),n=s.resolve(t,r),i=(await d()).find(u=>u.file===n);if(i)return i;let g=["typebulb",...e.trust?["--trust"]:[],r,...e.open===!1?["--no-open"]:[]];(process.platform==="win32"?y("cmd",["/c","start","","/b","npx",...g],{cwd:t,stdio:"ignore",windowsHide:!0}):y("npx",g,{cwd:t,detached:!0,stdio:"ignore"})).unref();let h=Date.now()+2e4;for(;Date.now()<h;){await A(150);let u=(await d()).find(B=>B.file===n);if(u)return u}throw new Error(`Launched ${s.basename(r)} but it did not register within 20s.`)}import{readdirSync as $,readFileSync as k,statSync as I}from"fs";import{join as w,basename as M}from"path";function p(r){let e=/^---[^\n]*\n([\s\S]*?)\n---/.exec(r),t=e?/^\s*name:\s*(.+?)\s*$/m.exec(e[1]):null;return t?t[1].replace(/^["']|["']$/g,""):void 0}function R(r){return(p(r)??"bulb").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"bulb"}function J(r){return r.replace(/^---[^\n]*\r?\n[\s\S]*?\r?\n---[^\n]*\r?\n?/,"").replace(/^\r?\n+/,"")}function S(r,e,t){if(e>8)return t;let n;try{n=$(r,{withFileTypes:!0})}catch{return t}for(let i of n)if(i.isDirectory()){if(i.name.startsWith(".")||i.name==="node_modules")continue;S(w(r,i.name),e+1,t)}else i.isFile()&&i.name.endsWith(".bulb.md")&&t.push(w(r,i.name));return t}function z(r){return S(r,0,[]).map(e=>{let t=0;try{t=I(e).mtimeMs}catch{}let n;try{n=p(k(e,"utf8").slice(0,1024))}catch{}return{path:e,name:n??M(e).replace(/\.bulb\.md$/,""),mtime:t}})}import{readFileSync as C,writeFileSync as H,mkdirSync as U}from"fs";import{join as W}from"path";function v(){return W(c(),"trust.json")}function b(){try{let r=JSON.parse(C(v(),"utf8"));return new Set(Array.isArray(r)?r:[])}catch{return new Set}}function G(r){U(c(),{recursive:!0}),H(v(),JSON.stringify([...r]))}function V(r){return b().has(m(r))}function Y(r,e){let t=b(),n=m(r);(e?t.has(n):!t.has(n))||(e?t.add(n):t.delete(n),G(t))}function q(){return[...b()]}export{p as bulbName,V as isBulbTrusted,O as launchBulbServer,z as listBulbFiles,d as listBulbServers,q as listTrustedBulbs,T as readServerLog,l as serverLogPath,Y as setBulbTrusted,R as slugifyBulbName,_ as stopBulbServer,J as stripFrontmatter};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typebulb",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.3",
|
|
4
4
|
"description": "Local bulb runner CLI for Typebulb",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": { "node": ">=18" },
|
|
@@ -14,6 +14,12 @@
|
|
|
14
14
|
"browser": "./dist/render.js",
|
|
15
15
|
"import": "./dist/render.js",
|
|
16
16
|
"default": "./dist/render.js"
|
|
17
|
+
},
|
|
18
|
+
"./servers": {
|
|
19
|
+
"types": "./dist/servers.d.ts",
|
|
20
|
+
"node": "./dist/servers.js",
|
|
21
|
+
"import": "./dist/servers.js",
|
|
22
|
+
"default": "./dist/servers.js"
|
|
17
23
|
}
|
|
18
24
|
},
|
|
19
25
|
"files": [
|