| 
									
										
										
										
											2024-07-01 03:59:01 +00:00
										 |  |  | #!/bin/bash
 | 
					
						
							|  |  |  | # https://docs.sheetjs.com/docs/demos/net/server#worker-threads | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cd /tmp | 
					
						
							|  |  |  | rm -rf sheetjs-worker | 
					
						
							| 
									
										
										
										
											2025-04-18 04:04:01 +00:00
										 |  |  | . ~/.bashrc ## This is apparently needed in macos | 
					
						
							| 
									
										
										
										
											2024-07-01 03:59:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | mkdir sheetjs-worker | 
					
						
							|  |  |  | cd sheetjs-worker | 
					
						
							|  |  |  | echo '{ "type": "module" }' > package.json | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cat >worker.js <<EOF | 
					
						
							|  |  |  | /* load the worker_threads module */ | 
					
						
							|  |  |  | import { parentPort } from 'node:worker_threads'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* load the SheetJS module and hook to FS */ | 
					
						
							|  |  |  | import { set_fs, readFile, write } from 'xlsx'; | 
					
						
							|  |  |  | import * as fs from 'fs'; | 
					
						
							|  |  |  | set_fs(fs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* the server will send a message with the \`path\` field */ | 
					
						
							|  |  |  | parentPort.on('message', (task) => { | 
					
						
							|  |  |  |   // read file | 
					
						
							|  |  |  |   const wb = readFile(task.path, { dense: true }); | 
					
						
							|  |  |  |   // send back XLSX | 
					
						
							|  |  |  |   parentPort.postMessage(write(wb, { type: "buffer", bookType: "xlsx" })); | 
					
						
							|  |  |  |   // remove file | 
					
						
							|  |  |  |   fs.unlink(task.path, ()=>{}); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | EOF | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/server/worker_pool.js | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/pres.numbers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cat >main.mjs <<EOF | 
					
						
							|  |  |  | /* load dependencies */ | 
					
						
							|  |  |  | import os from 'node:os'; | 
					
						
							|  |  |  | import process from 'node:process' | 
					
						
							|  |  |  | import express from 'express'; | 
					
						
							|  |  |  | import formidable from 'formidable'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* load worker pool */ | 
					
						
							|  |  |  | import WorkerPool from './worker_pool.js'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const pool = new WorkerPool(os.cpus().length); | 
					
						
							|  |  |  | process.on("beforeExit", () => { pool.close(); }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* create server */ | 
					
						
							|  |  |  | const app = express(); | 
					
						
							|  |  |  | app.post('/', (req, res, next) => { | 
					
						
							|  |  |  |   // parse body | 
					
						
							|  |  |  |   const form = formidable({}); | 
					
						
							|  |  |  |   form.parse(req, (err, fields, files) => { | 
					
						
							|  |  |  |     // look for "upload" field | 
					
						
							|  |  |  |     if(err) return next(err); | 
					
						
							|  |  |  |     if(!files["upload"]) return next(new Error("missing \`upload\` file")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // send a message to the worker with the path to the uploaded file | 
					
						
							|  |  |  |     pool.runTask({ path: files["upload"].filepath }, (err, result) => { | 
					
						
							|  |  |  |       if(err) return next(err); | 
					
						
							|  |  |  |       // send the file back as an attachment | 
					
						
							|  |  |  |       res.attachment("SheetJSPool.xlsx"); | 
					
						
							|  |  |  |       res.status(200).end(result); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // start server | 
					
						
							|  |  |  | app.listen(7262, () => { console.log(\`Example app listening on port 7262\`); }); | 
					
						
							|  |  |  | EOF | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-18 04:04:01 +00:00
										 |  |  | npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz formidable@2.1.2 | 
					
						
							|  |  |  | for express in 4.21.2 5.1.0; do | 
					
						
							|  |  |  |   npm i --save express@$express | 
					
						
							|  |  |  |   npm ls | grep express | 
					
						
							|  |  |  |   # this version uses `nvm` to cycle through node versions | 
					
						
							|  |  |  |   for n in 18 20 22; do | 
					
						
							|  |  |  |     nvm use $n | 
					
						
							|  |  |  |     node --version | 
					
						
							|  |  |  |     npx -y concurrently -k 'node main.mjs' 'sleep 2; curl -X POST -F upload=@pres.numbers http://localhost:7262/ -J -O' | 
					
						
							|  |  |  |     npx -y xlsx-cli SheetJSPool.xlsx | 
					
						
							|  |  |  |     rm -f SheetJSPool.xlsx | 
					
						
							|  |  |  |   done | 
					
						
							| 
									
										
										
										
											2024-07-01 03:59:01 +00:00
										 |  |  | done |