typebulb 0.1.5 → 0.1.7
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 +1 -1
- package/dist/index.js +14 -16
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ typebulb --server <file> Run server.ts only, no web server
|
|
|
31
31
|
|
|
32
32
|
- **Hot reload** — `--watch` recompiles on save and refreshes the browser
|
|
33
33
|
- **Filesystem access** — `tb.fs.read()` and `tb.fs.write()` for local files
|
|
34
|
-
- **Server-side code** — Add a `**server.ts**` section; exported functions become callable from the browser via `tb.server.
|
|
34
|
+
- **Server-side code** — Add a `**server.ts**` section; exported functions become callable from the browser via `tb.server.<name>()` (e.g., `export async function query(...)` → `await tb.server.query(...)`)
|
|
35
35
|
- **Console bulbs** — Bulbs with only `**server.ts**` (no `**code.tsx**`) run directly in Node and print to stdout. Use `--server` to force this mode for any bulb.
|
|
36
36
|
- **Auto-installs packages** — npm dependencies in server code are installed automatically
|
|
37
37
|
- **Env files** — `.env` and `.env.local` auto-loaded from cwd
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import*as
|
|
3
|
-
`),t=0;if(e[t]?.trim()!=="---")return null;t++;let r=[];for(;t<e.length&&e[t]?.trim()!=="---";)r.push(e[t]),t++;if(e[t]?.trim()!=="---")return null;t++;let n=
|
|
4
|
-
`))}else t++}return{frontmatter:n,files:o}}catch{return null}}function be(s){let e={};for(let t of s){let r=t.indexOf(":");if(r===-1)continue;let n=t.slice(0,r).trim(),o=t.slice(r+1).trim();switch(n){case"format":e.format=o;break;case"name":e.name=ye(o);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function ye(s){return s.startsWith('"')&&s.endsWith('"')?s.slice(1,-1).replace(/\\"/g,'"'):s.startsWith("'")&&s.endsWith("'")?s.slice(1,-1):s}function C(s){let e=t=>s.files.get(ve[t].path)||"";return{name:s.frontmatter.name,code:e("code"),css:e("css"),html:e("html"),config:e("config"),notes:e("notes"),data:e("data"),infer:e("infer"),insight:e("insight"),server:e("server")}}function xe(s){try{return JSON.parse(s),!0}catch{}return!!(/^\s*<[\s\S]*>/.test(s)||/^---\s*$/m.test(s)||/^\w[\w\s]*:[ \t]/m.test(s))}function H(s){let e=s.trim();return e?xe(e)?[e]:s.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function F(s){if(!s.trim())return{};try{return JSON.parse(s)}catch{return{}}}import{transform as q}from"sucrase";import*as g from"typescript";var Se=[/\bconst\s+enum\b/,/\bexport\s*=/,/\bimport\s+\w+\s*=/,/\bnamespace\s+\w+/,/\bmodule\s+\w+\s*\{/],Ee={target:g.ScriptTarget.ES2022,module:g.ModuleKind.ESNext,moduleResolution:g.ModuleResolutionKind.NodeNext,jsx:g.JsxEmit.ReactJSX,isolatedModules:!0,verbatimModuleSyntax:!0,inlineSourceMap:!0,inlineSources:!0,importHelpers:!1,skipLibCheck:!0};function z(s){return Se.some(e=>e.test(s))}function Pe(s,e){try{let{code:t}=q(s,{transforms:["typescript","jsx"],jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:t}}catch(t){return{code:"",error:String(t)}}}function K(s,e){try{let t=g.transpileModule(s,{compilerOptions:{...Ee,jsxImportSource:e.jsxImportSource||void 0},fileName:"code.tsx",reportDiagnostics:!0});if(t.diagnostics&&t.diagnostics.length>0){let r=t.diagnostics.filter(n=>n.category===g.DiagnosticCategory.Error).map(n=>g.flattenDiagnosticMessageText(n.messageText,`
|
|
5
|
-
`)).join(`
|
|
6
|
-
`);if(r)return{code:t.outputText||"",error:r}}return{code:t.outputText||""}}catch(t){return{code:"",error:String(t)}}}function G(s,e={}){return z(s)?K(s,e):Pe(s,e)}function Y(s){if(z(s))return K(s,{});try{let{code:e}=q(s,{transforms:["typescript"]});return{code:e}}catch(e){return{code:"",error:String(e)}}}var R="https://esm.sh",I="https://cdn.jsdelivr.net/npm/",O="https://data.jsdelivr.com/v1/package/npm/";function Z(s){let e=(s||"").replace(/^\/+/,"").replace(/\/+$/,"");return e?e.split("/"):[]}var f=class s{constructor(e,t,r){let n=typeof e=="string"?s.parse(e):e;this.name=n.name,this.version=S(t??n.version),this.subpath=S(r??n.subpath)}static parse(e){let t=Z(e||"");if(!t.length)return new s({name:""});if(t[0].startsWith("@")){let n=t[0],[o,i]=X(t[1]??""),c=S(t.slice(2).join("/"));return new s({name:`${n}/${o}`,version:i,subpath:c})}else{let[n,o]=X(t[0]),i=S(t.slice(1).join("/"));return new s({name:n,version:o,subpath:i})}}static fromUrl(e){try{let t=new URL(e),r=new URL(R).host,n=new URL(I).host;if(t.host===r){let o=Z(t.pathname.replace(/^\/v\d+\//,"/"));if(!o.length)return;let i=o[0].startsWith("@")?`${o[0]}/${o[1]??""}`:o[0];return s.parse(i)}if(t.host===n){let o=t.pathname.split("/npm/")[1];if(!o)return;let i=o.split("/")[0]||"";return s.parse(i)}return}catch{return}}static versionFromUrl(e){return s.fromUrl(e)?.version}format(){let e=this.version?`${this.name}@${this.version}`:this.name;return this.subpath?`${e}/${this.subpath}`:e}root(){return this.name}static rootOf(e){return s.parse(e).name}withVersion(e){return new s({name:this.name,version:S(e),subpath:this.subpath})}withPreferredVersion(e,t){let r=e||t;return r?this.withVersion(r):this}static isBare(e){if(!e||e.startsWith(".")||e.startsWith("/"))return!1;let t=e.toLowerCase();return!t.startsWith("http://")&&!t.startsWith("https://")}},S=s=>s&&s.length?s:void 0,X=s=>{let e=s.indexOf("@");return e<0?[s,void 0]:[s.slice(0,e),S(s.slice(e+1))]};async function w(s){try{return await s()}catch{return}}var j=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=R,this.jsDelivrBase=I,this.jsDelivrMeta=O,this.pinMs=1e4,this.versionsIndexMs=1440*60*1e3,this.metaTtlMs=10080*60*1e3,this.pinCache=new Map}normalizeRelative(e){let t=e||"";return t.startsWith("./")?t.slice(2):t.replace(/^\/+/,"")}ensureLeadingDotSlash(e){return e.startsWith("./")?e:`./${e}`}baseDir(e){let t=typeof e=="string"?new f(e):e;return`${this.jsDelivrBase}${t.name}${t.version?`@${t.version}`:""}/`}file(e,t){return new URL(this.normalizeRelative(t),this.baseDir(e)).toString()}packageJson(e){return this.file(e,"package.json")}buildEsmUrl(e,t={}){let{target:r="es2022",bundle:n=!1,external:o}=t,i=new URLSearchParams({target:r});return n&&i.append("bundle",""),o?.length&&i.append("external",o.join(",")),`${this.esmHost}/${e}?${i.toString()}`}async pinEsmUrl(e,t="es2022"){let r=this.buildEsmUrl(e,{target:t}),n=await w(()=>this.http.head(r));return n?.ok?n.url||r:void 0}async resolveExactVersion(e){let t=Date.now(),r=this.pinCache.get(e);if(r&&t-r.ts<this.pinMs)return r.value;let n=await this.tryResolveFromUrls([this.buildEsmUrl(e),`${this.esmHost}/${e}`]);return this.pinCache.set(e,{value:n,ts:t}),n}async tryResolveFromUrls(e){for(let t of e){let r=await w(()=>this.http.head(t)),n=this.parseVersionFromUrl(r?.url||t);if(n)return n}}async fetchVersionsIndex(e){if(await this.cache.isNegative(e))return;let t=await this.cache.getIndex(e);if(t&&Date.now()-t.updatedAt<this.versionsIndexMs)return{versions:t.versions,distTags:t.distTags};let r=await w(()=>this.http.getJson(`${this.jsDelivrMeta}${encodeURIComponent(e)}`));if(!r?.versions?.length){await this.cache.recordNegative(e);return}await this.cache.clearNegative(e);let n=r.distTags&&Object.keys(r.distTags).length?r.distTags:void 0;return await this.cache.setIndex(e,r.versions,n),r}parseVersionFromUrl(e){let t=f.fromUrl(e)?.version;return t&&/\d+\.\d+\.\d+/.test(t)?t:void 0}async fetchPackageMeta(e,t){let r=await this.cache.getMeta(e,t);if(r&&Date.now()-r.updatedAt<this.metaTtlMs){let{dependencies:a,peerDependencies:u,peerDependenciesMeta:d}=r;return{name:e,version:t,dependencies:a,peerDependencies:u,peerDependenciesMeta:d}}let n=this.packageJson(new f(`${e}@${t}`)),o=await w(()=>this.http.getJson(n));if(!o)return;let i=a=>a&&Object.keys(a).length?a:void 0,c=i(o.dependencies),l=i(o.peerDependencies),p=i(o.peerDependenciesMeta);return await this.cache.setMeta(e,t,c,l,p),{name:e,version:t,dependencies:c,peerDependencies:l,peerDependenciesMeta:p}}};var Q=s=>s.startsWith("@types/"),$=s=>Object.keys(s?.peerDependencies||{}).filter(e=>!Q(e)),B=s=>Object.keys(s?.dependencies||{}).filter(e=>!Q(e)),Re=s=>$(s).filter(e=>!s?.peerDependenciesMeta?.[e]?.optional),M=class{constructor(e){this.cdn=e}async resolve(e,t){let r=await this.fetchMeta(e),{allRoots:n,autoAddedPeers:o}=await this.expandWithPeers(r,t),i=this.computeFlags(n);return{allRoots:n,flags:i,autoAddedPeers:o}}async fetchMeta(e){return Promise.all(e.map(async({name:t,version:r})=>({name:t,version:r,meta:await this.cdn.fetchPackageMeta(t,r)})))}async expandWithPeers(e,t){let r=new Map(e.map(o=>[o.name,o])),n=[];for(let o of e)for(let i of Re(o.meta))!r.has(i)&&!n.some(c=>c.name===i)&&n.push({name:i,requiredBy:o.name});for(let{name:o,requiredBy:i}of n)try{let c=await t(o),l=await this.cdn.fetchPackageMeta(o,c);r.set(o,{name:o,version:c,meta:l})}catch(c){console.warn(`[typebulb] Failed to resolve peer "${o}" for "${i}":`,c)}return{allRoots:[...r.values()],autoAddedPeers:n.filter(o=>r.has(o.name))}}computeFlags(e){let t=new Set(e.flatMap(o=>$(o.meta))),r=new Map;for(let o of e)for(let i of B(o.meta))r.set(i,(r.get(i)||0)+1);let n=new Set([...r.entries()].filter(([,o])=>o>=2).map(([o])=>o));return new Map(e.map(o=>[o.name,{isPeerRoot:t.has(o.name),hasPeers:$(o.meta).length>0,isSharedDep:n.has(o.name)}]))}};var T=class{constructor(e,t,r){this.cache=e,this.cdn=t,this.semver=r}selectVersionFromIndex(e,t,r){return this.semver.selectBestVersion(e,{range:t,distTags:r})}async learnExactVersion(e){let t=await w(()=>this.cdn.fetchVersionsIndex(e));if(t?.versions?.length){let r=this.semver.selectBestVersion(t.versions,{distTags:t.distTags});if(r)return r}return this.cdn.resolveExactVersion(e)}async resolveExactForRoot(e,t){if(!t)return this.learnExactVersion(e);let r=await this.cache.getPinnedExact(e,t);if(r){if(this.semver.isExactVersion(r))return r;console.warn("[versionResolver] Rejecting invalid cached version for",e,":",r)}let n=await w(()=>this.cdn.fetchVersionsIndex(e));if(n?.versions?.length){let i=this.selectVersionFromIndex(n.versions,t,n.distTags);if(i){if(this.semver.isExactVersion(i))return await this.cache.setPinnedExact(e,t,i),i}else{console.warn("[versionResolver] Invalidating stale versions cache for",e,"- range",t,"not satisfied"),await this.cache.invalidateVersionsCache(e);let c=await w(()=>this.cdn.fetchVersionsIndex(e));if(c?.versions?.length){let l=this.selectVersionFromIndex(c.versions,t,c.distTags);if(l&&this.semver.isExactVersion(l))return await this.cache.setPinnedExact(e,t,l),l}}}let o=await this.cdn.resolveExactVersion(`${e}@${t}`);if(o&&this.semver.isExactVersion(o))return await this.cache.setPinnedExact(e,t,o),o}async effectivePackage(e,t){let r=new f(e),n=r.root(),o=t[n],i=o?await w(()=>this.cache.getPinnedExact(n,o))??await w(()=>this.resolveExactForRoot(n,o)):void 0;return{effectivePackage:i?r.withVersion(i).format():e,root:n,range:o,pinned:i}}};import{init as Ie,parse as je}from"es-module-lexer";var E=class s{constructor(e,t,r,n){this.version=e,this.cdn=t,this.peer=r,this.cache=n}extractImportsSync(e){let t=new Set;for(let r of s.importPatterns){r.lastIndex=0;for(let n of e.matchAll(r))f.isBare(n[1])&&t.add(n[1])}return Array.from(t)}async extractImports(e){let t=new Set,r=n=>{f.isBare(n)&&t.add(n)};try{await Ie;let[n]=je(e);n.forEach(o=>r(e.slice(o.s,o.e).trim()))}catch{return this.extractImportsSync(e)}return Array.from(t)}async buildImportMap(e,t){let r=await this.extractImports(e),n=[...new Set(r.map(f.rootOf))],o=await Promise.all(n.map(async a=>({name:a,version:await this.resolveVersion(a,t)}))),{allRoots:i,flags:c,autoAddedPeers:l}=await this.peer.resolve(o,a=>this.resolveVersion(a,t)),p=this.buildEntries([...r,...l.map(a=>a.name)],i,c,t);return{importMap:{imports:Object.fromEntries(p)},prefetchUrls:p.map(([,a])=>a)}}async resolveVersion(e,t){let r=t[e],n=await this.version.resolveExactForRoot(e,r);if(!n){let o=r?`${e}@${r}`:e,i=await w(()=>this.cdn.pinEsmUrl(o));if(!i)throw new Error(`Cannot resolve version for ${e} - network may be unavailable.`);n=f.versionFromUrl(i),n&&r&&await w(()=>this.cache.setPinnedExact(e,r,n))}if(!n)throw new Error(`Cannot resolve version for ${e}`);return n}buildEntries(e,t,r,n){let o=new Map(t.map(d=>[d.name,d])),i=d=>{let v=o.get(f.rootOf(d));return new f(d).withPreferredVersion(v.version,n[v.name]).format()},c=new Set([...r.entries()].filter(([,d])=>d.isPeerRoot||d.isSharedDep).map(([d])=>d)),l=new Set(e.filter(d=>d!==f.rootOf(d)).map(f.rootOf)),p=[],a=new Set,u=new Set(e.filter(d=>d===f.rootOf(d)));for(let d of e){let v=f.rootOf(d),b=o.get(v),{isPeerRoot:x,hasPeers:ue,isSharedDep:fe}=r.get(v),me=l.has(v),he=d!==v,ge=!(x||fe)&&(me||!ue),k=this.singletonDepsOf(b,c),we=he&&u.has(v)?[...k,v]:k.length?k:void 0;p.push([d,this.cdn.buildEsmUrl(i(d),{bundle:ge,external:we})]),a.add(d)}for(let d of c)o.has(d)&&(a.has(d)||p.push([d,this.cdn.buildEsmUrl(i(d),{})]),p.push([`${d}/`,`${this.cdn.esmHost}/${i(d)}/`]));return p}singletonDepsOf(e,t){return[...new Set([...$(e.meta),...B(e.meta)])].filter(r=>t.has(r))}};E.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as ee,satisfies as $e,maxSatisfying as A,major as Me,prerelease as Te,rsort as _e,valid as Ce}from"semver";var D=class{cmp(e,t){return e===t?0:ee(e,t)?1:ee(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!$e(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let r=A(e,t,{includePrerelease:!0});return r===null?void 0:r}pickLatest(e){return e?.length?_e(e)[0]:void 0}selectBestVersion(e,t){if(!e?.length)return;let r=t?.range?.trim()||"*",n=t?.preferStable??!0,o=t?.distTags?.latest;if(o&&e.includes(o)&&this.satisfies(r,o))return o;if(n){let c=A(e,r,{includePrerelease:!1});if(c)return c}return A(e,r,{includePrerelease:!0})??void 0}majorOf(e){return Me(e)}isPrerelease(e){return Te(e)!==null}isExactVersion(e){return Ce(e)!==null}},V=new D;function te(s,e){let t=new j(s,e),r=new M(t),n=new T(s,t,V);return{packageService:new E(n,t,r,s),versionResolver:n,cdnClient:t,peerResolver:r}}var N=class{pins=new Map;indexes=new Map;negatives=new Set;meta=new Map;async getPinnedExact(e,t){return this.pins.get(`${e}@${t}`)}async setPinnedExact(e,t,r){this.pins.set(`${e}@${t}`,r)}async getIndex(e){return this.indexes.get(e)}async setIndex(e,t,r){this.indexes.set(e,{versions:t,distTags:r,updatedAt:Date.now()})}async invalidateVersionsCache(e){this.indexes.delete(e)}async isNegative(e){return this.negatives.has(e)}async recordNegative(e){this.negatives.add(e)}async clearNegative(e){this.negatives.delete(e)}async getMeta(e,t){return this.meta.get(`${e}@${t}`)}async setMeta(e,t,r,n,o){this.meta.set(`${e}@${t}`,{dependencies:r,peerDependencies:n,peerDependenciesMeta:o,updatedAt:Date.now()})}},De={async getJson(s){try{let e=await fetch(s,{redirect:"follow"});return e.ok?await e.json():void 0}catch{return}},async head(s){try{let e=await fetch(s,{method:"HEAD",redirect:"follow"});return{ok:e.ok,url:e.url}}catch{return}}},ke=new N,{packageService:re,versionResolver:At,cdnClient:Vt,peerResolver:Nt}=te(ke,De);var se=`
|
|
2
|
+
import*as m from"fs/promises";import{readFileSync as Be,existsSync as oe}from"fs";import*as h from"path";import{pathToFileURL as Oe}from"url";import{execFile as Ae}from"child_process";import{promisify as Ve}from"util";import{EventEmitter as U}from"events";var me={code:{path:"code.tsx",language:"typescript"},css:{path:"styles.css",language:"css"},html:{path:"index.html",language:"html"},config:{path:"config.json",language:"json"},notes:{path:"notes.md",language:"markdown"},data:{path:"data.txt",language:"text"},infer:{path:"infer.md",language:"markdown"},insight:{path:"insight.json",language:"json"},server:{path:"server.ts",language:"typescript"}};function _(s){try{let e=s.split(`
|
|
3
|
+
`),t=0;if(e[t]?.trim()!=="---")return null;t++;let r=[];for(;t<e.length&&e[t]?.trim()!=="---";)r.push(e[t]),t++;if(e[t]?.trim()!=="---")return null;t++;let n=ge(r);if(!n)return null;let o=new Map;for(;t<e.length;){let c=e[t]?.trim()?.match(/^\*\*(.+)\*\*$/);if(c){let l=c[1].trim();for(t++;t<e.length&&e[t]?.trim()==="";)t++;let p=e[t]?.match(/^(`{3,})(\w*)\s*$/);if(!p){t++;continue}let a=p[1];t++;let f=[];for(;t<e.length&&!e[t]?.match(new RegExp(`^${a}\\s*$`));)f.push(e[t]),t++;t++,o.set(l,f.join(`
|
|
4
|
+
`))}else t++}return{frontmatter:n,files:o}}catch{return null}}function ge(s){let e={};for(let t of s){let r=t.indexOf(":");if(r===-1)continue;let n=t.slice(0,r).trim(),o=t.slice(r+1).trim();switch(n){case"format":e.format=o;break;case"name":e.name=we(o);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function we(s){return s.startsWith('"')&&s.endsWith('"')?s.slice(1,-1).replace(/\\"/g,'"'):s.startsWith("'")&&s.endsWith("'")?s.slice(1,-1):s}function k(s){let e=t=>s.files.get(me[t].path)||"";return{name:s.frontmatter.name,code:e("code"),css:e("css"),html:e("html"),config:e("config"),notes:e("notes"),data:e("data"),infer:e("infer"),insight:e("insight"),server:e("server")}}function ve(s){try{return JSON.parse(s),!0}catch{}return!!(/^\s*<[\s\S]*>/.test(s)||/^---\s*$/m.test(s)||/^\w[\w\s]*:[ \t]/m.test(s))}function J(s){let e=s.trim();return e?ve(e)?[e]:s.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function T(s){if(!s.trim())return{};try{return JSON.parse(s)}catch{return{}}}import{transform as L}from"sucrase";function be(s,e){try{let{code:t}=L(s,{transforms:["typescript","jsx"],jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:t}}catch(t){return{code:"",error:String(t)}}}function q(s,e={}){return be(s,e)}function z(s){try{let{code:e}=L(s,{transforms:["typescript"]});return{code:e}}catch(e){return{code:"",error:String(e)}}}var P="https://esm.sh",R="https://cdn.jsdelivr.net/npm/",C="https://data.jsdelivr.com/v1/package/npm/";function G(s){let e=(s||"").replace(/^\/+/,"").replace(/\/+$/,"");return e?e.split("/"):[]}var u=class s{constructor(e,t,r){let n=typeof e=="string"?s.parse(e):e;this.name=n.name,this.version=x(t??n.version),this.subpath=x(r??n.subpath)}static parse(e){let t=G(e||"");if(!t.length)return new s({name:""});if(t[0].startsWith("@")){let n=t[0],[o,i]=K(t[1]??""),c=x(t.slice(2).join("/"));return new s({name:`${n}/${o}`,version:i,subpath:c})}else{let[n,o]=K(t[0]),i=x(t.slice(1).join("/"));return new s({name:n,version:o,subpath:i})}}static fromUrl(e){try{let t=new URL(e),r=new URL(P).host,n=new URL(R).host;if(t.host===r){let o=G(t.pathname.replace(/^\/v\d+\//,"/"));if(!o.length)return;let i=o[0].startsWith("@")?`${o[0]}/${o[1]??""}`:o[0];return s.parse(i)}if(t.host===n){let o=t.pathname.split("/npm/")[1];if(!o)return;let i=o.split("/")[0]||"";return s.parse(i)}return}catch{return}}static versionFromUrl(e){return s.fromUrl(e)?.version}format(){let e=this.version?`${this.name}@${this.version}`:this.name;return this.subpath?`${e}/${this.subpath}`:e}root(){return this.name}static rootOf(e){return s.parse(e).name}withVersion(e){return new s({name:this.name,version:x(e),subpath:this.subpath})}withPreferredVersion(e,t){let r=e||t;return r?this.withVersion(r):this}static isBare(e){if(!e||e.startsWith(".")||e.startsWith("/"))return!1;let t=e.toLowerCase();return!t.startsWith("http://")&&!t.startsWith("https://")}},x=s=>s&&s.length?s:void 0,K=s=>{let e=s.indexOf("@");return e<0?[s,void 0]:[s.slice(0,e),x(s.slice(e+1))]};async function g(s){try{return await s()}catch{return}}var I=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=P,this.jsDelivrBase=R,this.jsDelivrMeta=C,this.pinMs=1e4,this.versionsIndexMs=1440*60*1e3,this.metaTtlMs=10080*60*1e3,this.pinCache=new Map}normalizeRelative(e){let t=e||"";return t.startsWith("./")?t.slice(2):t.replace(/^\/+/,"")}ensureLeadingDotSlash(e){return e.startsWith("./")?e:`./${e}`}baseDir(e){let t=typeof e=="string"?new u(e):e;return`${this.jsDelivrBase}${t.name}${t.version?`@${t.version}`:""}/`}file(e,t){return new URL(this.normalizeRelative(t),this.baseDir(e)).toString()}packageJson(e){return this.file(e,"package.json")}buildEsmUrl(e,t={}){let{target:r="es2022",bundle:n=!1,external:o}=t,i=new URLSearchParams({target:r});return n&&i.append("bundle",""),o?.length&&i.append("external",o.join(",")),`${this.esmHost}/${e}?${i.toString()}`}async pinEsmUrl(e,t="es2022"){let r=this.buildEsmUrl(e,{target:t}),n=await g(()=>this.http.head(r));return n?.ok?n.url||r:void 0}async resolveExactVersion(e){let t=Date.now(),r=this.pinCache.get(e);if(r&&t-r.ts<this.pinMs)return r.value;let n=await this.tryResolveFromUrls([this.buildEsmUrl(e),`${this.esmHost}/${e}`]);return this.pinCache.set(e,{value:n,ts:t}),n}async tryResolveFromUrls(e){for(let t of e){let r=await g(()=>this.http.head(t)),n=this.parseVersionFromUrl(r?.url||t);if(n)return n}}async fetchVersionsIndex(e){if(await this.cache.isNegative(e))return;let t=await this.cache.getIndex(e);if(t&&Date.now()-t.updatedAt<this.versionsIndexMs)return{versions:t.versions,distTags:t.distTags};let r=await g(()=>this.http.getJson(`${this.jsDelivrMeta}${encodeURIComponent(e)}`));if(!r?.versions?.length){await this.cache.recordNegative(e);return}await this.cache.clearNegative(e);let n=r.distTags&&Object.keys(r.distTags).length?r.distTags:void 0;return await this.cache.setIndex(e,r.versions,n),r}parseVersionFromUrl(e){let t=u.fromUrl(e)?.version;return t&&/\d+\.\d+\.\d+/.test(t)?t:void 0}async fetchPackageMeta(e,t){let r=await this.cache.getMeta(e,t);if(r&&Date.now()-r.updatedAt<this.metaTtlMs){let{dependencies:a,peerDependencies:f,peerDependenciesMeta:d}=r;return{name:e,version:t,dependencies:a,peerDependencies:f,peerDependenciesMeta:d}}let n=this.packageJson(new u(`${e}@${t}`)),o=await g(()=>this.http.getJson(n));if(!o)return;let i=a=>a&&Object.keys(a).length?a:void 0,c=i(o.dependencies),l=i(o.peerDependencies),p=i(o.peerDependenciesMeta);return await this.cache.setMeta(e,t,c,l,p),{name:e,version:t,dependencies:c,peerDependencies:l,peerDependenciesMeta:p}}};var Y=s=>s.startsWith("@types/"),$=s=>Object.keys(s?.peerDependencies||{}).filter(e=>!Y(e)),B=s=>Object.keys(s?.dependencies||{}).filter(e=>!Y(e)),ye=s=>$(s).filter(e=>!s?.peerDependenciesMeta?.[e]?.optional),j=class{constructor(e){this.cdn=e}async resolve(e,t){let r=await this.fetchMeta(e),{allRoots:n,autoAddedPeers:o}=await this.expandWithPeers(r,t),i=this.computeFlags(n);return{allRoots:n,flags:i,autoAddedPeers:o}}async fetchMeta(e){return Promise.all(e.map(async({name:t,version:r})=>({name:t,version:r,meta:await this.cdn.fetchPackageMeta(t,r)})))}async expandWithPeers(e,t){let r=new Map(e.map(o=>[o.name,o])),n=[];for(let o of e)for(let i of ye(o.meta))!r.has(i)&&!n.some(c=>c.name===i)&&n.push({name:i,requiredBy:o.name});for(let{name:o,requiredBy:i}of n)try{let c=await t(o),l=await this.cdn.fetchPackageMeta(o,c);r.set(o,{name:o,version:c,meta:l})}catch(c){console.warn(`[typebulb] Failed to resolve peer "${o}" for "${i}":`,c)}return{allRoots:[...r.values()],autoAddedPeers:n.filter(o=>r.has(o.name))}}computeFlags(e){let t=new Set(e.flatMap(o=>$(o.meta))),r=new Map;for(let o of e)for(let i of B(o.meta))r.set(i,(r.get(i)||0)+1);let n=new Set([...r.entries()].filter(([,o])=>o>=2).map(([o])=>o));return new Map(e.map(o=>[o.name,{isPeerRoot:t.has(o.name),hasPeers:$(o.meta).length>0,isSharedDep:n.has(o.name)}]))}};var M=class{constructor(e,t,r){this.cache=e,this.cdn=t,this.semver=r}selectVersionFromIndex(e,t,r){return this.semver.selectBestVersion(e,{range:t,distTags:r})}async learnExactVersion(e){let t=await g(()=>this.cdn.fetchVersionsIndex(e));if(t?.versions?.length){let r=this.semver.selectBestVersion(t.versions,{distTags:t.distTags});if(r)return r}return this.cdn.resolveExactVersion(e)}async resolveExactForRoot(e,t){if(!t)return this.learnExactVersion(e);let r=await this.cache.getPinnedExact(e,t);if(r){if(this.semver.isExactVersion(r))return r;console.warn("[versionResolver] Rejecting invalid cached version for",e,":",r)}let n=await g(()=>this.cdn.fetchVersionsIndex(e));if(n?.versions?.length){let i=this.selectVersionFromIndex(n.versions,t,n.distTags);if(i){if(this.semver.isExactVersion(i))return await this.cache.setPinnedExact(e,t,i),i}else{console.warn("[versionResolver] Invalidating stale versions cache for",e,"- range",t,"not satisfied"),await this.cache.invalidateVersionsCache(e);let c=await g(()=>this.cdn.fetchVersionsIndex(e));if(c?.versions?.length){let l=this.selectVersionFromIndex(c.versions,t,c.distTags);if(l&&this.semver.isExactVersion(l))return await this.cache.setPinnedExact(e,t,l),l}}}let o=await this.cdn.resolveExactVersion(`${e}@${t}`);if(o&&this.semver.isExactVersion(o))return await this.cache.setPinnedExact(e,t,o),o}async effectivePackage(e,t){let r=new u(e),n=r.root(),o=t[n],i=o?await g(()=>this.cache.getPinnedExact(n,o))??await g(()=>this.resolveExactForRoot(n,o)):void 0;return{effectivePackage:i?r.withVersion(i).format():e,root:n,range:o,pinned:i}}};import{init as xe,parse as Se}from"es-module-lexer";var S=class s{constructor(e,t,r,n){this.version=e,this.cdn=t,this.peer=r,this.cache=n}extractImportsSync(e){let t=new Set;for(let r of s.importPatterns){r.lastIndex=0;for(let n of e.matchAll(r))u.isBare(n[1])&&t.add(n[1])}return Array.from(t)}async extractImports(e){let t=new Set,r=n=>{u.isBare(n)&&t.add(n)};try{await xe;let[n]=Se(e);n.forEach(o=>r(e.slice(o.s,o.e).trim()))}catch{return this.extractImportsSync(e)}return Array.from(t)}async buildImportMap(e,t){let r=await this.extractImports(e),n=[...new Set(r.map(u.rootOf))],o=await Promise.all(n.map(async a=>({name:a,version:await this.resolveVersion(a,t)}))),{allRoots:i,flags:c,autoAddedPeers:l}=await this.peer.resolve(o,a=>this.resolveVersion(a,t)),p=this.buildEntries([...r,...l.map(a=>a.name)],i,c,t);return{importMap:{imports:Object.fromEntries(p)},prefetchUrls:p.map(([,a])=>a)}}async resolveVersion(e,t){let r=t[e],n=await this.version.resolveExactForRoot(e,r);if(!n){let o=r?`${e}@${r}`:e,i=await g(()=>this.cdn.pinEsmUrl(o));if(!i)throw new Error(`Cannot resolve version for ${e} - network may be unavailable.`);n=u.versionFromUrl(i),n&&r&&await g(()=>this.cache.setPinnedExact(e,r,n))}if(!n)throw new Error(`Cannot resolve version for ${e}`);return n}buildEntries(e,t,r,n){let o=new Map(t.map(d=>[d.name,d])),i=d=>{let w=o.get(u.rootOf(d));return new u(d).withPreferredVersion(w.version,n[w.name]).format()},c=new Set([...r.entries()].filter(([,d])=>d.isPeerRoot||d.isSharedDep).map(([d])=>d)),l=new Set(e.filter(d=>d!==u.rootOf(d)).map(u.rootOf)),p=[],a=new Set,f=new Set(e.filter(d=>d===u.rootOf(d)));for(let d of e){let w=u.rootOf(d),v=o.get(w),{isPeerRoot:y,hasPeers:le,isSharedDep:pe}=r.get(w),de=l.has(w),fe=d!==w,ue=!(y||pe)&&(de||!le),F=this.singletonDepsOf(v,c),he=fe&&f.has(w)?[...F,w]:F.length?F:void 0;p.push([d,this.cdn.buildEsmUrl(i(d),{bundle:ue,external:he})]),a.add(d)}for(let d of c)o.has(d)&&(a.has(d)||p.push([d,this.cdn.buildEsmUrl(i(d),{})]),p.push([`${d}/`,`${this.cdn.esmHost}/${i(d)}/`]));return p}singletonDepsOf(e,t){return[...new Set([...$(e.meta),...B(e.meta)])].filter(r=>t.has(r))}};S.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as Z,satisfies as Ee,maxSatisfying as O,major as Pe,prerelease as Re,rsort as Ie,valid as $e}from"semver";var D=class{cmp(e,t){return e===t?0:Z(e,t)?1:Z(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!Ee(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let r=O(e,t,{includePrerelease:!0});return r===null?void 0:r}pickLatest(e){return e?.length?Ie(e)[0]:void 0}selectBestVersion(e,t){if(!e?.length)return;let r=t?.range?.trim()||"*",n=t?.preferStable??!0,o=t?.distTags?.latest;if(o&&e.includes(o)&&this.satisfies(r,o))return o;if(n){let c=O(e,r,{includePrerelease:!1});if(c)return c}return O(e,r,{includePrerelease:!0})??void 0}majorOf(e){return Pe(e)}isPrerelease(e){return Re(e)!==null}isExactVersion(e){return $e(e)!==null}},A=new D;function Q(s,e){let t=new I(s,e),r=new j(t),n=new M(s,t,A);return{packageService:new S(n,t,r,s),versionResolver:n,cdnClient:t,peerResolver:r}}var V=class{pins=new Map;indexes=new Map;negatives=new Set;meta=new Map;async getPinnedExact(e,t){return this.pins.get(`${e}@${t}`)}async setPinnedExact(e,t,r){this.pins.set(`${e}@${t}`,r)}async getIndex(e){return this.indexes.get(e)}async setIndex(e,t,r){this.indexes.set(e,{versions:t,distTags:r,updatedAt:Date.now()})}async invalidateVersionsCache(e){this.indexes.delete(e)}async isNegative(e){return this.negatives.has(e)}async recordNegative(e){this.negatives.add(e)}async clearNegative(e){this.negatives.delete(e)}async getMeta(e,t){return this.meta.get(`${e}@${t}`)}async setMeta(e,t,r,n,o){this.meta.set(`${e}@${t}`,{dependencies:r,peerDependencies:n,peerDependenciesMeta:o,updatedAt:Date.now()})}},je={async getJson(s){try{let e=await fetch(s,{redirect:"follow"});return e.ok?await e.json():void 0}catch{return}},async head(s){try{let e=await fetch(s,{method:"HEAD",redirect:"follow"});return{ok:e.ok,url:e.url}}catch{return}}},Me=new V,{packageService:X,versionResolver:Ft,cdnClient:Tt,peerResolver:Ct}=Q(Me,je);var ee=`
|
|
7
5
|
(() => {
|
|
8
6
|
// JSON parser (handles jsonish - unquoted keys)
|
|
9
7
|
const parseJson = (str) => {
|
|
@@ -109,12 +107,12 @@ import*as h from"fs/promises";import{readFileSync as We,existsSync as ce}from"fs
|
|
|
109
107
|
};
|
|
110
108
|
}
|
|
111
109
|
})();
|
|
112
|
-
`;function
|
|
110
|
+
`;function te(s){let{name:e,code:t,css:r,html:n,data:o,insight:i,importMap:c,watch:l}=s,p=n.trim()||'<div id="app"></div>',a=f=>f.replace(/<\/script/gi,"<\\/script");return`<!DOCTYPE html>
|
|
113
111
|
<html>
|
|
114
112
|
<head>
|
|
115
113
|
<meta charset="utf-8">
|
|
116
114
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
117
|
-
<title>${
|
|
115
|
+
<title>${_e(e)} - typebulb</title>
|
|
118
116
|
<script type="importmap">
|
|
119
117
|
${JSON.stringify(c,null,2)}
|
|
120
118
|
</script>
|
|
@@ -135,14 +133,14 @@ ${i?`<script>window.__TB_INSIGHT__ = ${a(JSON.stringify(i))};</script>`:""}
|
|
|
135
133
|
${l?"<script>window.__TYPEBULB_WATCH__ = true;</script>":""}
|
|
136
134
|
|
|
137
135
|
<script>
|
|
138
|
-
${
|
|
136
|
+
${ee}
|
|
139
137
|
</script>
|
|
140
138
|
|
|
141
139
|
<script type="module">
|
|
142
140
|
${a(t)}
|
|
143
141
|
</script>
|
|
144
142
|
</body>
|
|
145
|
-
</html>`}function
|
|
143
|
+
</html>`}function _e(s){return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}import{Hono as ke}from"hono";import{serve as De}from"@hono/node-server";import{streamSSE as Fe}from"hono/streaming";import*as E from"fs/promises";import*as b from"path";async function se(s){let{getHtml:e,basePath:t,port:r,reloadEmitter:n,getServerExports:o}=s,i=new ke;i.get("/",l=>l.html(e())),i.post("/__fs/read",async l=>{try{let{path:p}=await l.req.json(),a=re(p,t),f=await E.readFile(a,"utf-8");return l.json({content:f})}catch(p){let a=p instanceof Error?p.message:"Unknown error";return l.json({error:a},400)}}),i.post("/__fs/write",async l=>{try{let{path:p,content:a}=await l.req.json(),f=re(p,t);return await E.mkdir(b.dirname(f),{recursive:!0}),await E.writeFile(f,a,"utf-8"),l.json({success:!0})}catch(p){let a=p instanceof Error?p.message:"Unknown error";return l.json({error:a},400)}}),i.post("/__api/:name",async l=>{try{let p=o?.(),a=l.req.param("name");if(!p||typeof p[a]!="function")return l.json({error:`API function '${a}' not found`},404);let{args:f}=await l.req.json(),d=await p[a](...f||[]);return l.json({result:d})}catch(p){let a=p instanceof Error?p.message:"Unknown error";return l.json({error:a},500)}}),n&&i.get("/__reload",l=>Fe(l,async p=>{let a=()=>{p.writeSSE({event:"reload",data:""})};for(n.on("reload",a),p.onAbort(()=>{n.removeListener("reload",a)});;)await p.sleep(3e4)}));let c=De({fetch:i.fetch,port:r});return{port:r,close:()=>c.close()}}function re(s,e){let t=b.resolve(e,s),r=b.normalize(e);if(!b.normalize(t).startsWith(r))throw new Error("Path traversal detected - access denied");return t}async function W(s){let e=await import("net");return new Promise(t=>{let r=e.createServer();r.listen(s,()=>{let n=r.address(),o=typeof n=="object"&&n?n.port:s;r.close(()=>t(o))}),r.on("error",()=>{t(W(s+1))})})}import Te from"open";async function ne(s){await Te(s)}import Ce from"chokidar";function N(s){let{bulbPath:e,emitter:t}=s,r=Ce.watch(e,{persistent:!0,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}});return r.on("change",()=>{t.emit("reload")}),()=>r.close()}var We=Ve(Ae),Ne="0.1.3";function Ue(s){let e={file:"",port:3e3,watch:!1,open:!0,server:!1,help:!1,version:!1};for(let t=0;t<s.length;t++){let r=s[t];if(r==="--help"||r==="-h")e.help=!0;else if(r==="--version"||r==="-V")e.version=!0;else if(r==="--watch"||r==="-w")e.watch=!0;else if(r==="--headless")e.open=!1;else if(r==="--server")e.server=!0;else if(r==="--port"||r==="-p"){let n=s[++t],o=parseInt(n,10);isNaN(o)&&(console.error(`Invalid port: ${n}`),process.exit(1)),e.port=o}else r.startsWith("-")||(e.file=r)}return e}function He(){console.log(`
|
|
146
144
|
typebulb - Local bulb runner for Typebulb
|
|
147
145
|
|
|
148
146
|
Usage:
|
|
@@ -173,11 +171,11 @@ Examples:
|
|
|
173
171
|
typebulb my-editor.bulb.md
|
|
174
172
|
typebulb --watch --port 8080 my-editor.bulb.md
|
|
175
173
|
typebulb .
|
|
176
|
-
`)}async function
|
|
177
|
-
`)){let c=i.trim();if(!c||c.startsWith("#"))continue;let l=c.indexOf("=");if(l===-1)continue;let p=c.slice(0,l).trim(),a=c.slice(l+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),process.env[p]??=a}}catch{t||console.warn(` Warning: env file not found: ${r}`)}}}function
|
|
178
|
-
`);let r=new
|
|
179
|
-
${c.name}`),console.log(` ${
|
|
174
|
+
`)}async function Je(s){let t=(await m.readdir(s)).find(r=>r.endsWith(".bulb.md"));return t?h.join(s,t):null}function ae(){H([".env",".env.local"],process.cwd(),!0)}function H(s,e,t=!1){for(let r of s){let n=h.resolve(e,r);try{let o=Be(n,"utf-8");for(let i of o.split(`
|
|
175
|
+
`)){let c=i.trim();if(!c||c.startsWith("#"))continue;let l=c.indexOf("=");if(l===-1)continue;let p=c.slice(0,l).trim(),a=c.slice(l+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),process.env[p]??=a}}catch{t||console.warn(` Warning: env file not found: ${r}`)}}}function Le(s){let e=new Set,t=/\bimport\s+(?:[\s\S]*?\s+from\s+)?['"]([^./][^'"]*)['"]/g,r;for(;r=t.exec(s);){let n=r[1];if(n.startsWith("node:"))continue;let o=n.startsWith("@")?n.split("/").slice(0,2).join("/"):n.split("/")[0];e.add(o)}return[...e]}async function qe(s,e){let t=s.filter(n=>!oe(h.join(e,"node_modules",n)));if(t.length===0)return;let r=h.join(e,"package.json");oe(r)||await m.writeFile(r,JSON.stringify({name:"typebulb-server",private:!0})),console.log(` Installing: ${t.join(", ")}`),await We("npm",["install","--no-audit","--no-fund",...t],{cwd:e,shell:!0})}async function ce(s,e){let t=z(s);if(t.error)throw new Error(`Server compilation error: ${t.error}`);let r=h.join(e,".typebulb");await m.mkdir(r,{recursive:!0});let n=Le(t.code);n.length>0&&await qe(n,r);let o=h.join(r,"server.mjs");return await m.writeFile(o,t.code,"utf-8"),await import(`${Oe(o).href}?t=${Date.now()}`)}async function ie(s,e){let t=await m.readFile(s,"utf-8"),r=_(t);if(!r)throw new Error("Invalid .bulb.md file format");let n=k(r),o=T(n.config),i=J(n.data),c=q(n.code,{jsxImportSource:o.jsxImportSource});c.error&&console.error("Compilation error:",c.error);let{importMap:l}=await X.buildImportMap(c.code,o.dependencies??{}),p=te({name:n.name,code:c.code,css:n.css,html:n.html,data:i,insight:n.insight,importMap:l,watch:e}),a=h.dirname(s);o.env?.length&&H(o.env,a);let f=null;return n.server&&(f=await ce(n.server,a)),{html:p,bulb:n,serverExports:f}}async function ze(s,e){ae();let t=async()=>{let r=await m.readFile(s,"utf-8"),n=_(r);if(!n)throw new Error("Invalid .bulb.md file format");let o=k(n),i=T(o.config),c=h.dirname(s);i.env?.length&&H(i.env,c),await ce(o.server,c)};if(console.log(`Running ${h.basename(s)}...`),await t(),e){console.log(`Watching for changes...
|
|
176
|
+
`);let r=new U;r.on("reload",async()=>{try{console.log("Re-running..."),await t()}catch(n){console.error("Error:",n)}}),N({bulbPath:s,emitter:r})}}async function Ge(){let s=Ue(process.argv.slice(2));s.version&&(console.log(`typebulb ${Ne}`),process.exit(0)),s.help&&(He(),process.exit(0));let e;if(!s.file||s.file==="."){let v=await Je(process.cwd());v||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=v}else e=h.resolve(s.file);try{await m.access(e)}catch{console.error(`File not found: ${e}`),process.exit(1)}e.endsWith(".bulb.md")||(console.error("File must have .bulb.md extension"),process.exit(1));let t=await m.readFile(e,"utf-8"),r=_(t);if(r){let v=k(r);if(v.server&&(!v.code||s.server)){await ze(e,s.watch);return}}let n=process.cwd(),o=s.watch?new U:void 0;ae(),console.log(`Loading ${h.basename(e)}...`);let{html:i,bulb:c,serverExports:l}=await ie(e,s.watch),p=await W(s.port),a=await se({getHtml:()=>i,basePath:n,port:p,reloadEmitter:o,getServerExports:()=>l}),f=`http://localhost:${p}`;console.log(`
|
|
177
|
+
${c.name}`),console.log(` ${f}
|
|
180
178
|
`),s.watch&&console.log(` Watching for changes...
|
|
181
|
-
`);let d;if(s.watch&&o){let
|
|
182
|
-
`)}catch(
|
|
183
|
-
Shutting down...`),a.close(),d?.();let
|
|
179
|
+
`);let d;if(s.watch&&o){let v=new U;v.on("reload",async()=>{try{console.log("Recompiling...");let y=await ie(e,!0);i=y.html,l=y.serverExports,o.emit("reload"),console.log(`Done. Browser reloading...
|
|
180
|
+
`)}catch(y){console.error("Compile error:",y)}}),d=N({bulbPath:e,emitter:v})}s.open&&await ne(f);let w=async()=>{console.log(`
|
|
181
|
+
Shutting down...`),a.close(),d?.();let v=h.join(h.dirname(e),".typebulb","server.mjs");await m.rm(v,{force:!0}).catch(()=>{}),process.exit(0)};process.on("SIGINT",w),process.on("SIGTERM",w)}Ge().catch(s=>{console.error("Error:",s.message),process.exit(1)});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typebulb",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Local bulb runner CLI for Typebulb",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": { "node": ">=18" },
|
|
@@ -25,8 +25,7 @@
|
|
|
25
25
|
"hono": "^4.7.5",
|
|
26
26
|
"open": "^10.1.0",
|
|
27
27
|
"semver": "^7.7.3",
|
|
28
|
-
"sucrase": "^3.35.0"
|
|
29
|
-
"typescript": "^5.4.5"
|
|
28
|
+
"sucrase": "^3.35.0"
|
|
30
29
|
},
|
|
31
30
|
"devDependencies": {
|
|
32
31
|
"@types/node": "^22.15.21",
|