diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2247aa1 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,33 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Attach", + "port": 9229, + "request": "attach", + "skipFiles": [ + "/**" + ], + "type": "node" + }, + { + "request": "launch", + "name": "Launch Program", + "type": "node", + "program": "${workspaceFolder}/main.ts", + "cwd": "${workspaceFolder}", + "env": {}, + "runtimeExecutable": "C:\\Users\\strowbridge\\.deno\\bin\\deno.EXE", + "runtimeArgs": [ + "run", + "--unstable", + "--inspect-wait", + "--allow-all" + ], + "attachSimplePort": 9229 + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 3dabe8d..95c9946 100644 --- a/README.md +++ b/README.md @@ -1,48 +1,27 @@ # ESBuild Typescript Bunder -## Supports import maps and runs on Deno Deploy +## Supports import maps and runs on Deno Deploy and the browser Uses the WASM version of ESBuild for use on Deno Deploy and adds some plugins to allow for import maps. ***Unfortunately, `npm:*` and `jsr:*` specifiers are not supported currently***. ### Manual Bundle API -```typescript -import Bundle from "./mod.ts"; -Bundle( - // directory to work from - "./some_folder", +```javascript +import Bundle from "./mod.js"; - // ESBuild configuration (entry points are relative to "directory"): - {entry:["./app.tsx"]}, - - // import map (if omitted, will scan for a deno configuration within "directory" and use that) - {"imports": { +const {outputFiles} = await Bundle({ + fileSystem:import.meta.resolve('./test_project/'), + esBuild:{entryPoints:["entry"]}, + importMap:{"imports": { + "entry": "./app.tsx", "react": "https://esm.sh/preact@10.22.0/compat", "react/": "https://esm.sh/preact@10.22.0/compat/" }} -); -if(outputFiles){ - for(const item of outputFiles){ - // do something with the output... - console.log(item.text); - } +}); + + +for(const item of outputFiles){ + // do something with the output... + console.log(item.text.substring(0, 200)); } ``` -### Static bundle server - -#### API -```typescript -import Serve from "./serve.tsx"; -Serve({path:"./some_folder", html:"index.html", port:8080}); -``` - -#### CLI -``` -deno run -A /serve.tsx --path=./some_folder --html=index.html --port=8080 -``` - -Accepts three optional settings: -- `path` A directory to serve content from. Defaults to the current working directory. -- `html` A path to an html file or actual html string to *always use* when the server would serve up a non-file route. If `html` is a path, it is assumed to be relative to `path`. If not specified, routes that don't match files will 404. -- `port` Port number (default is 8000). - -When requests to typescript files are made to the server, it will treat that file as an entrypoint and return the corresponding plain javascript bundle. +(dev server is being reworked) \ No newline at end of file diff --git a/browser_example/bundle.js b/browser_example/bundle.js new file mode 100644 index 0000000..f8be7bf --- /dev/null +++ b/browser_example/bundle.js @@ -0,0 +1 @@ +var V,f,Hn,he,U,Pn,Dn,tn,ln,_n,rn,Tn,L={},On=[],ve=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,Z=Array.isArray;function w(n,e){for(var t in e)n[t]=e[t];return n}function Mn(n){var e=n.parentNode;e&&e.removeChild(n)}function x(n,e,t){var _,r,o,i={};for(o in e)o=="key"?_=e[o]:o=="ref"?r=e[o]:i[o]=e[o];if(arguments.length>2&&(i.children=arguments.length>3?V.call(arguments,2):t),typeof n=="function"&&n.defaultProps!=null)for(o in n.defaultProps)i[o]===void 0&&(i[o]=n.defaultProps[o]);return I(n,i,_,r,null)}function I(n,e,t,_,r){var o={type:n,props:e,key:t,ref:_,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,constructor:void 0,__v:r??++Hn,__i:-1,__u:0};return r==null&&f.vnode!=null&&f.vnode(o),o}function an(){return{current:null}}function S(n){return n.children}function k(n,e){this.props=n,this.context=e}function H(n,e){if(e==null)return n.__?H(n.__,n.__i+1):null;for(var t;ee&&U.sort(tn));Y.__r=0}function In(n,e,t,_,r,o,i,l,c,a,p){var u,d,s,y,E,g=_&&_.__k||On,v=e.length;for(t.__d=c,me(t,e,g),c=t.__d,u=0;u0?I(r.type,r.props,r.key,r.ref?r.ref:null,r.__v):r)!=null?(r.__=n,r.__b=n.__b+1,l=ye(r,t,i,p),r.__i=l,o=null,l!==-1&&(p--,(o=t[l])&&(o.__u|=131072)),o==null||o.__v===null?(l==-1&&u--,typeof r.type!="function"&&(r.__u|=65536)):l!==i&&(l===i+1?u++:l>i?p>c-i?u+=l-i:u--:l(c!=null&&!(131072&c.__u)?1:0))for(;i>=0||l=0){if((c=e[i])&&!(131072&c.__u)&&r==c.key&&o===c.type)return i;i--}if(l2&&(l.children=arguments.length>3?V.call(arguments,2):t),I(n.type,l,_||n.key,r||n.ref,null)}function pn(n,e){var t={__c:e="__cC"+Tn++,__:n,Consumer:function(_,r){return _.children(r)},Provider:function(_){var r,o;return this.getChildContext||(r=[],(o={})[e]=this,this.getChildContext=function(){return o},this.shouldComponentUpdate=function(i){this.props.value!==i.value&&r.some(function(l){l.__e=!0,on(l)})},this.sub=function(i){r.push(i);var l=i.componentWillUnmount;i.componentWillUnmount=function(){r.splice(r.indexOf(i),1),l&&l.call(i)}}),_.children}};return t.Provider.__=t.Consumer.contextType=t}V=On.slice,f={__e:function(n,e,t,_){for(var r,o,i;e=e.__;)if((r=e.__c)&&!r.__)try{if((o=r.constructor)&&o.getDerivedStateFromError!=null&&(r.setState(o.getDerivedStateFromError(n)),i=r.__d),r.componentDidCatch!=null&&(r.componentDidCatch(n,_||{}),i=r.__d),i)return r.__E=r}catch(l){n=l}throw n}},Hn=0,he=function(n){return n!=null&&n.constructor==null},k.prototype.setState=function(n,e){var t;t=this.__s!=null&&this.__s!==this.state?this.__s:this.__s=w({},this.state),typeof n=="function"&&(n=n(w({},t),this.props)),n&&w(t,n),n!=null&&this.__v&&(e&&this._sb.push(e),on(this))},k.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),on(this))},k.prototype.render=S,U=[],Dn=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,tn=function(n,e){return n.__v.__b-e.__v.__b},Y.__r=0,ln=0,_n=Un(!1),rn=Un(!0),Tn=0;var P,h,dn,Wn,O=0,Gn=[],G=[],m=f,$n=m.__b,Bn=m.__r,zn=m.diffed,jn=m.__c,qn=m.unmount,Yn=m.__;function D(n,e){m.__h&&m.__h(h,n,O||e),O=0;var t=h.__H||(h.__H={__:[],__h:[]});return n>=t.__.length&&t.__.push({__V:G}),t.__[n]}function A(n){return O=1,K(Jn,n)}function K(n,e,t){var _=D(P++,2);if(_.t=n,!_.__c&&(_.__=[t?t(e):Jn(void 0,e),function(l){var c=_.__N?_.__N[0]:_.__[0],a=_.t(c,l);c!==a&&(_.__N=[a,_.__[1]],_.__c.setState({}))}],_.__c=h,!h.u)){var r=function(l,c,a){if(!_.__c.__H)return!0;var p=_.__c.__H.__.filter(function(d){return!!d.__c});if(p.every(function(d){return!d.__N}))return!o||o.call(this,l,c,a);var u=!1;return p.forEach(function(d){if(d.__N){var s=d.__[0];d.__=d.__N,d.__N=void 0,s!==d.__[0]&&(u=!0)}}),!(!u&&_.__c.props===l)&&(!o||o.call(this,l,c,a))};h.u=!0;var o=h.shouldComponentUpdate,i=h.componentWillUpdate;h.componentWillUpdate=function(l,c,a){if(this.__e){var p=o;o=void 0,r(l,c,a),o=p}i&&i.call(this,l,c,a)},h.shouldComponentUpdate=r}return _.__N||_.__}function Q(n,e){var t=D(P++,3);!m.__s&&kn(t.__H,e)&&(t.__=n,t.i=e,h.__H.__h.push(t))}function M(n,e){var t=D(P++,4);!m.__s&&kn(t.__H,e)&&(t.__=n,t.i=e,h.__h.push(t))}function vn(n){return O=5,W(function(){return{current:n}},[])}function mn(n,e,t){O=6,M(function(){return typeof n=="function"?(n(e()),function(){return n(null)}):n?(n.current=e(),function(){return n.current=null}):void 0},t==null?t:t.concat(n))}function W(n,e){var t=D(P++,7);return kn(t.__H,e)?(t.__V=n(),t.i=e,t.__h=n,t.__V):t.__}function yn(n,e){return O=8,W(function(){return n},e)}function gn(n){var e=h.context[n.__c],t=D(P++,9);return t.c=n,e?(t.__==null&&(t.__=!0,e.sub(h)),e.props.value):n.__}function bn(n,e){m.useDebugValue&&m.useDebugValue(e?e(n):n)}function _t(n){var e=D(P++,10),t=A();return e.__=n,h.componentDidCatch||(h.componentDidCatch=function(_,r){e.__&&e.__(_,r),t[1](_)}),[t[0],function(){t[1](void 0)}]}function Cn(){var n=D(P++,11);if(!n.__){for(var e=h.__v;e!==null&&!e.__m&&e.__!==null;)e=e.__;var t=e.__m||(e.__m=[0,0]);n.__="P"+t[0]+"-"+t[1]++}return n.__}function Ce(){for(var n;n=Gn.shift();)if(n.__P&&n.__H)try{n.__H.__h.forEach(J),n.__H.__h.forEach(hn),n.__H.__h=[]}catch(e){n.__H.__h=[],m.__e(e,n.__v)}}m.__b=function(n){h=null,$n&&$n(n)},m.__=function(n,e){n&&e.__k&&e.__k.__m&&(n.__m=e.__k.__m),Yn&&Yn(n,e)},m.__r=function(n){Bn&&Bn(n),P=0;var e=(h=n.__c).__H;e&&(dn===h?(e.__h=[],h.__h=[],e.__.forEach(function(t){t.__N&&(t.__=t.__N),t.__V=G,t.__N=t.i=void 0})):(e.__h.forEach(J),e.__h.forEach(hn),e.__h=[],P=0)),dn=h},m.diffed=function(n){zn&&zn(n);var e=n.__c;e&&e.__H&&(e.__H.__h.length&&(Gn.push(e)!==1&&Wn===m.requestAnimationFrame||((Wn=m.requestAnimationFrame)||ke)(Ce)),e.__H.__.forEach(function(t){t.i&&(t.__H=t.i),t.__V!==G&&(t.__=t.__V),t.i=void 0,t.__V=G})),dn=h=null},m.__c=function(n,e){e.some(function(t){try{t.__h.forEach(J),t.__h=t.__h.filter(function(_){return!_.__||hn(_)})}catch(_){e.some(function(r){r.__h&&(r.__h=[])}),e=[],m.__e(_,t.__v)}}),jn&&jn(n,e)},m.unmount=function(n){qn&&qn(n);var e,t=n.__c;t&&t.__H&&(t.__H.__.forEach(function(_){try{J(_)}catch(r){e=r}}),t.__H=void 0,e&&m.__e(e,t.__v))};var Zn=typeof requestAnimationFrame=="function";function ke(n){var e,t=function(){clearTimeout(_),Zn&&cancelAnimationFrame(e),setTimeout(n)},_=setTimeout(t,100);Zn&&(e=requestAnimationFrame(t))}function J(n){var e=h,t=n.__c;typeof t=="function"&&(n.__c=void 0,t()),h=e}function hn(n){var e=h;n.__c=n.__(),h=e}function kn(n,e){return!n||n.length!==e.length||e.some(function(t,_){return t!==n[_]})}function Jn(n,e){return typeof e=="function"?e(n):e}function oe(n,e){for(var t in e)n[t]=e[t];return n}function xn(n,e){for(var t in n)if(t!=="__source"&&!(t in e))return!0;for(var _ in e)if(_!=="__source"&&n[_]!==e[_])return!0;return!1}function Sn(n,e){this.props=n,this.context=e}function Ee(n,e){function t(r){var o=this.props.ref,i=o==r.ref;return!i&&o&&(o.call?o(null):o.current=null),e?!e(this.props,r)||!i:xn(this.props,r)}function _(r){return this.shouldComponentUpdate=t,x(n,r)}return _.displayName="Memo("+(n.displayName||n.name)+")",_.prototype.isReactComponent=!0,_.__f=!0,_}(Sn.prototype=new k).isPureReactComponent=!0,Sn.prototype.shouldComponentUpdate=function(n,e){return xn(this.props,n)||xn(this.state,e)};var Kn=f.__b;f.__b=function(n){n.type&&n.type.__f&&n.ref&&(n.props.ref=n.ref,n.ref=null),Kn&&Kn(n)};var xe=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.forward_ref")||3911;function Se(n){function e(t){var _=oe({},t);return delete _.ref,n(_,t.ref||null)}return e.$$typeof=xe,e.render=e,e.prototype.isReactComponent=e.__f=!0,e.displayName="ForwardRef("+(n.displayName||n.name)+")",e}var Qn=function(n,e){return n==null?null:N(N(n).map(e))},Ne={map:Qn,forEach:Qn,count:function(n){return n?N(n).length:0},only:function(n){var e=N(n);if(e.length!==1)throw"Children.only";return e[0]},toArray:N},we=f.__e;f.__e=function(n,e,t,_){if(n.then){for(var r,o=e;o=o.__;)if((r=o.__c)&&r.__c)return e.__e==null&&(e.__e=t.__e,e.__k=t.__k),r.__c(n,e)}we(n,e,t,_)};var Xn=f.unmount;function ue(n,e,t){return n&&(n.__c&&n.__c.__H&&(n.__c.__H.__.forEach(function(_){typeof _.__c=="function"&&_.__c()}),n.__c.__H=null),(n=oe({},n)).__c!=null&&(n.__c.__P===t&&(n.__c.__P=e),n.__c=null),n.__k=n.__k&&n.__k.map(function(_){return ue(_,e,t)})),n}function ie(n,e,t){return n&&t&&(n.__v=null,n.__k=n.__k&&n.__k.map(function(_){return ie(_,e,t)}),n.__c&&n.__c.__P===e&&(n.__e&&t.appendChild(n.__e),n.__c.__e=!0,n.__c.__P=t)),n}function X(){this.__u=0,this.t=null,this.__b=null}function le(n){var e=n.__.__c;return e&&e.__a&&e.__a(n)}function Pe(n){var e,t,_;function r(o){if(e||(e=n()).then(function(i){t=i.default||i},function(i){_=i}),_)throw _;if(!t)throw e;return x(t,o)}return r.displayName="Lazy",r.__f=!0,r}function $(){this.u=null,this.o=null}f.unmount=function(n){var e=n.__c;e&&e.__R&&e.__R(),e&&32&n.__u&&(n.type=null),Xn&&Xn(n)},(X.prototype=new k).__c=function(n,e){var t=e.__c,_=this;_.t==null&&(_.t=[]),_.t.push(t);var r=le(_.__v),o=!1,i=function(){o||(o=!0,t.__R=null,r?r(l):l())};t.__R=i;var l=function(){if(!--_.__u){if(_.state.__a){var c=_.state.__a;_.__v.__k[0]=ie(c,c.__c.__P,c.__c.__O)}var a;for(_.setState({__a:_.__b=null});a=_.t.pop();)a.forceUpdate()}};_.__u++||32&e.__u||_.setState({__a:_.__b=_.__v.__k[0]}),n.then(i,i)},X.prototype.componentWillUnmount=function(){this.t=[]},X.prototype.render=function(n,e){if(this.__b){if(this.__v.__k){var t=document.createElement("div"),_=this.__v.__k[0].__c;this.__v.__k[0]=ue(this.__b,t,_.__O=_.__P)}this.__b=null}var r=e.__a&&x(S,null,n.fallback);return r&&(r.__u&=-33),[x(S,null,e.__a?null:n.children),r]};var ne=function(n,e,t){if(++t[1]===t[0]&&n.o.delete(e),n.props.revealOrder&&(n.props.revealOrder[0]!=="t"||!n.o.size))for(t=n.u;t;){for(;t.length>3;)t.pop()();if(t[1]>>1,1),e.i.removeChild(_)}}),T(x(Re,{context:e.context},n.__v),e.l)}function He(n,e){var t=x(Ue,{__v:n,i:e});return t.containerInfo=e,t}($.prototype=new k).__a=function(n){var e=this,t=le(e.__v),_=e.o.get(n);return _[0]++,function(r){var o=function(){e.props.revealOrder?(_.push(r),ne(e,n,_)):r()};t?t(o):o()}},$.prototype.render=function(n){this.u=null,this.o=new Map;var e=N(n.children);n.revealOrder&&n.revealOrder[0]==="b"&&e.reverse();for(var t=e.length;t--;)this.o.set(e[t],this.u=[1,0,this.u]);return n.children},$.prototype.componentDidUpdate=$.prototype.componentDidMount=function(){var n=this;this.o.forEach(function(e,t){ne(n,t,e)})};var ae=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.element")||60103,De=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image(!S)|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,Te=/^on(Ani|Tra|Tou|BeforeInp|Compo)/,Oe=/[A-Z0-9]/g,Me=typeof document<"u",Fe=function(n){return(typeof Symbol<"u"&&typeof Symbol()=="symbol"?/fil|che|rad/:/fil|che|ra/).test(n)};function Ie(n,e,t){return e.__k==null&&(e.textContent=""),T(n,e),typeof t=="function"&&t(),n?n.__c:null}function Le(n,e,t){return fn(n,e),typeof t=="function"&&t(),n?n.__c:null}k.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(n){Object.defineProperty(k.prototype,n,{configurable:!0,get:function(){return this["UNSAFE_"+n]},set:function(e){Object.defineProperty(this,n,{configurable:!0,writable:!0,value:e})}})});var ee=f.event;function Ve(){}function Ae(){return this.cancelBubble}function We(){return this.defaultPrevented}f.event=function(n){return ee&&(n=ee(n)),n.persist=Ve,n.isPropagationStopped=Ae,n.isDefaultPrevented=We,n.nativeEvent=n};var Nn,$e={enumerable:!1,configurable:!0,get:function(){return this.class}},te=f.vnode;f.vnode=function(n){typeof n.type=="string"&&function(e){var t=e.props,_=e.type,r={};for(var o in t){var i=t[o];if(!(o==="value"&&"defaultValue"in t&&i==null||Me&&o==="children"&&_==="noscript"||o==="class"||o==="className")){var l=o.toLowerCase();o==="defaultValue"&&"value"in t&&t.value==null?o="value":o==="download"&&i===!0?i="":l==="translate"&&i==="no"?i=!1:l==="ondoubleclick"?o="ondblclick":l!=="onchange"||_!=="input"&&_!=="textarea"||Fe(t.type)?l==="onfocus"?o="onfocusin":l==="onblur"?o="onfocusout":Te.test(o)?o=l:_.indexOf("-")===-1&&De.test(o)?o=o.replace(Oe,"-$&").toLowerCase():i===null&&(i=void 0):l=o="oninput",l==="oninput"&&r[o=l]&&(o="oninputCapture"),r[o]=i}}_=="select"&&r.multiple&&Array.isArray(r.value)&&(r.value=N(t.children).forEach(function(c){c.props.selected=r.value.indexOf(c.props.value)!=-1})),_=="select"&&r.defaultValue!=null&&(r.value=N(t.children).forEach(function(c){c.props.selected=r.multiple?r.defaultValue.indexOf(c.props.value)!=-1:r.defaultValue==c.props.value})),t.class&&!t.className?(r.class=t.class,Object.defineProperty(r,"className",$e)):(t.className&&!t.class||t.class&&t.className)&&(r.class=r.className=t.className),e.props=r}(n),n.$$typeof=ae,te&&te(n)};var _e=f.__r;f.__r=function(n){_e&&_e(n),Nn=n.__c};var re=f.diffed;f.diffed=function(n){re&&re(n);var e=n.props,t=n.__e;t!=null&&n.type==="textarea"&&"value"in e&&e.value!==t.value&&(t.value=e.value==null?"":e.value),Nn=null};var Be={ReactCurrentDispatcher:{current:{readContext:function(n){return Nn.__n[n.__c].props.value},useCallback:yn,useContext:gn,useDebugValue:bn,useDeferredValue:se,useEffect:Q,useId:Cn,useImperativeHandle:mn,useInsertionEffect:pe,useLayoutEffect:M,useMemo:W,useReducer:K,useRef:vn,useState:A,useSyncExternalStore:de,useTransition:fe}}},lt="17.0.2";function ze(n){return x.bind(null,n)}function nn(n){return!!n&&n.$$typeof===ae}function je(n){return nn(n)&&n.type===S}function qe(n){return!!n&&!!n.displayName&&(typeof n.displayName=="string"||n.displayName instanceof String)&&n.displayName.startsWith("Memo(")}function Ye(n){return nn(n)?An.apply(null,arguments):n}function Ze(n){return!!n.__k&&(T(null,n),!0)}function Ge(n){return n&&(n.base||n.nodeType===1&&n)||null}var Je=function(n,e){return n(e)},Ke=function(n,e){return n(e)},Qe=S;function ce(n){n()}function se(n){return n}function fe(){return[!1,ce]}var pe=M,Xe=nn;function de(n,e){var t=e(),_=A({h:{__:t,v:e}}),r=_[0].h,o=_[1];return M(function(){r.__=t,r.v=e,En(r)&&o({h:r})},[n,t,e]),Q(function(){return En(r)&&o({h:r}),n(function(){En(r)&&o({h:r})})},[n]),t}function En(n){var e,t,_=n.v,r=n.__;try{var o=_();return!((e=r)===(t=o)&&(e!==0||1/e==1/t)||e!=e&&t!=t)}catch{return!0}}var nt={useState:A,useId:Cn,useReducer:K,useEffect:Q,useLayoutEffect:M,useInsertionEffect:pe,useTransition:fe,useDeferredValue:se,useSyncExternalStore:de,startTransition:ce,useRef:vn,useImperativeHandle:mn,useMemo:W,useCallback:yn,useContext:gn,useDebugValue:bn,version:"17.0.2",Children:Ne,render:Ie,hydrate:Le,unmountComponentAtNode:Ze,createPortal:He,createElement:x,createContext:pn,createFactory:ze,cloneElement:Ye,createRef:an,Fragment:S,isValidElement:nn,isElement:Xe,isFragment:je,isMemo:qe,findDOMNode:Ge,Component:k,PureComponent:Sn,memo:Ee,forwardRef:Se,flushSync:Ke,unstable_batchedUpdates:Je,StrictMode:Qe,Suspense:X,SuspenseList:$,lazy:Pe,__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:Be};export{Ne as Children,k as Component,S as Fragment,Sn as PureComponent,Qe as StrictMode,X as Suspense,$ as SuspenseList,Be as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,Ye as cloneElement,pn as createContext,x as createElement,ze as createFactory,He as createPortal,an as createRef,nt as default,Ge as findDOMNode,Ke as flushSync,Se as forwardRef,Le as hydrate,Xe as isElement,je as isFragment,qe as isMemo,nn as isValidElement,Pe as lazy,Ee as memo,Ie as render,ce as startTransition,Ze as unmountComponentAtNode,Je as unstable_batchedUpdates,yn as useCallback,gn as useContext,bn as useDebugValue,se as useDeferredValue,Q as useEffect,_t as useErrorBoundary,Cn as useId,mn as useImperativeHandle,pe as useInsertionEffect,M as useLayoutEffect,W as useMemo,K as useReducer,vn as useRef,A as useState,de as useSyncExternalStore,fe as useTransition,lt as version}; diff --git a/browser_example/index.html b/browser_example/index.html new file mode 100644 index 0000000..8c2ab52 --- /dev/null +++ b/browser_example/index.html @@ -0,0 +1,39 @@ + + + + + Document + + + + + + + + + \ No newline at end of file diff --git a/jsapi.test.tsx b/jsapi.test.tsx deleted file mode 100644 index c3b0571..0000000 --- a/jsapi.test.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import * as Test from "https://deno.land/std@0.224.0/assert/mod.ts"; -import Bundle, {ESBuild} from "./mod.ts"; - - -const path = await import.meta.resolve("./test/"); -const {outputFiles} = await Bundle(path, {entryPoints:["./app.tsx"]}); - -Deno.test("check", ()=>{ - Test.assert(outputFiles?.length == 1); - Test.assert(outputFiles[0].text.length > 1000); -}) diff --git a/mod.js b/mod.js new file mode 100644 index 0000000..945d5d1 --- /dev/null +++ b/mod.js @@ -0,0 +1,136 @@ +import * as ESBuild from "https://deno.land/x/esbuild@v0.25.0/wasm.js"; +await ESBuild.initialize({ worker: false }); + +/** @typedef {{imports?:Record, scopes?:Record>}} ImportMap */ +/** @typedef {{fileSystem:string, esBuild:ESBuild.BuildOptions, importMap:ImportMap}} BuildOptions */ + +/** + * Resolves a module specifier against an import map + * @param {string} specifier - The module specifier to resolve (bare specifier or absolute URL) + * @param {ImportMap} importMap - The import map object containing imports and scopes + * @param {string} baseURL - The base URL for context (especially for scopes) + * @returns {string} The resolved URL + */ +function resolveImportMap(specifier, importMap, baseURL) { + + // Check for prefix matches in the main imports + const result = checkPrefixMatch(specifier, importMap.imports); + if (result) { + return result + } + + // First check scopes that match the baseURL (scope applies based on baseURL, not specifier) + if (importMap.scopes) { + const scopeKeys = Object.keys(importMap.scopes).sort((a, b) => b.length - a.length); + + for (const scopeKey of scopeKeys) { + // Convert scope key to absolute URL and check if baseURL starts with it + const scopeURL = new URL(scopeKey, baseURL).href; + + if (baseURL.startsWith(scopeURL)) { + const scopeImports = importMap.scopes[scopeKey]; + + // Check for prefix match in the scope + const result = checkPrefixMatch(specifier, scopeImports); + if (result) { + return result; + } + } + } + } +} + +/** + * Helper function to check for prefix matches + * @param {string} specifier - The specifier to check + * @param {Object} mappings - Object with prefix mappings + * @returns {string|null} The resolved path or null if no match + */ +function checkPrefixMatch(specifier, mappings) { + + const check = mappings[specifier]; + if(check){ return check; } + + const prefixes = Object.keys(mappings) + .filter(key => key.endsWith('/') && specifier.startsWith(key)) + .sort((a, b) => b.length - a.length); + + for (const prefix of prefixes) { + const remainder = specifier.slice(prefix.length); + return mappings[prefix] + remainder; + } + + return null; +} + +/** + * + * @param {string} fullPathDir + * @param {ImportMap} importMap + * @returns {ESBuild.Plugin} + */ +export function resolvePlugin(fullPathDir, importMap) +{ + return { + name: "resolve-plugin", + setup(build) { + + build.onResolve( {/* `/`, `./`, and `../` */ filter:/^(\/|\.\/|\.\.\/).*/}, args=> + { + const resolveRoot = args.importer||fullPathDir; + const out = { path:new URL(args.path, resolveRoot).href, namespace:"FULLPATH" }; + return out; + } ); + + build.onResolve({filter:/.*/}, args=> + { + const resolveRoot = args.importer||fullPathDir; + const check = resolveImportMap(args.path, importMap, resolveRoot); + if(check) + { + console.log("import remap", args.path, "=>", check); + const out = { path:new URL(check, resolveRoot).href, namespace:"FULLPATH" }; + return out; + } + + }) + + build.onLoad( + {/* `file://`, `http://`, and `https://` */ filter:/^(file:\/\/|http:\/\/|https:\/\/).*/}, + async(args)=> + { + const contents = await fetch(args.path).then(r=>r.text()); + const out = { contents, loader: `tsx` }; + return out; + } ); + }, + } +}; + + +/** + * Perform a bundle + * @param {Partial} options + * @returns {Promise>} build result + */ +export default async function Build(options) +{ + const configuration = { + entryPoints: ["entry"], + bundle: true, + minify: true, + format: "esm", + jsx: "automatic", + jsxImportSource: "react", + ...options.esBuild||{}, + plugins: [ + resolvePlugin(options.fileSystem||import.meta.resolve("./"), options.importMap||{}), + ...options.esBuild.plugins||[] + ] + }; + + const result = await ESBuild.build(configuration); + return result; +} + +export { ESBuild } \ No newline at end of file diff --git a/mod.test.tsx b/mod.test.tsx new file mode 100644 index 0000000..1b390aa --- /dev/null +++ b/mod.test.tsx @@ -0,0 +1,24 @@ +import * as Test from "https://deno.land/std@0.224.0/assert/mod.ts"; + +import Bundle from "./mod.js"; + +const {outputFiles} = await Bundle({ + fileSystem:import.meta.resolve('./test_project/'), + esBuild:{entryPoints:["entry"]}, + importMap:{"imports": { + "entry": "./app.tsx", + "react": "https://esm.sh/preact@10.22.0/compat", + "react/": "https://esm.sh/preact@10.22.0/compat/" + }} +}); + + +for(const item of outputFiles){ + // do something with the output... + console.log(item.text.substring(0, 200)); +} + +Deno.test("check", ()=>{ + Test.assert(outputFiles?.length == 1); + Test.assert(outputFiles[0].text.length > 1000); +}) diff --git a/mod.ts b/mod.ts deleted file mode 100644 index a957ea1..0000000 --- a/mod.ts +++ /dev/null @@ -1,67 +0,0 @@ -import * as ESBuild from "https://deno.land/x/esbuild@v0.19.2/wasm.js"; -import * as Mapper from "https://esm.sh/esbuild-plugin-importmaps@1.0.0"; // https://github.com/andstellar/esbuild-plugin-importmaps -import Introspect from "./introspect.ts"; - -const prefix = "/_dot_importer_/"; -const resolvePlugin =(fullPathDir:string):ESBuild.Plugin=>({ - name: "resolve-plugin", - setup(build) { - build.onResolve({ filter: /^(\.\/|\.\.\/).*/ }, (args)=> - { - let resolveRoot = args.importer||fullPathDir; - if(resolveRoot.startsWith(prefix)) - { - resolveRoot = resolveRoot.substring(prefix.length); - } - const output:ESBuild.OnResolveResult = { - path:prefix + new URL(args.path, resolveRoot).href, - namespace:"http", - } - return output; - }); - build.onLoad({ filter: /.*/, namespace:"http" }, async(args)=> { - const fetchPath = args.path.substring(prefix.length); - console.log("fetch path", fetchPath); - const result = await fetch(fetchPath); - const contents = await result.text(); - return { contents, loader: `tsx` }; - }); - }, -}); - -await ESBuild.initialize({ worker: false }); -export type ImportMap = Parameters[0]; -export type BuildOptions = ESBuild.BuildOptions; -/** - * - * @param directory Full file:// or http(s):// path to the directory containing assets you want to build (needed to resolve relative imports) - * @param buildOptions ESBuild "build" options (will be merged with "reasonable defaults") for docs: https://esbuild.github.io/api/#general-options - * @param importMap An object to act as the import map ({imports:Record}). If this is left blank, a configuration will be scanned for in the "directory" - * @returns build result - */ -export default async function(directory:string, buildOptions={} as BuildOptions, importMap?:ImportMap):Promise> -{ - if(!importMap) - { - importMap = await Introspect(directory) as ImportMap - } - console.log("using import map", importMap); - const configuration:ESBuild.BuildOptions = { - entryPoints: ["entry"], - bundle: true, - minify: true, - format: "esm", - jsx: "automatic", - jsxImportSource: "react", - ...buildOptions, - plugins: [ - resolvePlugin(directory), - Mapper.importmapPlugin(importMap) as ESBuild.Plugin, - ...buildOptions.plugins||[] - ] - }; - - const result = await ESBuild.build(configuration); - return result; -} -export { ESBuild }; \ No newline at end of file diff --git a/introspect.ts b/server/introspect.ts similarity index 100% rename from introspect.ts rename to server/introspect.ts diff --git a/serve.tsx b/server/serve.tsx similarity index 97% rename from serve.tsx rename to server/serve.tsx index 283ec83..0636a41 100644 --- a/serve.tsx +++ b/server/serve.tsx @@ -1,6 +1,6 @@ import mime from "https://esm.sh/mime@4.0.3"; import { parseArgs } from "jsr:@std/cli/parse-args"; -import bundler, {type ESBuild, type ImportMap} from "./mod.ts"; +import bundler, {type ESBuild, type ImportMap} from "../mod.js"; import Introspect from "./introspect.ts"; if(Deno.mainModule == import.meta.url) @@ -105,6 +105,9 @@ async function serve(settings:ServeArgs):Promise const url = new URL(req.url); const {path, type} = PathExtensionType(url.pathname); + + console.log(req.url); + const headers = {"content-type":type||"", ETag, "Cache-Control":"max-age=3600"} // serve javascript diff --git a/test/app-dynamic.tsx b/test_project/app-dynamic.tsx similarity index 100% rename from test/app-dynamic.tsx rename to test_project/app-dynamic.tsx diff --git a/test/app.tsx b/test_project/app.tsx similarity index 100% rename from test/app.tsx rename to test_project/app.tsx diff --git a/test/deep/deep.tsx b/test_project/deep/deep.tsx similarity index 100% rename from test/deep/deep.tsx rename to test_project/deep/deep.tsx diff --git a/test/deno.json b/test_project/deno.json similarity index 100% rename from test/deno.json rename to test_project/deno.json diff --git a/test/index.html b/test_project/index.html similarity index 100% rename from test/index.html rename to test_project/index.html diff --git a/test/leaf.ts b/test_project/leaf.ts similarity index 100% rename from test/leaf.ts rename to test_project/leaf.ts diff --git a/test/other.tsx b/test_project/other.tsx similarity index 100% rename from test/other.tsx rename to test_project/other.tsx