#!/bin/bash
# https://docs.sheetjs.com/docs/demos/net/server#worker-threads

cd /tmp
rm -rf sheetjs-worker

mkdir sheetjs-worker
cd sheetjs-worker
echo '{ "type": "module" }' > package.json

npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz express@4.18.2 formidable@2.1.2

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

# this version uses `n` to cycle through node versions
for n in 18 20 22; do
  sudo n $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