UNPKG

stormflow

Version:

StormFlow is a versatile Node.js data management library designed for efficient data management.

3 lines (2 loc) 3.59 kB
import $ from"fs/promises";import j from"path";var p=t=>{if(typeof t!="object"||t===null)return t;if(Array.isArray(t)){let e=new Array(t.length);for(let n=0;n<t.length;n++)e[n]=p(t[n]);return e}else{let e={},n=Object.keys(t);for(let s=0;s<n.length;s++)e[n[s]]=p(t[n[s]]);return e}};var u=t=>t==null?t===null?"null":"undefined":Array.isArray(t)?"array":t instanceof Date?"date":typeof t;var A=(t={})=>{if(u(t)!=="object")throw new Error("defaultConfig must be an object");let e=p(t),n=p(t),s=r=>{let l=Object.keys(e);if(u(r)!=="object")throw new Error('Invalid type of options. Expected type is "object"');Object.keys(r).forEach(i=>{if(!l.includes(i)){let a=l.join('", "');throw new Error(`Invalid "${i}" key in options.\r Allowed keys: "${a}"`)}let o=u(e[i]);if(u(r[i])!==o)throw new Error(`Invalid type of "${i}" key in options. Expected type is ${o}`)})};return{getDefaultConfig(){return p(e)},resetConfig(){n=p(e)},getConfig(){return p(n)},setConfig(r){s(r),Object.assign(n,e,r)},get(r){return n[r]},set(r,l){n[r]=l}}},C=A;import w from"fs/promises";import S from"path";import{promisify as x}from"util";import E from"zlib";var O=x(E.gzip),T=x(E.gunzip),m=async t=>{await w.mkdir(t,{recursive:!0})},F=async(t,e=!1)=>{try{await w.unlink(t),e&&console.log(`Deleted file: ${t}`)}catch(n){if(n.code==="ENOENT")return;e&&console.error(`Failed to delete file: ${t}:`,n)}},P=async(t=[])=>{if(u(t)!=="array")return;let e=[];for(let{fileName:n,fileContent:s}of t){let r=n.replace(/\.sfc$/,""),l=await T(s),i=JSON.parse(l.toString("utf8"));e.push({collectionName:r,collectionData:i})}return e},k=async(t,e)=>{if(!e)return{collectionName:t};let n=`${t}.sfc`,s=JSON.stringify(e),r=await O(s);return{collectionName:t,fileName:n,fileContent:r}};var v=async(t,e=!1)=>{await m(t);let n=await w.readdir(t);for(let s of n)if(s.endsWith(".json")){let r=S.join(t,s),l=S.join(t,s.replace(/\.json$/,".sfc"));try{e&&console.log("[FileStorage]",`Converting ${r} to sfc`);let i=await w.readFile(r,"utf8"),o=await O(i);await w.writeFile(l,o),e&&console.log("[FileStorage]",`Converted and saved as ${l}`),await F(r,e)}catch(i){console.error(`[FileStorage] Error converting ${r} to gzip:`,i)}}};var z=(t={})=>{let e=C({dataFolder:"./data",throttle:100,verbose:!1,...t}),n={},s={},r=async()=>{let{verbose:o,dataFolder:c}=e.getConfig();await m(c),await v(c,o);let f=(await $.readdir(c)).filter(g=>g.endsWith(".sfc"));f.length>0&&console.log("[FileStorage]","Restoring data from files:");let h=await Promise.all(f.map(async g=>{console.log("[FileStorage]",` \u2192 ${g}`);let y=j.join(c,g),d=await $.readFile(y);return{fileName:g,fileContent:d}}));return await P(h)},l=async(o,c)=>{try{let{verbose:a,dataFolder:f}=e.getConfig();await m(f),a&&console.log("[FileStorage]",`Compress data before writing: ${o}`);let{fileName:h,fileContent:g}=await k(o,c),y=j.join(f,`${h}.tmp`),d=j.join(f,h);if(c.length===0){a&&console.log("[FileStorage]",`Removing empty file: ${d}`),await F(d,a);return}a&&console.log("[FileStorage]",`Writing data to temp file: ${y}`),await $.writeFile(y,g),a&&console.log("[FileStorage]",`Move data to final file: ${d}`),await $.rename(y,d),await F(y,a)}catch(a){console.error(`Failed to write ${o}:`,a)}},i=(o,c)=>{let{throttle:a}=e.getConfig();s[o]=c,n[o]||(n[o]=!0,setTimeout(async()=>{let f=s[o];delete s[o],await l(o,f),n[o]=!1,s[o]&&i(o,s[o])},a))};return{init:async()=>({collections:await r()}),insert:async({collectionName:o,collectionData:c})=>i(o,c),update:async({collectionName:o,collectionData:c})=>i(o,c),delete:async({collectionName:o,collectionData:c})=>i(o,c)}},U=z;export{U as default};