UNPKG

@wrdagency/react-islands

Version:

Created by Kyle Cooper at [WRD.agency](https://webresultsdirect.com)

3 lines (2 loc) 6.78 kB
#!/usr/bin/env node import e from"@rollup/plugin-commonjs";import n from"@rollup/plugin-node-resolve";import t from"@rollup/plugin-replace";import r from"@rollup/plugin-terser";import o from"path";import{rollup as s,watch as i}from"rollup";import a from"@rollup/plugin-typescript";import{typescriptPaths as c}from"rollup-plugin-typescript-paths";import l,{readFileSync as u}from"fs";import{exec as p}from"child_process";import{promisify as m}from"util";import d from"yocto-spinner";import f from"command-line-args";import g from"command-line-usage";class h{lines=[];import(e,n){return n||(n=h.packageNameToProperty(e)),this.add(`import * as ${n} from "${e}"`)}createGlobalObject(e){return this.add(e.split(".").map(e=>e.trim()).filter(Boolean).map((e,n,t)=>{const r="window."+t.slice(0,n+1).join(".");return`${r} = ${r} || {}`}))}setGlobalObjectProperty(e,n,t){return this.add(`window.${e}['${n}'] = ${t}`)}static packageNameToProperty(e){return e.replace(/^@/,"").replace(/\//g,"_").replace(/[-_](.)/g,(e,n)=>n.toUpperCase()).replace(/^[a-z]/,e=>e.toUpperCase())}static renderReactComponentToFile(e,n){return`var server = require('react-dom/server');\nvar fs = require('node:fs/promises');\nvar path = require('node:path');\nconst html = server.renderToString( ${n}( {} ) );\nconst file = path.resolve(__dirname, '${e}');\nfs.writeFile(file, html, { flag: "w+" });`}add(e){return Array.isArray(e)?this.lines.push(...e):this.lines.push(e),this}out(){return this.lines.join(";\n")}}function y(e){const{dependencies:n,namespace:t=""}=e,r="\0virtual-entry";return{name:"rollup-plugin-virtualize-dependency",resolveId:e=>"virtual-entry"===e?r:null,load(e){if(e!==r)return null;const o=new h;o.createGlobalObject(t);for(const e of n){const n=h.packageNameToProperty(e);o.import(e,n),o.setGlobalObjectProperty(t,n,n)}return o.out()}}}async function w(e){const{output:n,...t}=e;let r,o=!1;try{r=await s(t),await r.write(n)}catch(e){o=!0,console.error(e)}return r&&await r.close(),!o}function b(e){const{output:n,...t}=e,r=i({...t,output:n,watch:{clearScreen:!1}});return r.on("event",e=>{"BUNDLE_END"===e.code&&e.result&&e.result.close()}),r}function j(s){const{output:i,minify:a,jsx:c,common:l}=s;return{input:"virtual-entry",jsx:c,output:{name:"Islands._Common",file:o.resolve(i,"common.js"),format:"iife"},plugins:[t({preventAssignment:!0,"process.env.NODE_ENV":JSON.stringify("production")}),y({dependencies:l,namespace:"Islands._Common"}),n(),e(),a&&r()]}}const v=m(p);class ${line(e){console.log(e)}async spinner(e,n){const t=d({text:`${e}...`}).start();await n()?t.success(`Succeeded: ${e}`):t.warning(`Failed: ${e}`)}watcher(e,n){const t=d({text:`Rebuilding ${e}...`});let r=0;n.on("event",n=>{if("START"===n.code)t.clear(),t.start(),r=Date.now();else if("END"===n.code){const n=Date.now()-r;t.success(`Rebuilt: ${e} in ${n}ms.`)}else"ERROR"===n.code&&(t.warning(`Failed: ${e}`),console.error(n.error))})}async command(e){try{const{stdout:n,stderr:t}=await v(e);return n&&console.log(n),t&&console.error(t),n}catch(e){throw console.error(e),e}}}function x(e){const{deleteAfterRunning:n=!1}=e;return{name:"rollup-plugin-run-script-after-builder",writeBundle(e,t){const r=e.dir?e.dir:o.dirname(e.file||"");for(const[e,s]of Object.entries(t)){const t=o.resolve(r,e);if("chunk"!==s.type||!s.isEntry)return;if(!t&&!t.endsWith("js"))return;if(!l.existsSync(t))return;(new $).command(`node ${t}`).then(()=>{n&&l.unlinkSync(t)})}}}}function N(o,s){const{name:i,input:l,output:u,minify:p,jsx:m,typescript:d,define:f}=o,{external:g=[],subName:h,format:y,globals:w={},prefix:b,suffix:j,plugins:v=[]}=s;return{input:l,external:[...Object.keys(w),...g],jsx:m,output:{name:`Islands.${i}`,globals:w,format:y,entryFileNames:`${i}/${h}`,dir:u,banner:b&&(e=>b(e.name)),footer:j&&(e=>j(e.name))},plugins:[n({extensions:[".cjs",".mjs",".js",".json",".node",".jsx",".ts",".tsx"]}),e(),d&&a({outputToFilesystem:!1,noForceEmit:!0,compilerOptions:{outDir:u,jsx:m}}),d&&c(),t({preventAssignment:!0,values:{...f,"process.env.NODE_ENV":JSON.stringify("production")}}),p&&r(),...v]}}function O(e){return N(e,{subName:"client.js",format:"iife",globals:e.common.reduce((e,n)=>({...e,[n]:`Islands._Common["${h.packageNameToProperty(n)}"]`}),{}),suffix:()=>`\nwindow.Islands['${e.name}']?.render('${e.name}')`})}function k(e){const n=[O(e)];return e.ssg&&n.push(function(e){return N(e,{external:["react","react-dom"],subName:"server.cjs",format:"cjs",suffix:()=>h.renderReactComponentToFile("ssg.html","module.exports.component"),plugins:[x({deleteAfterRunning:!0})]})}(e)),n}function S(e){return async function(e){let n=!0;for(const t of e)await w(t)||(n=!1);return n}(k(e))}function C(e){return b(O(e))}class T{args;callback;description;constructor(e){let{args:n,callback:t,description:r}=e;n.push({name:"help",alias:"h",type:Boolean,description:"Display this usage guide."}),this.args=n,this.callback=t,this.description=r}run(e){const{help:n,...t}=f(this.args,{argv:e});if(!n)return this.callback(t);console.log(g([{header:"Options",optionList:this.args}]))}}function _(e){const n=u(e,"utf8");return function(e){const n=(e,n)=>"boolean"==typeof e?e:n;return{islands:e.islands,output:e.output||"./dist/",minify:n(e.minify,!0),ssg:n(e.ssg,!0),jsx:e.jsx||"react-jsx",typescript:n(e.typescript,!0),common:e.common||["react","react/jsx-runtime","react-dom/client","@wrdagency/react-islands"],define:e.define||{}}}(JSON.parse(n))}!async function(e){const{command:n,help:t=!1,_unknown:r=[]}=f([{name:"command",type:String,defaultOption:!0},{name:"help",alias:"h",type:Boolean,description:"Display this usage guide."}],{stopAtFirstUnknown:!0});if(n&&n in e)return e[n].run([...r,t&&"--help"].filter(Boolean));if(t){const n=Object.keys(e).map(n=>({name:n,summary:e[n].description})),t=g([{header:"Synopsis",content:"npx react-islands <command> <options>"},{header:"Command List",content:n}]);console.log(t)}else console.error(`Command '${n}' not recognized by React Islands.`)}({build:new T({description:"Build and statically render the islands.",args:[{name:"config",type:String,alias:"c",description:"The config file to use.",defaultValue:"islands.config.json"}],callback:async e=>{const{config:n}=e,t=new $,r=_(n);r.common&&await t.spinner("Creating common dependencies file",async()=>w(j(r)));for(const[e,n]of Object.entries(r.islands))await t.spinner(`Creating island ${e}`,()=>S({name:e,input:n,...r}))}}),watch:new T({description:"Watch & build the islands for development",args:[{name:"config",type:String,alias:"c",description:"The config file to use.",defaultValue:"islands.config.json"}],callback:async e=>{const{config:n}=e,t=new $,r=_(n);if(r.common){const e=b(j(r));t.watcher("Common Dependencies",e)}for(const[e,n]of Object.entries(r.islands)){const o=C({name:e,input:n,...r});t.watcher(e,o)}}})});