database reading

This commit is contained in:
micialware committed 2026-09-14 14:32:38 +03:00
1 parent 68c24dcec5
commit fc8455e353
418 files changed
+674402 -1553

No files matched your search

-19
View File
@@ -1,19 +0,0 @@
# Зависимости
node_modules
# Сборка
dist
dist-ssr
# Логи
*.log
# Окружение
.env
.env.*
# Редактор / ОС
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
+45
View File
@@ -0,0 +1,45 @@
(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))u(s);new MutationObserver(s=>{for(const l of s)if(l.type==="childList")for(const h of l.addedNodes)h.tagName==="LINK"&&h.rel==="modulepreload"&&u(h)}).observe(document,{childList:!0,subtree:!0});function i(s){const l={};return s.integrity&&(l.integrity=s.integrity),s.referrerPolicy&&(l.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?l.credentials="include":s.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function u(s){if(s.ep)return;s.ep=!0;const l=i(s);fetch(s.href,l)}})();const vt="japanese_app.db";async function wt(){return navigator.storage.getDirectory()}async function gn(r){const i=await(await wt()).getFileHandle(vt,{create:!0}),u=i.createSyncAccessHandle;if(typeof u=="function")try{const l=await u.call(i);try{l.truncate(0),l.write(r,{at:0}),l.flush()}finally{l.close()}return}catch{}const s=await i.createWritable();try{await s.truncate(0);const l=new Uint8Array(r.length);l.set(r),await s.write(l)}finally{await s.close()}}async function vn(){const r=await wt();let n;try{n=await r.getFileHandle(vt)}catch{throw new Error("Локальная база не найдена — сначала скачай сохранение")}const i=await n.getFile();if(i.size===0)throw new Error("Локальная база пуста");return new Uint8Array(await i.arrayBuffer())}async function Se(){try{return(await(await(await wt()).getFileHandle(vt)).getFile()).size>0}catch{return!1}}var wn=ArrayBuffer,L=Uint8Array,Ye=Uint16Array,yn=Int16Array,De=Int32Array,ut=function(r,n,i){if(L.prototype.slice)return L.prototype.slice.call(r,n,i);(n==null||n<0)&&(n=0),(i==null||i>r.length)&&(i=r.length);var u=new L(i-n);return u.set(r.subarray(n,i)),u},$e=function(r,n,i,u){if(L.prototype.fill)return L.prototype.fill.call(r,n,i,u);for((i==null||i<0)&&(i=0),(u==null||u>r.length)&&(u=r.length);i<u;++i)r[i]=n;return r},mn=function(r,n,i,u){if(L.prototype.copyWithin)return L.prototype.copyWithin.call(r,n,i,u);for((i==null||i<0)&&(i=0),(u==null||u>r.length)&&(u=r.length);i<u;)r[n++]=r[i++]},bn=["invalid zstd data","window size too large (>2046MB)","invalid block type","FSE accuracy too high","match distance too far back","unexpected EOF"],I=function(r,n,i){var u=new Error(n||bn[r]);if(u.code=r,Error.captureStackTrace&&Error.captureStackTrace(u,I),!i)throw u;return u},Yt=function(r,n,i){for(var u=0,s=0;u<i;++u)s|=r[n++]<<(u<<3);return s},Un=function(r,n){return(r[n]|r[n+1]<<8|r[n+2]<<16|r[n+3]<<24)>>>0},Cn=function(r,n){var i=r[0]|r[1]<<8|r[2]<<16;if(i==3126568&&r[3]==253){var u=r[4],s=u>>5&1,l=u>>2&1,h=u&3,g=u>>6;u&8&&I(0);var y=6-s,E=h==3?4:h,U=Yt(r,y,E);y+=E;var k=g?1<<g:s,F=Yt(r,y,k)+(g==1&&256),m=F;if(!s){var x=1<<10+(r[5]>>3);m=x+(x>>3)*(r[5]&7)}m>2145386496&&I(1);var w=new L((n==1?F||m:n?0:m)+12);return w[0]=1,w[4]=4,w[8]=8,{b:y+k,y:0,l:0,d:U,w:n&&n!=1?n:w.subarray(12),e:m,o:new De(w.buffer,0,3),u:F,c:l,m:Math.min(131072,m)}}else if((i>>4|r[3]<<20)==25481893)return Un(r,4)+8;I(0)},me=function(r){for(var n=0;1<<n<=r;++n);return n-1},Te=function(r,n,i){var u=(n<<3)+4,s=(r[n]&15)+5;s>i&&I(3);for(var l=1<<s,h=l,g=-1,y=-1,E=-1,U=l,k=new wn(512+(l<<2)),F=new yn(k,0,256),m=new Ye(k,0,256),x=new Ye(k,512,l),w=512+(l<<1),$=new L(k,w,l),D=new L(k,w+l);g<255&&h>0;){var X=me(h+1),J=u>>3,se=(1<<X+1)-1,R=(r[J]|r[J+1]<<8|r[J+2]<<16)>>(u&7)&se,b=(1<<X)-1,V=se-h-1,Z=R&b;if(Z<V?(u+=X,R=Z):(u+=X+1,R>b&&(R-=V)),F[++g]=--R,R==-1?(h+=R,$[--U]=g):h-=R,!R)do{var te=u>>3;y=(r[te]|r[te+1]<<8)>>(u&7)&3,u+=2,g+=y}while(y==3)}(g>255||h)&&I(0);for(var Y=0,re=(l>>1)+(l>>3)+3,ne=l-1,G=0;G<=g;++G){var N=F[G];if(N<1){m[G]=-N;continue}for(E=0;E<N;++E){$[Y]=G;do Y=Y+re&ne;while(Y>=U)}}for(Y&&I(0),E=0;E<l;++E){var C=m[$[E]]++,S=D[E]=s-me(C);x[E]=(C<<S)-l}return[u+7>>3,{b:s,s:$,n:D,t:x}]},Mn=function(r,n){var i=0,u=-1,s=new L(292),l=r[n],h=s.subarray(0,256),g=s.subarray(256,268),y=new Ye(s.buffer,268);if(l<128){var E=Te(r,n+1,6),U=E[0],k=E[1];n+=l;var F=U<<3,m=r[n];m||I(0);for(var x=0,w=0,$=k.b,D=$,X=(++n<<3)-8+me(m);X-=$,!(X<F);){var J=X>>3;if(x+=(r[J]|r[J+1]<<8)>>(X&7)&(1<<$)-1,h[++u]=k.s[x],X-=D,X<F)break;J=X>>3,w+=(r[J]|r[J+1]<<8)>>(X&7)&(1<<D)-1,h[++u]=k.s[w],$=k.n[x],x=k.t[x],D=k.n[w],w=k.t[w]}++u>255&&I(0)}else{for(u=l-127;i<u;i+=2){var se=r[++n];h[i]=se>>4,h[i+1]=se&15}++n}var R=0;for(i=0;i<u;++i){var b=h[i];b>11&&I(0),R+=b&&1<<b-1}var V=me(R)+1,Z=1<<V,te=Z-R;for(te&te-1&&I(0),h[u++]=me(te)+1,i=0;i<u;++i){var b=h[i];++g[h[i]=b&&V+1-b]}var Y=new L(Z<<1),re=Y.subarray(0,Z),ne=Y.subarray(Z);for(y[V]=0,i=V;i>0;--i){var G=y[i];$e(ne,i,G,y[i-1]=G+g[i]*(1<<V-i))}for(y[0]!=Z&&I(0),i=0;i<u;++i){var N=h[i];if(N){var C=y[N];$e(re,i,C,y[N]=C+(1<<V-N))}}return[n,{n:ne,b:V,s:re}]},Qn=Te(new L([81,16,99,140,49,198,24,99,12,33,196,24,99,102,102,134,70,146,4]),0,6)[1],En=Te(new L([33,20,196,24,99,140,33,132,16,66,8,33,132,16,66,8,33,68,68,68,68,68,68,Line truncated
<main class="card" aria-labelledby="home-title">
<h2 id="home-title" class="card-title">🏠 Главная</h2>
<p class="card-hint">Локальное сохранение и повторения — всё работает офлайн.</p>
<div id="home-db-status" class="status-bar" role="status">Проверка локальной базы…</div>
<div class="btn-row">
<button id="btn-go-sync" class="btn btn-primary" type="button">📡 К синхронизации</button>
</div>
<div id="home-actions" class="btn-row" hidden>
<button id="btn-start" class="btn" type="button">▶ Начать повторение</button>
</div>
</main>
`;const i=r.querySelector("#home-db-status"),u=r.querySelector("#btn-go-sync"),s=r.querySelector("#home-actions"),l=r.querySelector("#btn-start");u.addEventListener("click",()=>n.goSync()),l.addEventListener("click",()=>{i.textContent="Экран повторений — следующий шаг."}),(async()=>{if(!await Se()){i.textContent="Локальной базы нет. Скачай сохранение на странице «Синхронизация».",s.hidden=!0;return}try{const g=await vn(),y=gt(g);i.textContent=y?`Локальная база на месте: ${(g.length/1024).toFixed(1)} КБ, сигнатура SQLite OK.`:"Файл в OPFS есть, но это не похоже на SQLite — перекачай сохранение.",s.hidden=!y}catch(g){i.textContent=`Не удалось прочитать базу: ${g instanceof Error?g.message:String(g)}`,s.hidden=!0}})()}const Bt=24,Yn=/^[A-Za-z0-9]{24}$/,At="japlearn_sync_token";function Dt(r){return r.trim().replace(/\s+/g,"")}function ye(r){return Yn.test(r)}function Bn(){try{return localStorage.getItem(At)??""}catch{return""}}function dt(r){try{localStorage.setItem(At,r)}catch{}}const er="https://learning.micialware.ru";function Dn(r,n=er){return`${n.replace(/\/+$/,"")}/download/${encodeURIComponent(r)}`}async function Gn(r,n,i=er){const u=Dn(r,i);let s;try{s=await fetch(u,{method:"GET",...n})}catch(h){throw new Error(`Нет связи с сервером: ${h instanceof Error?h.message:String(h)}`)}if(!s.ok)throw s.status===404?new Error("Сохранение не найдено (404). Проверь токен."):new Error(`Сервер ответил ${s.status} ${s.statusText}`);const l=await s.arrayBuffer();if(l.byteLength===0)throw new Error("Сервер вернул пустой файл");return new Uint8Array(l)}function jn(r){r.innerHTML=`
<main class="card" aria-labelledby="sync-title">
<h2 id="sync-title" class="card-title">📡 Синхронизация</h2>
<p class="card-hint">Токен сохранения — 24 символа: латинские буквы и цифры.</p>
<label class="field-label" for="token-input">Токен сохранения</label>
<input
id="token-input"
class="token-input"
type="text"
inputmode="latin"
autocomplete="off"
autocapitalize="off"
autocorrect="off"
spellcheck="false"
maxlength="24"
minlength="24"
placeholder="Например: aB3dEf7hJk9mN2pQr5tUvWx1z"
aria-describedby="token-error token-counter"
/>
<div class="token-meta">
<span id="token-error" class="token-error" role="alert"></span>
<span id="token-counter" class="token-counter" aria-live="polite">0 / 24</span>
</div>
<div class="btn-row">
<button id="btn-download" class="btn" type="button" disabled>📥 Скачать</button>
<button id="btn-upload" class="btn btn-primary" type="button" disabled>📤 Выгрузить</button>
</div>
<p id="status" class="status-bar" role="status">Введите токен из 24 символов</p>
</main>
`;const n=r.querySelector("#token-input"),i=r.querySelector("#token-error"),u=r.querySelector("#token-counter"),s=r.querySelector("#btn-download"),l=r.querySelector("#btn-upload"),h=r.querySelector("#status");function g(m){h.textContent=m,console.log(`[JapLearn] ${m}`)}function y(){return Dt(n.value)}function E(m){s.disabled=m||!ye(y()),l.disabled=!0,n.disabled=m,m||Se().then(x=>{!n.disabled&&ye(y())&&(l.disabled=!x)})}function U(){const m=y(),x=m.length;u.textContent=`${x} / ${Bt}`;const w=ye(m),$=x===0;n.classList.toggle("invalid",!$&&!w),n.setAttribute("aria-invalid",String(!$&&!w)),$?i.textContent="":x!==Bt?i.textContent=`Нужно 24 символа, сейчас ${x}`:i.textContent=w?"":"Только латинские буквы и цифры",s.disabled=!w,w?Se().then(D=>{n.disabled||(l.disabled=!D)}):l.disabled=!0}async function k(){const m=y();if(ye(m)){dt(m),E(!0),g("Скачивание сохранения...");try{const x=await Gn(m);g(`Скачано ${(x.length/1024).toFixed(1)} КБ, распаковка...`);const w=await Zn(x);g(`Распаковано ${(w.length/1024).toFixed(1)} КБ, сохранение в OPFS...`),await gn(w),g(`Готово: база ${(w.length/1024).toFixed(1)} КБ сохранена локально (OPFS).`)}catch(x){g(`Ошибка скачивания: ${x instanceof Error?x.message:String(x)}`)}finally{E(!1),U()}}}n.addEventListener("input",()=>{U()}),n.addEventListener("change",()=>{const m=y();n.value=m,ye(m)&&(dt(m),g("Токен сохранён локально. Можно скачивать или выгружать.")),U()}),s.addEventListener("click",()=>{k()}),l.addEventListener("click",()=>{const m=y();ye(m)&&(dt(m),g("Выгрузка — следующий шаг (POST /upload/stream/{id})."))});const F=Bn();F&&(n.value=F),U(),ye(Dt(F))&&Se().then(m=>{g(m?"Токен восстановлен, локальная база на месте.":"Токен восстановлен. Нажми «Скачать», чтобы получить базу."),U()})}const Wn={home:"Главная",sync:"Синхронизация"};function _e(r){const n=document.getElementById(r);if(!n)throw new Error(`[JapLearn] Не найден элемент #${r}`);return n}const tr=_e("burger-btn"),Be=_e("drawer"),rr=_e("drawer-overlay"),An=_e("page-title"),Gt=_e("page");let yt=!1;function qe(r){yt=r,Be.classList.toggle("open",r),rr.hidden=!r,tr.setAttribute("aria-expanded",String(r)),Be.setAttribute("aria-hidden",String(!r)),document.body.classList.toggle("drawer-open",r)}function ea(r){Be.querySelectorAll(".drawer-btn").forEach(n=>{n.classList.toggle("active",n.dataset.page===r)})}function mt(r){An.textContent=Wn[r],ea(r),r==="home"?Sn(Gt,{goSync:()=>mt("sync")}):jn(Gt)}tr.addEventListener("click",()=>{qe(!yt)});rr.addEventListener("click",()=>{qe(!1)});document.addEventListener("keydown",r=>{r.key==="Escape"&&yt&&qe(!1)});Be.querySelectorAll(".drawer-btn").forEach(r=>{r.addEventListener("click",()=>{const n=r.dataset.page;(n==="home"||n==="sync")&&mt(n),qe(!1)})});qe(!1);mt("home");console.log("[JapLearn] crossOriginIsolated =",window.crossOriginIsolated);
+1
View File
@@ -0,0 +1 @@
:root{font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.5;color:#1e1b2e;background:#f4f1fa}*{box-sizing:border-box}body{margin:0;min-height:100dvh;display:flex;justify-content:center;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)}#app{width:100%;max-width:480px;padding:24px 16px 32px;display:flex;flex-direction:column;gap:16px}.app-header h1{margin:0;font-size:1.75rem;letter-spacing:.02em}.app-subtitle{margin:4px 0 0;color:#6d6390}.top-bar{display:flex;align-items:center;gap:12px}.burger-btn{width:44px;height:44px;border:2px solid #d9d2f0;border-radius:12px;background:#fff;cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;touch-action:manipulation;flex:none}.burger-btn span{display:block;width:20px;height:2px;border-radius:2px;background:#4c446b}.burger-btn[aria-expanded=true]{border-color:#7c3aed}.top-bar-title h1{margin:0;font-size:1.4rem;line-height:1.2}.top-bar-title p{margin:0;font-size:.9rem;color:#6d6390}.top-bar-spacer{flex:1}.app-content{display:flex;flex-direction:column;gap:16px}.drawer-overlay{position:fixed;inset:0;background:#1e1b2e73;z-index:40}.drawer-overlay[hidden]{display:none}.drawer{position:fixed;top:0;left:0;bottom:0;width:min(300px,85vw);background:#fff;z-index:50;transform:translate(-105%);transition:transform .22s ease;display:flex;flex-direction:column;gap:8px;padding:20px 14px;box-shadow:8px 0 32px #1e1b2e2e}.drawer.open{transform:translate(0)}.drawer-header{padding:4px 8px 14px;border-bottom:1px solid #eee9fb;margin-bottom:8px}.drawer-logo{font-size:1.3rem;font-weight:800;color:#7c3aed}.drawer-subtitle{font-size:.9rem;color:#6d6390}.drawer-btn{border:none;background:transparent;text-align:left;font-size:1.05rem;font-weight:600;color:#1e1b2e;padding:13px 12px;border-radius:12px;cursor:pointer;touch-action:manipulation}.drawer-btn.active{background:#f1eafe;color:#6d28d9}.drawer-btn:active{background:#e9defc}body.drawer-open{overflow:hidden}.card{background:#fff;border-radius:16px;padding:20px 16px;box-shadow:0 8px 24px #7c3aed1f;display:flex;flex-direction:column;gap:12px}.card-title{margin:0;font-size:1.25rem}.card-hint{margin:0;color:#6d6390;font-size:.95rem}.field-label{font-weight:600;font-size:.95rem}.token-input{width:100%;padding:14px 12px;font-size:1.05rem;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.04em;border:2px solid #d9d2f0;border-radius:12px;outline:none}.token-input:focus{border-color:#7c3aed}.token-input.invalid{border-color:#dc2626;background:#fef2f2}.token-meta{display:flex;justify-content:space-between;align-items:baseline;gap:8px;min-height:1.4em}.token-error{color:#dc2626;font-size:.9rem}.token-counter{color:#6d6390;font-variant-numeric:tabular-nums;white-space:nowrap}.btn-row{display:flex;gap:12px}.btn{flex:1;padding:14px 12px;font-size:1rem;font-weight:600;border-radius:12px;border:2px solid #7c3aed;background:#fff;color:#7c3aed;cursor:pointer;touch-action:manipulation}.btn-primary{background:#7c3aed;color:#fff}.btn:disabled{opacity:.4;cursor:not-allowed}.btn:not(:disabled):active{transform:scale(.98)}.status-bar{margin:0;padding:10px 12px;border-radius:10px;background:#f4f1fa;color:#4c446b;font-size:.95rem;word-break:break-word}
+41
View File
@@ -0,0 +1,41 @@
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="theme-color" content="#7c3aed" />
<title>JapLearn — интервальные повторения</title>
<script type="module" crossorigin src="/assets/index-17GvxYKC.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DhXfM6jc.css">
</head>
<body>
<div id="app">
<header class="top-bar">
<button id="burger-btn" class="burger-btn" type="button" aria-label="Меню" aria-expanded="false" aria-controls="drawer">
<span></span>
<span></span>
<span></span>
</button>
<div class="top-bar-title">
<h1>JapLearn</h1>
<p id="page-title">Главная</p>
</div>
<div class="top-bar-spacer"></div>
</header>
<div id="drawer-overlay" class="drawer-overlay" hidden></div>
<nav id="drawer" class="drawer" aria-label="Навигация" aria-hidden="true">
<div class="drawer-header">
<div class="drawer-logo">JapLearn</div>
<div class="drawer-subtitle">Интервальные повторения</div>
</div>
<button class="drawer-btn active" data-page="home" type="button">🏠 Главная</button>
<button class="drawer-btn" data-page="sync" type="button">📡 Синхронизация</button>
</nav>
<div id="page" class="app-content">
<!-- Страницы рендерятся сюда -->
</div>
</div>
</body>
</html>
+24 -49
View File
@@ -2,64 +2,39 @@
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Cross-Origin-Embedder-Policy" content="require-corp" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="theme-color" content="#7c3aed" />
<title>JapLearn — интервальные повторения</title>
</head>
<body>
<main id="app">
<header class="app-header">
<div id="app">
<header class="top-bar">
<button id="burger-btn" class="burger-btn" type="button" aria-label="Меню" aria-expanded="false" aria-controls="drawer">
<span></span>
<span></span>
<span></span>
</button>
<div class="top-bar-title">
<h1>JapLearn</h1>
<p class="subtitle">Интервальные повторения · офлайн-первая</p>
<p id="page-title">Главная</p>
</div>
<div class="top-bar-spacer"></div>
</header>
<section class="card" aria-labelledby="sync-title">
<h2 id="sync-title">Сохранение</h2>
<p class="card-note">
База данных хранится локально на устройстве. Токен связывает её
с копией на сервере — скачивайте и выгружайте файл по мере
необходимости.
</p>
<form id="sync-form" novalidate>
<div class="field">
<label for="save-token">Токен сохранения</label>
<input
id="save-token"
name="save-token"
type="text"
maxlength="24"
autocomplete="off"
autocapitalize="characters"
spellcheck="false"
placeholder="24 буквы или цифры"
aria-describedby="token-hint token-error"
/>
<p id="token-hint" class="hint">
Последовательность из 24 символов: латинские буквы (A–Z)
и цифры (0–9).
</p>
<p id="token-error" class="error" hidden>
Нужно ровно 24 символа — латинские буквы и цифры, без пробелов
и знаков.
</p>
<div id="drawer-overlay" class="drawer-overlay" hidden></div>
<nav id="drawer" class="drawer" aria-label="Навигация" aria-hidden="true">
<div class="drawer-header">
<div class="drawer-logo">JapLearn</div>
<div class="drawer-subtitle">Интервальные повторения</div>
</div>
<button class="drawer-btn active" data-page="home" type="button">🏠 Главная</button>
<button class="drawer-btn" data-page="sync" type="button">📡 Синхронизация</button>
</nav>
<div class="actions">
<button type="button" id="btn-download" class="btn btn-primary" disabled>
Скачать
</button>
<button type="button" id="btn-upload" class="btn btn-secondary" disabled>
Выгрузить
</button>
<div id="page" class="app-content">
<!-- Страницы рендерятся сюда -->
</div>
</div>
</form>
<p id="sync-status" class="status" role="status" aria-live="polite"></p>
<p id="db-state" class="status" role="status" aria-live="polite"></p>
</section>
<p id="sqlite-status" class="footer-status"></p>
</main>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../esbuild/bin/esbuild
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../nanoid/bin/nanoid.cjs
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../rollup/dist/bin/rollup
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../@sqlite.org/sqlite-wasm/bin/index.js
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../typescript/bin/tsc
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../typescript/bin/tsserver
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../vite/bin/vite.js
+374
View File
@@ -0,0 +1,374 @@
{
"name": "jap_web",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"node_modules/@esbuild/linux-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
"integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@hpcc-js/wasm-zstd": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/@hpcc-js/wasm-zstd/-/wasm-zstd-1.16.0.tgz",
"integrity": "sha512-+F+GRnqsbcVvr6vlSivB+YYOYNaDt21CAwfp0ru9mPeYeVPX6YFCu8fZaARuyklZZ9/9uUAs5qymEfnXKBZl8g==",
"license": "Apache-2.0"
},
"node_modules/@napi-rs/lzma-linux-x64-gnu": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz",
"integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==",
"cpu": [
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^22.20 || ^24.12 || >=25"
}
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.63.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.63.2.tgz",
"integrity": "sha512-bcq2h2pkKmH2po4cZV8VWzO4lL40STyu/nLoFpYMQp9C2tCVNTdcVv86MwSsn3D5s1FBe2Ty1atqvVAUTMimNg==",
"cpu": [
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@sqlite.org/sqlite-wasm": {
"version": "3.50.4-build1",
"resolved": "https://registry.npmjs.org/@sqlite.org/sqlite-wasm/-/sqlite-wasm-3.50.4-build1.tgz",
"integrity": "sha512-Qig2Wso7gPkU1PtXwFzndh+CTRzrIFxVGqv6eCetjU7YqxlHItj+GvQYwYTppCRgAPawtRN/4AJcEgB9xDHGug==",
"license": "Apache-2.0",
"bin": {
"sqlite-wasm": "bin/index.js"
}
},
"node_modules/@types/estree": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
"integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
"dev": true,
"license": "MIT"
},
"node_modules/esbuild": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
"integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.28.2",
"@esbuild/android-arm": "0.28.2",
"@esbuild/android-arm64": "0.28.2",
"@esbuild/android-x64": "0.28.2",
"@esbuild/darwin-arm64": "0.28.2",
"@esbuild/darwin-x64": "0.28.2",
"@esbuild/freebsd-arm64": "0.28.2",
"@esbuild/freebsd-x64": "0.28.2",
"@esbuild/linux-arm": "0.28.2",
"@esbuild/linux-arm64": "0.28.2",
"@esbuild/linux-ia32": "0.28.2",
"@esbuild/linux-loong64": "0.28.2",
"@esbuild/linux-mips64el": "0.28.2",
"@esbuild/linux-ppc64": "0.28.2",
"@esbuild/linux-riscv64": "0.28.2",
"@esbuild/linux-s390x": "0.28.2",
"@esbuild/linux-x64": "0.28.2",
"@esbuild/netbsd-arm64": "0.28.2",
"@esbuild/netbsd-x64": "0.28.2",
"@esbuild/openbsd-arm64": "0.28.2",
"@esbuild/openbsd-x64": "0.28.2",
"@esbuild/openharmony-arm64": "0.28.2",
"@esbuild/sunos-x64": "0.28.2",
"@esbuild/win32-arm64": "0.28.2",
"@esbuild/win32-ia32": "0.28.2",
"@esbuild/win32-x64": "0.28.2"
}
},
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/nanoid": {
"version": "3.3.19",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",
"integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
"node_modules/picomatch": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
"integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/postcss": {
"version": "8.5.28",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",
"integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.18",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/rollup": {
"version": "4.63.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.63.2.tgz",
"integrity": "sha512-l5eyksV4tPBj6lJyEa37YzIOCSOV7lkZzEHUdpjWZbtD7wTcFYmEYXSgm5bT4vV+dZLb9rBG1W9GROOG4NS4Ew==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.9"
},
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=18.0.0",
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@napi-rs/lzma-linux-x64-gnu": "1.5.1",
"@rollup/rollup-android-arm-eabi": "4.63.2",
"@rollup/rollup-android-arm64": "4.63.2",
"@rollup/rollup-darwin-arm64": "4.63.2",
"@rollup/rollup-darwin-x64": "4.63.2",
"@rollup/rollup-freebsd-arm64": "4.63.2",
"@rollup/rollup-freebsd-x64": "4.63.2",
"@rollup/rollup-linux-arm-gnueabihf": "4.63.2",
"@rollup/rollup-linux-arm-musleabihf": "4.63.2",
"@rollup/rollup-linux-arm64-gnu": "4.63.2",
"@rollup/rollup-linux-arm64-musl": "4.63.2",
"@rollup/rollup-linux-loong64-gnu": "4.63.2",
"@rollup/rollup-linux-loong64-musl": "4.63.2",
"@rollup/rollup-linux-ppc64-gnu": "4.63.2",
"@rollup/rollup-linux-ppc64-musl": "4.63.2",
"@rollup/rollup-linux-riscv64-gnu": "4.63.2",
"@rollup/rollup-linux-riscv64-musl": "4.63.2",
"@rollup/rollup-linux-s390x-gnu": "4.63.2",
"@rollup/rollup-linux-x64-gnu": "4.63.2",
"@rollup/rollup-linux-x64-musl": "4.63.2",
"@rollup/rollup-openbsd-x64": "4.63.2",
"@rollup/rollup-openharmony-arm64": "4.63.2",
"@rollup/rollup-win32-arm64-msvc": "4.63.2",
"@rollup/rollup-win32-ia32-msvc": "4.63.2",
"@rollup/rollup-win32-x64-gnu": "4.63.2",
"@rollup/rollup-win32-x64-msvc": "4.63.2",
"fsevents": "~2.3.2"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/tinyglobby": {
"version": "0.2.17",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
"integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
"picomatch": "^4.0.4"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/vite": {
"version": "7.3.6",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz",
"integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.27.0 || ^0.28.0",
"fdir": "^6.5.0",
"picomatch": "^4.0.3",
"postcss": "^8.5.6",
"rollup": "^4.43.0",
"tinyglobby": "^0.2.15"
},
"bin": {
"vite": "bin/vite.js"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"funding": {
"url": "https://github.com/vitejs/vite?sponsor=1"
},
"optionalDependencies": {
"fsevents": "~2.3.3"
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
"lightningcss": "^1.21.0",
"sass": "^1.70.0",
"sass-embedded": "^1.70.0",
"stylus": ">=0.54.8",
"sugarss": "^5.0.0",
"terser": "^5.16.0",
"tsx": "^4.8.1",
"yaml": "^2.4.2"
},
"peerDependenciesMeta": {
"@types/node": {
"optional": true
},
"jiti": {
"optional": true
},
"less": {
"optional": true
},
"lightningcss": {
"optional": true
},
"sass": {
"optional": true
},
"sass-embedded": {
"optional": true
},
"stylus": {
"optional": true
},
"sugarss": {
"optional": true
},
"terser": {
"optional": true
},
"tsx": {
"optional": true
},
"yaml": {
"optional": true
}
}
}
}
}
+1283
View File
File diff suppressed because it is too large. Load diff
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../node_modules/fzstd/esm/index.mjs", "../../build/packages/zstd/zstdlib.js", "../../build/packages/zstd/zstdlib.wasm", "../../@hpcc-js/util/src/wasm-library.ts", "../../@hpcc-js/wasm-zstd/src/zstd.ts"],
"sourcesContent": ["// Some numerical data is initialized as -1 even when it doesn't need initialization to help the JIT infer types\n// aliases for shorter compressed code (most minifers don't do this)\nvar ab = ArrayBuffer, u8 = Uint8Array, u16 = Uint16Array, i16 = Int16Array, u32 = Uint32Array, i32 = Int32Array;\nvar slc = function (v, s, e) {\n if (u8.prototype.slice)\n return u8.prototype.slice.call(v, s, e);\n if (s == null || s < 0)\n s = 0;\n if (e == null || e > v.length)\n e = v.length;\n var n = new u8(e - s);\n n.set(v.subarray(s, e));\n return n;\n};\nvar fill = function (v, n, s, e) {\n if (u8.prototype.fill)\n return u8.prototype.fill.call(v, n, s, e);\n if (s == null || s < 0)\n s = 0;\n if (e == null || e > v.length)\n e = v.length;\n for (; s < e; ++s)\n v[s] = n;\n return v;\n};\nvar cpw = function (v, t, s, e) {\n if (u8.prototype.copyWithin)\n return u8.prototype.copyWithin.call(v, t, s, e);\n if (s == null || s < 0)\n s = 0;\n if (e == null || e > v.length)\n e = v.length;\n while (s < e) {\n v[t++] = v[s++];\n }\n};\n/**\n * Codes for errors generated within this library\n */\nexport var ZstdErrorCode = {\n InvalidData: 0,\n WindowSizeTooLarge: 1,\n InvalidBlockType: 2,\n FSEAccuracyTooHigh: 3,\n DistanceTooFarBack: 4,\n UnexpectedEOF: 5\n};\n// error codes\nvar ec = [\n 'invalid zstd data',\n 'window size too large (>2046MB)',\n 'invalid block type',\n 'FSE accuracy too high',\n 'match distance too far back',\n 'unexpected EOF'\n];\nvar err = function (ind, msg, nt) {\n var e = new Error(msg || ec[ind]);\n e.code = ind;\n if (Error.captureStackTrace)\n Error.captureStackTrace(e, err);\n if (!nt)\n throw e;\n return e;\n};\nvar rb = function (d, b, n) {\n var i = 0, o = 0;\n for (; i < n; ++i)\n o |= d[b++] << (i << 3);\n return o;\n};\nvar b4 = function (d, b) { return (d[b] | (d[b + 1] << 8) | (d[b + 2] << 16) | (d[b + 3] << 24)) >>> 0; };\n// read Zstandard frame header\nvar rzfh = function (dat, w) {\n var n3 = dat[0] | (dat[1] << 8) | (dat[2] << 16);\n if (n3 == 0x2FB528 && dat[3] == 253) {\n // Zstandard\n var flg = dat[4];\n // single segment checksum dict flag frame content flag\n var ss = (flg >> 5) & 1, cc = (flg >> 2) & 1, df = flg & 3, fcf = flg >> 6;\n if (flg & 8)\n err(0);\n // byte\n var bt = 6 - ss;\n // dict bytes\n var db = df == 3 ? 4 : df;\n // dictionary id\n var di = rb(dat, bt, db);\n bt += db;\n // frame size bytes\n var fsb = fcf ? (1 << fcf) : ss;\n // frame source size\n var fss = rb(dat, bt, fsb) + ((fcf == 1) && 256);\n // window size\n var ws = fss;\n if (!ss) {\n // window descriptor\n var wb = 1 << (10 + (dat[5] >> 3));\n ws = wb + (wb >> 3) * (dat[5] & 7);\n }\n if (ws > 2145386496)\n err(1);\n var buf = new u8((w == 1 ? (fss || ws) : w ? 0 : ws) + 12);\n buf[0] = 1, buf[4] = 4, buf[8] = 8;\n return {\n b: bt + fsb,\n y: 0,\n l: 0,\n d: di,\n w: (w && w != 1) ? w : buf.subarray(12),\n e: ws,\n o: new i32(buf.buffer, 0, 3),\n u: fss,\n c: cc,\n m: Math.min(131072, ws)\n };\n }\n else if (((n3 >> 4) | (dat[3] << 20)) == 0x184D2A5) {\n // skippable\n return b4(dat, 4) + 8;\n }\n err(0);\n};\n// most significant bit for nonzero\nvar msb = function (val) {\n var bits = 0;\n for (; (1 << bits) <= val; ++bits)\n ;\n return bits - 1;\n};\n// read finite state entropy\nvar rfse = function (dat, bt, mal) {\n // table pos\n var tpos = (bt << 3) + 4;\n // accuracy log\n var al = (dat[bt] & 15) + 5;\n if (al > mal)\n err(3);\n // size\n var sz = 1 << al;\n // probabilities symbols repeat index high threshold\n var probs = sz, sym = -1, re = -1, i = -1, ht = sz;\n // optimization: single allocation is much faster\n var buf = new ab(512 + (sz << 2));\n var freq = new i16(buf, 0, 256);\n // same view as freq\n var dstate = new u16(buf, 0, 256);\n var nstate = new u16(buf, 512, sz);\n var bb1 = 512 + (sz << 1);\n var syms = new u8(buf, bb1, sz);\n var nbits = new u8(buf, bb1 + sz);\n while (sym < 255 && probs > 0) {\n var bits = msb(probs + 1);\n var cbt = tpos >> 3;\n // mask\n var msk = (1 << (bits + 1)) - 1;\n var val = ((dat[cbt] | (dat[cbt + 1] << 8) | (dat[cbt + 2] << 16)) >> (tpos & 7)) & msk;\n // mask (1 fewer bit)\n var msk1fb = (1 << bits) - 1;\n // max small value\n var msv = msk - probs - 1;\n // small value\Line truncated
"mappings": ";AAEA,IAAIA,KAAK;AAAT,IAAsBC,IAAK;AAA3B,IAAuCC,KAAM;AAA7C,IAA0DC,KAAM;AAAhE,IAA+FC,KAAM;AAArG,IACIC,KAAM,SAAUC,IAAGC,GAAGC,GAAG;AACzB,MAAIP,EAAG,UAAU,MACb,QAAOA,EAAG,UAAU,MAAM,KAAKK,IAAGC,GAAGC,CAAC;AAAA,GACtCD,KAAK,QAAQA,IAAI,OACjBA,IAAI,KACJC,KAAK,QAAQA,IAAIF,GAAE,YACnBE,IAAIF,GAAE;AACV,MAAIG,IAAI,IAAIR,EAAGO,IAAID,CAAC;AACpB,SAAAE,EAAE,IAAIH,GAAE,SAASC,GAAGC,CAAC,CAAC,GACfC;AACX;AAXA,IAYIC,KAAO,SAAUJ,IAAGG,GAAG,GAAGD,GAAG;AAC7B,MAAIP,EAAG,UAAU,KACb,QAAOA,EAAG,UAAU,KAAK,KAAKK,IAAGG,GAAG,GAAGD,CAAC;AAK5C,QAJI,KAAK,QAAQ,IAAI,OACjB,IAAI,KACJA,KAAK,QAAQA,IAAIF,GAAE,YACnBE,IAAIF,GAAE,SACH,IAAIE,GAAG,EAAE,EACZF,CAAAA,GAAE,CAAC,IAAIG;AACX,SAAOH;AACX;AAtBA,IAuBIK,KAAM,SAAUL,IAAGM,GAAG,GAAGJ,GAAG;AAC5B,MAAIP,EAAG,UAAU,WACb,QAAOA,EAAG,UAAU,WAAW,KAAKK,IAAGM,GAAG,GAAGJ,CAAC;AAKlD,QAJI,KAAK,QAAQ,IAAI,OACjB,IAAI,KACJA,KAAK,QAAQA,IAAIF,GAAE,YACnBE,IAAIF,GAAE,SACH,IAAIE,IACPF,CAAAA,GAAEM,GAAG,IAAIN,GAAE,GAAG;AAEtB;AAaA,IAAIO,KAAK,CACL,qBACA,mCACA,sBACA,yBACA,+BACA,gBACJ;AAPA,IAQIC,IAAM,SAAUC,IAAKC,GAAKC,GAAI;AAC9B,MAAIT,IAAI,IAAI,MAAMQ,KAAOH,GAAGE,EAAG,CAAC;AAIhC,MAHAP,EAAE,OAAOO,IACL,MAAM,qBACN,MAAM,kBAAkBP,GAAGM,CAAG,GAC9B,CAACG,EACD,OAAMT;AACV,SAAOA;AACX;AAhBA,IAiBIU,KAAK,SAAUC,IAAGC,GAAGX,GAAG;AAExB,WADIY,IAAI,GAAGC,IAAI,GACRD,IAAIZ,GAAG,EAAEY,EACZC,MAAKH,GAAEC,GAAG,MAAMC,KAAK;AACzB,SAAOC;AACX;AAtBA,IAuBIC,KAAK,SAAUJ,IAAGC,GAAG;AAAE,UAAQD,GAAEC,CAAC,IAAKD,GAAEC,IAAI,CAAC,KAAK,IAAMD,GAAEC,IAAI,CAAC,KAAK,KAAOD,GAAEC,IAAI,CAAC,KAAK,QAAS;AAAG;AAvBxG,IAyBII,KAAO,SAAUC,IAAKC,GAAG;AACzB,MAAIC,IAAKF,GAAI,CAAC,IAAKA,GAAI,CAAC,KAAK,IAAMA,GAAI,CAAC,KAAK;AAC7C,MAAIE,KAAM,WAAYF,GAAI,CAAC,KAAK,KAAK;AAEjC,QAAIG,IAAMH,GAAI,CAAC,GAEXI,IAAMD,KAAO,IAAK,GAAGE,IAAMF,KAAO,IAAK,GAAGG,IAAKH,IAAM,GAAGI,IAAMJ,KAAO;AACrEA,QAAM,KACNd,EAAI,CAAC;AAET,QAAImB,IAAK,IAAIJ,GAETK,IAAKH,KAAM,IAAI,IAAIA,GAEnBI,IAAKjB,GAAGO,IAAKQ,GAAIC,CAAE;AACvBD,SAAMC;AAEN,QAAIE,IAAMJ,IAAO,KAAKA,IAAOH,GAEzBQ,IAAMnB,GAAGO,IAAKQ,GAAIG,CAAG,KAAMJ,KAAO,KAAM,MAExCM,IAAKD;AACT,QAAI,CAACR,GAAI;AAEL,UAAIU,IAAK,KAAM,MAAMd,GAAI,CAAC,KAAK;AAC/Ba,UAAKC,KAAMA,KAAM,MAAMd,GAAI,CAAC,IAAI;IACpC;AACIa,QAAK,cACLxB,EAAI,CAAC;AACT,QAAI0B,IAAM,IAAIvC,GAAIyB,KAAK,IAAKW,KAAOC,IAAMZ,IAAI,IAAIY,KAAM,EAAE;AACzD,WAAAE,EAAI,CAAC,IAAI,GAAGA,EAAI,CAAC,IAAI,GAAGA,EAAI,CAAC,IAAI,GAC1B,EACH,GAAGP,IAAKG,GACR,GAAG,GACH,GAAG,GACH,GAAGD,GACH,GAAIT,KAAKA,KAAK,IAAKA,IAAIc,EAAI,SAAS,EAAE,GACtC,GAAGF,GACH,GAAG,IAAIlC,GAAIoC,EAAI,QAAQ,GAAG,CAAC,GAC3B,GAAGH,GACH,GAAGP,GACH,GAAG,KAAK,IAAI,QAAQQ,CAAE,EAC1B;EACJ,YACWX,KAAM,IAAMF,GAAI,CAAC,KAAK,OAAQ,SAErC,QAAOF,GAAGE,IAAK,CAAC,IAAI;AAExBX,IAAI,CAAC;AACT;AA1EA,IA4EI2B,KAAM,SAAUC,IAAK;AAErB,WADIC,IAAO,GACH,KAAKA,KAASD,IAAK,EAAEC,EACzB;AACJ,SAAOA,IAAO;AAClB;AAjFA,IAmFIC,KAAO,SAAUnB,IAAKQ,GAAIY,GAAK;AAE/B,MAAIC,KAAQb,KAAM,KAAK,GAEnBc,KAAMtB,GAAIQ,CAAE,IAAI,MAAM;AACtBc,MAAKF,KACL/B,EAAI,CAAC;AAcT,WAZIkC,IAAK,KAAKD,GAEVE,IAAQD,GAAIE,IAAM,IAAIC,IAAK,IAAI9B,IAAI,IAAI+B,IAAKJ,GAE5CR,IAAM,IAAIxC,GAAG,OAAOgD,KAAM,EAAE,GAC5BK,IAAO,IAAIlD,GAAIqC,GAAK,GAAG,GAAG,GAE1Bc,IAAS,IAAIpD,GAAIsC,GAAK,GAAG,GAAG,GAC5Be,IAAS,IAAIrD,GAAIsC,GAAK,KAAKQ,CAAE,GAC7BQ,IAAM,OAAOR,KAAM,IACnBS,IAAO,IAAIxD,EAAGuC,GAAKgB,GAAKR,CAAE,GAC1BU,KAAQ,IAAIzD,EAAGuC,GAAKgB,IAAMR,CAAE,GACzBE,IAAM,OAAOD,IAAQ,KAAG;AAC3B,QAAIN,IAAOF,GAAIQ,IAAQ,CAAC,GACpBU,IAAMb,KAAQ,GAEdc,MAAO,KAAMjB,IAAO,KAAM,GAC1BD,KAAQjB,GAAIkC,CAAG,IAAKlC,GAAIkC,IAAM,CAAC,KAAK,IAAMlC,GAAIkC,IAAM,CAAC,KAAK,QAASb,IAAO,KAAMc,IAEhFC,KAAU,KAAKlB,KAAQ,GAEvBmB,IAAMF,KAAMX,IAAQ,GAEpBc,IAAOrB,IAAMmB;AAejB,QAdIE,IAAOD,KACPhB,KAAQH,GAAMD,IAAMqB,MAEpBjB,KAAQH,IAAO,GACXD,IAAMmB,MACNnB,KAAOoB,KAEfT,EAAK,EAAEH,CAAG,IAAI,EAAER,GACZA,KAAO,MACPO,KAASP,GACTe,EAAK,EAAEL,CAAE,IAAIF,KAGbD,KAASP,GACT,CAACA,EACD,IAAG;AAEC,UAAIsB,IAAMlB,KAAQ;AAClBK,WAAO1B,GAAIuC,CAAG,IAAKvC,GAAIuC,IAAM,CAAC,KAAK,OAAQlB,IAAO,KAAM,GACxDA,KAAQ,GACRI,KAAOC;IACX,SAASA,KAAM;EAEvB;AAAA,GACID,IAAM,OAAOD,MACbnC,EAAI,CAAC;AAMT,WALImD,IAAS,GAETC,KAASlB,KAAM,MAAMA,KAAM,KAAK,GAEhCmB,KAAQnB,IAAK,GACRzC,IAAI,GAAGA,KAAK2C,GAAK,EAAE3C,GAAG;AAC3B,QAAI6D,IAAKf,EAAK9C,CAAC;AACf,QAAI6D,IAAK,GAAG;AACRd,QAAO/C,CAAC,IAAI,CAAC6D;AACb;IACJ;AAEA,SAAK/C,IAAI,GAAGA,IAAI+C,GAAI,EAAE/C,GAAG;AACrBoC,QAAKQ,CAAM,IAAI1D;AACf;AACI0D,YAAUA,IAASC,IAASC;aACvBF,KAAUb;IACvB;EACJ;AAIA,OAFIa,KACAnD,EAAI,CAAC,GACJO,IAAI,GAAGA,IAAI2B,GAAI,EAAE3B,GAAG;AAErB,QAAIgD,IAAKf,EAAOG,EAAKpC,CAAC,CAAC,KAEnBiD,IAAKZ,GAAMrC,CAAC,IAAI0B,IAAKN,GAAI4B,CAAE;AAC/Bd,MAAOlC,CAAC,KAAKgD,KAAMC,KAAMtB;EAC7B;AACA,SAAO,CAAEF,IAAO,KAAM,GAAG,EACjB,GAAGC,GACH,GAAGU,GACH,GAAGC,IACH,GAAGH,EACP,CAAC;AACT;AAhLA,IAkLIgB,KAAM,SAAU9C,IAAKQ,GAAI;AAEzB,MAAIZ,IAAI,GAAGmD,IAAK,IAEZhC,IAAM,IAAIvC,EAAG,GAAG,GAAGwE,IAAKhD,GAAIQ,CAAE,GAE9ByC,IAAKlC,EAAI,SAAS,GAAG,GAAG,GAExBmC,IAAKnC,EAAI,SAAS,KAAK,GAAG,GAE1BoC,IAAK,IAAI1E,GAAIsC,EAAI,QAAQ,GAAG;AAEhC,MAAIiC,IAAK,KAAK;AAEV,QAAII,IAAKjC,GAAKnB,IAAKQ,IAAK,GAAG,CAAC,GAAG6C,IAAMD,EAAG,CAAC,GAAGE,IAAMF,EAAG,CAAC;AACtD5C,SAAMwC;AACN,QAAIO,IAAOF,KAAO,GAEdG,IAAKxD,GAAIQ,CAAE;AACVgD,SACDnE,EAAI,CAAC;AAMT,aAJIoE,IAAM,GAAGC,IAAM,GAAGC,IAAOL,EAAI,GAAGM,KAAOD,GAGvCE,KAAQ,EAAErD,KAAM,KAAK,IAAIQ,GAAIwC,CAAE,GAE/BK,KAAQF,GACLine truncated
"names": ["ab", "u8", "u16", "i16", "i32", "slc", "v", "s", "e", "n", "fill", "cpw", "t", "ec", "err", "ind", "msg", "nt", "rb", "d", "b", "i", "o", "b4", "rzfh", "dat", "w", "n3", "flg", "ss", "cc", "df", "fcf", "bt", "db", "di", "fsb", "fss", "ws", "wb", "buf", "msb", "val", "bits", "rfse", "mal", "tpos", "al", "sz", "probs", "sym", "re", "ht", "freq", "dstate", "nstate", "bb1", "syms", "nbits", "cbt", "msk", "msk1fb", "msv", "sval", "rbt", "sympos", "sstep", "smask", "sf", "ns", "nb", "rhu", "wc", "hb", "hw", "rc", "ri", "_a", "ebt", "fdt", "epos", "lb", "st1", "st2", "btr1", "btr2", "fpos", "byte", "wes", "wt", "mb", "ts", "rem", "hbuf", "pv", "code", "dllt", "dmlt", "doct", "b2bl", "len", "bl", "llb", "llbl", "mlb", "mlbl", "dhu", "out", "hu", "eb", "st", "btr", "pos", "dhu4", "sz1", "sz2", "sz3", "rzb", "b0", "btype", "b3", "lbt", "lss", "lcs", "s4", "spl", "hud", "scm", "dts", "md", "rbuf", "_b", "mlt", "oct", "llt", "spos", "oubt", "lst", "ost", "mst", "llc", "lbtr", "mlc", "mbtr", "ofc", "obtr", "ofp", "off", "ml", "ll", "idx", "stin", "bs", "cct", "bufs", "ol", "chk", "decompress", "blk", "cpp", "moduleArg", "Module", "quit_", "status", "toThrow", "_scriptName", "scriptDirectory", "locateFile", "path", "readAsync", "wasmBinary", "ABORT", "filename", "runtimeInitialized", "getMemoryBuffer", "preRun", "initRuntime", "postRun", "what", "___trap", "getBinarySync", "file", "readBinary", "getWasmBinary", "binaryFile", "response", "imports", "binary", "instance", "instantiateAsync", "isFileURI", "instantiationResult", "getWasmImports", "wasmImports", "createWasm", "wasmExports", "assignWasmExports", "receiveInstantiationResult", "result", "receiveInstance", "info", "wasmBinaryFile", "exports", "HEAP8", "getCppExceptionTag", "___cpp_exception", "getCppExceptionThrownObjectFromWebAssemblyException", "unwind_header", "ex", "___thrown_object_from_unwind_exception", "stackSave", "_emscripten_stack_get_current", "stackRestore", "__emscripten_stack_restore", "stackAlloc", "UTF8Decoder", "findStringEnd", "maxBytesToRead", "ignoreNul", "maxIdx", "heapOrArray", "endPtr", "u0", "u2", "u1", "ch", "str", "HEAPU8", "UTF8ToString", "ptr", "UTF8ArrayToString", "HEAPU32", "getExceptionMessageCommon", "sp", "type_addr_addr", "message_addr_addr", "___get_exception_message", "type_addr", "type", "message", "message_addr", "_free", "getExceptionMessage", "___throw_exception_with_stack_trace", "__abort_js", "abort", "structRegistrations", "runDestructors", "del", "destructors", "readPointer", "pointer", "awaitingDependencies", "InternalError", "throwInternalError", "whenDependentTypesAreResolved", "getTypeConverters", "myTypes", "onComplete", "typeConverters", "myTypeConverters", "registerType", "dependentTypes", "registered", "registeredTypes", "unregisteredTypes", "dt", "__embind_finalize_value_object", "structType", "fieldRecords", "reg", "fieldTypes", "fields", "getter", "field", "setterArgumentType", "setter", "getterContext", "rv", "fieldName", "rawConstructor", "rawDestructor", "AsciiToString", "BindingError", "sharedRegisterType", "rawType", "registeredInstance", "options", "callbacks", "HEAP16", "HEAPU16", "HEAP32", "HEAP64", "HEAPU64", "integerReadValueFromPointer", "width", "signed", "name", "primitiveType", "size", "minRange", "maxRange", "isUnsignedType", "fromWireType", "value", "__embind_register_bool", "trueValue", "falseValue", "shallowCopyInternalPointer", "obj", "getInstanceTypeName", "handle", "finalizationRegistry", "detachFinalizer", "$$", "releaseClassHandle", "toDelete", "runDestructor", "attachFinalizer", "hasSmartPtr", "deletionQueue", "flushPendingDeletes", "delayFunction", "init_ClassHandle", "ClassHandle", "proto", "other", "left", "right", "leftClass", "rightClass", "throwInstanceAlreadyDeleted", "registeredPointers", "ensureOverloadTable", "methodName", "humanName", "args", "prevFunc", "exposePublicSymbol", "numArguments", "char_0", "char_9", "f", "RegisteredClass", "constructor", "instancePrototype", "baseClass", "downcast", "getActualType", "upcastPointer", "desiredClass", "ptrClass", "embindRepr", "constNoSmartPtrRawPointerToWireType", "genericPointerToWireType", "clonedHandle", "nonConstNoSmartPtrRawPointerToWireType", "downcastPointer", "getBasestPointer", "class_", "getInheritedInstance", "registeredInstances", "makeClassHandle", "record", "prototype", "rawPointer", "registeredPointerRecord", "makeDefaultHandle", "dp", "toType", "init_RegisteredPointer", "RegisteredPointer", "registeredClass", "isReference", "isConst", "isSmartPointer", "pointeeType", "rawGetPointee", "replacePublicSymbol", "getWasmTableEntry", "funcPtr", "wasmTable", "embind__requireFunction", "signature", "rawFunction", "isAsync", "makeDynCaller", "fp", "UnboundTypeError", "getTypeName", "___getTypeName", "throwUnboundTypeError", "types", "seen", "typeDependencies", "unboundTypes", "visit", "__embind_register_class", "rawPointerType", "rawConstPointerType", "baseClassRawType", "getActualTypeSignature", "upcast", "downLine truncated
}
+15
View File
@@ -0,0 +1,15 @@
{
"hash": "b95e48b0",
"configHash": "7e5ba4af",
"lockfileHash": "0299b8d0",
"browserHash": "6e4eb490",
"optimized": {
"@hpcc-js/wasm-zstd": {
"src": "../../@hpcc-js/wasm-zstd/dist/index.js",
"file": "@hpcc-js_wasm-zstd.js",
"fileHash": "e5eae5ad",
"needsInterop": false
}
},
"chunks": {}
}
+3
View File
@@ -0,0 +1,3 @@
{
"type": "module"
}
+3
View File
@@ -0,0 +1,3 @@
# esbuild
This is the Linux 64-bit binary for esbuild, a JavaScript bundler and minifier. See https://github.com/evanw/esbuild for details.
Generated Vendored Executable
BIN
View File
Binary file not shown.
+20
View File
@@ -0,0 +1,20 @@
{
"name": "@esbuild/linux-x64",
"version": "0.28.2",
"description": "The Linux 64-bit binary for esbuild, a JavaScript bundler.",
"repository": {
"type": "git",
"url": "git+https://github.com/evanw/esbuild.git"
},
"license": "MIT",
"preferUnplugged": true,
"engines": {
"node": ">=18"
},
"os": [
"linux"
],
"cpu": [
"x64"
]
}
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+148
View File
@@ -0,0 +1,148 @@
---
title: Zstd
description: WebAssembly wrapper for the Zstandard compression library
outline: deep
---
# @hpcc-js/wasm-zstd
<script setup>
import ZstdDemo from "../../.vitepress/components/ZstdDemo.vue";
</script>
This package provides a WebAssembly wrapper around the [Zstandard](https://facebook.github.io/zstd/) library. This provides efficient compression and decompression of data.
## Installation
::: code-group
```sh [npm]
npm install @hpcc-js/wasm-zstd
```
```sh [yarn]
yarn add @hpcc-js/wasm-zstd
```
```sh [pnpm]
pnpm add @hpcc-js/wasm-zstd
```
:::
## One-shot usage
```typescript
import { Zstd } from "@hpcc-js/wasm-zstd";
const zstd = await Zstd.load();
// Generate some "data"
const data = new Uint8Array(Array.from({ length: 100000 }, (_, i) => i % 256));
const compressed_data = zstd.compress(data);
const decompressed_data = zstd.decompress(compressed_data);
```
## Try it
<ZstdDemo />
`decompress()` uses a fast path when the frame records its content size. Frames with unknown content size (streaming compressors, stdin, many network streams) automatically fall back to the safe streaming decoder—no output-size guessing is required.
## Streaming compression
```typescript
import { Zstd } from "@hpcc-js/wasm-zstd";
const zstd = await Zstd.load();
zstd.resetCompression(3);
const parts: Uint8Array[] = [];
parts.push(zstd.compressChunk(chunk1)); // may be empty while Zstd buffers input
parts.push(zstd.compressChunk(chunk2));
parts.push(zstd.compressEnd());
```
## Streaming decompression
```typescript
import { Zstd } from "@hpcc-js/wasm-zstd";
const zstd = await Zstd.load();
zstd.resetDecompression();
const parts: Uint8Array[] = [];
parts.push(zstd.decompressChunk(compressedChunk1)); // may be empty
parts.push(zstd.decompressChunk(compressedChunk2));
zstd.decompressEnd(); // throws if the final frame is truncated
```
Call `decompressEnd()` after the last chunk. Intermediate empty output is valid and does **not** mean the frame is complete. Corrupt or truncated input throws an `Error` that includes the operation name and Zstandard error name when available.
## Workers
Use the default package entry from browser module workers or Node.js worker threads. The WASM payload is embedded in the bundled JavaScript, so there is no separate `.wasm` file to copy or URL to pass to `Zstd.load()`.
### Browser module worker
```typescript [worker.ts]
import { Zstd } from "@hpcc-js/wasm-zstd";
self.onmessage = async function (e: MessageEvent<Uint8Array>) {
const zstd = await Zstd.load();
const compressed = zstd.compress(e.data);
const decompressed = zstd.decompress(compressed);
self.postMessage(decompressed);
};
```
```typescript [main.ts]
const worker = new Worker(new URL("./worker.ts", import.meta.url), {
type: "module",
});
worker.onmessage = function (e: MessageEvent<Uint8Array>) {
console.log(e.data);
};
worker.postMessage(data);
```
### Node.js worker thread
```javascript [worker.js]
import { parentPort } from "node:worker_threads";
import { Zstd } from "@hpcc-js/wasm-zstd";
parentPort?.on("message", async function (data) {
const zstd = await Zstd.load();
const compressed = zstd.compress(data);
const decompressed = zstd.decompress(compressed);
parentPort?.postMessage(decompressed);
});
```
```typescript [main.ts]
import { Worker } from "node:worker_threads";
const worker = new Worker(new URL("./worker.js", import.meta.url));
worker.on("message", function (data: Uint8Array) {
console.log(data);
});
worker.postMessage(data);
```
## Singleton / serialization warning
`Zstd.load()` returns a singleton within the current JavaScript context. Compression and decompression contexts are stateful. Callers must serialize streaming operations on the shared instance—do not interleave concurrent streams on the same `Zstd` object. Prefer `resetCompression()` / `resetDecompression()` over the legacy `reset()` so one context is not cleared accidentally with the other.
<!--@include: ../../docs/zstd/src/zstd/README.md-->
## Reference
- [API Documentation](https://hpcc-systems.github.io/hpcc-js-wasm/docs/zstd/src/zstd/classes/Zstd.html)
+2
View File
@@ -0,0 +1,2 @@
var mi=ArrayBuffer,N=Uint8Array,De=Uint16Array,_i=Int16Array;var Ge=Int32Array,ur=function(n,i,s){if(N.prototype.slice)return N.prototype.slice.call(n,i,s);(i==null||i<0)&&(i=0),(s==null||s>n.length)&&(s=n.length);var c=new N(s-i);return c.set(n.subarray(i,s)),c},Re=function(n,i,s,c){if(N.prototype.fill)return N.prototype.fill.call(n,i,s,c);for((s==null||s<0)&&(s=0),(c==null||c>n.length)&&(c=n.length);s<c;++s)n[s]=i;return n},Ui=function(n,i,s,c){if(N.prototype.copyWithin)return N.prototype.copyWithin.call(n,i,s,c);for((s==null||s<0)&&(s=0),(c==null||c>n.length)&&(c=n.length);s<c;)n[i++]=n[s++]};var bi=["invalid zstd data","window size too large (>2046MB)","invalid block type","FSE accuracy too high","match distance too far back","unexpected EOF"],k=function(n,i,s){var c=new Error(i||bi[n]);if(c.code=n,Error.captureStackTrace&&Error.captureStackTrace(c,k),!s)throw c;return c},Lr=function(n,i,s){for(var c=0,l=0;c<s;++c)l|=n[i++]<<(c<<3);return l},Ci=function(n,i){return(n[i]|n[i+1]<<8|n[i+2]<<16|n[i+3]<<24)>>>0},Mi=function(n,i){var s=n[0]|n[1]<<8|n[2]<<16;if(s==3126568&&n[3]==253){var c=n[4],l=c>>5&1,p=c>>2&1,h=c&3,d=c>>6;c&8&&k(0);var U=6-l,C=h==3?4:h,M=Lr(n,U,C);U+=C;var Q=d?1<<d:l,x=Lr(n,U,Q)+(d==1&&256),R=x;if(!l){var Z=1<<10+(n[5]>>3);R=Z+(Z>>3)*(n[5]&7)}R>2145386496&&k(1);var b=new N((i==1?x||R:i?0:R)+12);return b[0]=1,b[4]=4,b[8]=8,{b:U+Q,y:0,l:0,d:M,w:i&&i!=1?i:b.subarray(12),e:R,o:new Ge(b.buffer,0,3),u:x,c:p,m:Math.min(131072,R)}}else if((s>>4|n[3]<<20)==25481893)return Ci(n,4)+8;k(0)},me=function(n){for(var i=0;1<<i<=n;++i);return i-1},$e=function(n,i,s){var c=(i<<3)+4,l=(n[i]&15)+5;l>s&&k(3);for(var p=1<<l,h=p,d=-1,U=-1,C=-1,M=p,Q=new mi(512+(p<<2)),x=new _i(Q,0,256),R=new De(Q,0,256),Z=new De(Q,512,p),b=512+(p<<1),q=new N(Q,b,p),te=new N(Q,b+p);d<255&&h>0;){var V=me(h+1),K=c>>3,ie=(1<<V+1)-1,$=(n[K]|n[K+1]<<8|n[K+2]<<16)>>(c&7)&ie,y=(1<<V)-1,L=ie-h-1,O=$&y;if(O<L?(c+=V,$=O):(c+=V+1,$>y&&($-=L)),x[++d]=--$,$==-1?(h+=$,q[--M]=d):h-=$,!$)do{var W=c>>3;U=(n[W]|n[W+1]<<8)>>(c&7)&3,c+=2,d+=U}while(U==3)}(d>255||h)&&k(0);for(var Y=0,A=(p>>1)+(p>>3)+3,ee=p-1,D=0;D<=d;++D){var P=x[D];if(P<1){R[D]=-P;continue}for(C=0;C<P;++C){q[Y]=D;do Y=Y+A&ee;while(Y>=M)}}for(Y&&k(0),C=0;C<p;++C){var m=R[q[C]]++,S=te[C]=l-me(m);Z[C]=(m<<S)-p}return[c+7>>3,{b:l,s:q,n:te,t:Z}]},Pi=function(n,i){var s=0,c=-1,l=new N(292),p=n[i],h=l.subarray(0,256),d=l.subarray(256,268),U=new De(l.buffer,268);if(p<128){var C=$e(n,i+1,6),M=C[0],Q=C[1];i+=p;var x=M<<3,R=n[i];R||k(0);for(var Z=0,b=0,q=Q.b,te=q,V=(++i<<3)-8+me(R);V-=q,!(V<x);){var K=V>>3;if(Z+=(n[K]|n[K+1]<<8)>>(V&7)&(1<<q)-1,h[++c]=Q.s[Z],V-=te,V<x)break;K=V>>3,b+=(n[K]|n[K+1]<<8)>>(V&7)&(1<<te)-1,h[++c]=Q.s[b],q=Q.n[Z],Z=Q.t[Z],te=Q.n[b],b=Q.t[b]}++c>255&&k(0)}else{for(c=p-127;s<c;s+=2){var ie=n[++i];h[s]=ie>>4,h[s+1]=ie&15}++i}var $=0;for(s=0;s<c;++s){var y=h[s];y>11&&k(0),$+=y&&1<<y-1}var L=me($)+1,O=1<<L,W=O-$;for(W&W-1&&k(0),h[c++]=me(W)+1,s=0;s<c;++s){var y=h[s];++d[h[s]=y&&L+1-y]}var Y=new N(O<<1),A=Y.subarray(0,O),ee=Y.subarray(O);for(U[L]=0,s=L;s>0;--s){var D=U[s];Re(ee,s,D,U[s-1]=D+d[s]*(1<<L-s))}for(U[0]!=O&&k(0),s=0;s<c;++s){var P=h[s];if(P){var m=U[P];Re(A,s,m,U[P]=m+(1<<L-P))}}return[i,{n:ee,b:L,s:A}]},Qi=$e(new N([81,16,99,140,49,198,24,99,12,33,196,24,99,102,102,134,70,146,4]),0,6)[1],Fi=$e(new N([33,20,196,24,99,140,33,132,16,66,8,33,132,16,66,8,33,68,68,68,68,68,68,68,68,36,9]),0,6)[1],Hi=$e(new N([32,132,16,66,102,70,68,68,68,68,36,73,2]),0,5)[1],Yr=function(n,i){for(var s=n.length,c=new Ge(s),l=0;l<s;++l)c[l]=i,i+=1<<n[l];return c},cr=new N(new Ge([0,0,0,0,16843009,50528770,134678020,202050057,269422093]).buffer,0,36),xi=Yr(cr,0),lr=new N(new Ge([0,0,0,0,0,0,0,0,16843009,50528770,117769220,185207048,252579084,16]).buffer,0,53),Ti=Yr(lr,3),qe=function(n,i,s){var c=n.length,l=i.length,p=n[c-1],h=(1<<s.b)-1,d=-s.b;p||k(0);for(var U=0,C=s.b,M=(c<<3)-8+me(p)-C,Q=-1;M>d&&Q<l;){var x=M>>3,R=(n[x]|n[x+1]<<8|n[x+2]<<16)>>(M&7);U=(U<<C|R)&h,i[++Q]=s.s[U],M-=C=s.n[U]}(M!=d||Q+1!=l)&&k(0)},Ei=function(n,i,s){var c=6,l=i.length,p=l+3>>2,h=p<<1,d=p+h;qe(n.subarray(c,c+=n[0]|n[1]<<8),i.subarray(0,p),s),qe(n.subarray(c,c+=n[2]|n[3]<<8),i.subarray(p,h),s),qe(n.subarray(c,c+=n[4]|n[5]<<8),i.subarray(h,d),s),qe(n.subarray(c),i.subarray(d),s)},qi=function(n,i,s){var c,l=i.b,p=n[l],h=p>>1&3;i.l=p&1;var d=p>>3|n[l+1]<<5|n[l+2]<<13,U=(l+=3)+d;if(h==1)return l>=n.length?void 0:(i.b=l+1,s?(Re(s,n[l],i.y,i.y+=d),s):Re(new N(d),n[l]));if(!(U>n.length)){if(h==0)return i.b=U,s?(s.set(n.subarray(l,U),i.y),i.y+=d,s):ur(n,l,U);if(h==2){var C=n[l],M=C&3,Q=C>>2&3,x=C>>4,R=0,Z=0;M<2?Q&1?x|=n[++l]<<4|(Q&2&&n[++l]<<12):x=C>>3:(Z=Q,Q<2?(x|=(n[++l]&63)<<4,R=n[l]>>6|n[++l]<<2):Q==2?(x|=n[++l]<<4|(n[++l]&3)<<12,R=n[l]>>2|n[++l]<<6):(x|=n[++l]<<4|(n[++l]&63)<<12,R=n[l]>>6|n[++l]<<2|n[++l]<<10)),++l;var b=s?s.subarray(i.y,i.y+i.m):new N(i.m),q=b.length-x;if(M==0)b.set(n.subarray(l,l+=x),q);else if(M==1)Re(b,n[l++],q);else{var te=i.h;if(M==2){var V=Pi(n,l);R+=l-(l=V[0]),i.h=te=V[1]}else te||k(0);(ZLine truncated
//# sourceMappingURL=index.js.map
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../../node_modules/fzstd/esm/index.mjs", "../../../build/packages/zstd/zstdlib.js", "../../../build/packages/zstd/zstdlib.wasm", "../../util/src/wasm-library.ts", "../src/zstd.ts"],
"sourcesContent": ["// Some numerical data is initialized as -1 even when it doesn't need initialization to help the JIT infer types\n// aliases for shorter compressed code (most minifers don't do this)\nvar ab = ArrayBuffer, u8 = Uint8Array, u16 = Uint16Array, i16 = Int16Array, u32 = Uint32Array, i32 = Int32Array;\nvar slc = function (v, s, e) {\n if (u8.prototype.slice)\n return u8.prototype.slice.call(v, s, e);\n if (s == null || s < 0)\n s = 0;\n if (e == null || e > v.length)\n e = v.length;\n var n = new u8(e - s);\n n.set(v.subarray(s, e));\n return n;\n};\nvar fill = function (v, n, s, e) {\n if (u8.prototype.fill)\n return u8.prototype.fill.call(v, n, s, e);\n if (s == null || s < 0)\n s = 0;\n if (e == null || e > v.length)\n e = v.length;\n for (; s < e; ++s)\n v[s] = n;\n return v;\n};\nvar cpw = function (v, t, s, e) {\n if (u8.prototype.copyWithin)\n return u8.prototype.copyWithin.call(v, t, s, e);\n if (s == null || s < 0)\n s = 0;\n if (e == null || e > v.length)\n e = v.length;\n while (s < e) {\n v[t++] = v[s++];\n }\n};\n/**\n * Codes for errors generated within this library\n */\nexport var ZstdErrorCode = {\n InvalidData: 0,\n WindowSizeTooLarge: 1,\n InvalidBlockType: 2,\n FSEAccuracyTooHigh: 3,\n DistanceTooFarBack: 4,\n UnexpectedEOF: 5\n};\n// error codes\nvar ec = [\n 'invalid zstd data',\n 'window size too large (>2046MB)',\n 'invalid block type',\n 'FSE accuracy too high',\n 'match distance too far back',\n 'unexpected EOF'\n];\nvar err = function (ind, msg, nt) {\n var e = new Error(msg || ec[ind]);\n e.code = ind;\n if (Error.captureStackTrace)\n Error.captureStackTrace(e, err);\n if (!nt)\n throw e;\n return e;\n};\nvar rb = function (d, b, n) {\n var i = 0, o = 0;\n for (; i < n; ++i)\n o |= d[b++] << (i << 3);\n return o;\n};\nvar b4 = function (d, b) { return (d[b] | (d[b + 1] << 8) | (d[b + 2] << 16) | (d[b + 3] << 24)) >>> 0; };\n// read Zstandard frame header\nvar rzfh = function (dat, w) {\n var n3 = dat[0] | (dat[1] << 8) | (dat[2] << 16);\n if (n3 == 0x2FB528 && dat[3] == 253) {\n // Zstandard\n var flg = dat[4];\n // single segment checksum dict flag frame content flag\n var ss = (flg >> 5) & 1, cc = (flg >> 2) & 1, df = flg & 3, fcf = flg >> 6;\n if (flg & 8)\n err(0);\n // byte\n var bt = 6 - ss;\n // dict bytes\n var db = df == 3 ? 4 : df;\n // dictionary id\n var di = rb(dat, bt, db);\n bt += db;\n // frame size bytes\n var fsb = fcf ? (1 << fcf) : ss;\n // frame source size\n var fss = rb(dat, bt, fsb) + ((fcf == 1) && 256);\n // window size\n var ws = fss;\n if (!ss) {\n // window descriptor\n var wb = 1 << (10 + (dat[5] >> 3));\n ws = wb + (wb >> 3) * (dat[5] & 7);\n }\n if (ws > 2145386496)\n err(1);\n var buf = new u8((w == 1 ? (fss || ws) : w ? 0 : ws) + 12);\n buf[0] = 1, buf[4] = 4, buf[8] = 8;\n return {\n b: bt + fsb,\n y: 0,\n l: 0,\n d: di,\n w: (w && w != 1) ? w : buf.subarray(12),\n e: ws,\n o: new i32(buf.buffer, 0, 3),\n u: fss,\n c: cc,\n m: Math.min(131072, ws)\n };\n }\n else if (((n3 >> 4) | (dat[3] << 20)) == 0x184D2A5) {\n // skippable\n return b4(dat, 4) + 8;\n }\n err(0);\n};\n// most significant bit for nonzero\nvar msb = function (val) {\n var bits = 0;\n for (; (1 << bits) <= val; ++bits)\n ;\n return bits - 1;\n};\n// read finite state entropy\nvar rfse = function (dat, bt, mal) {\n // table pos\n var tpos = (bt << 3) + 4;\n // accuracy log\n var al = (dat[bt] & 15) + 5;\n if (al > mal)\n err(3);\n // size\n var sz = 1 << al;\n // probabilities symbols repeat index high threshold\n var probs = sz, sym = -1, re = -1, i = -1, ht = sz;\n // optimization: single allocation is much faster\n var buf = new ab(512 + (sz << 2));\n var freq = new i16(buf, 0, 256);\n // same view as freq\n var dstate = new u16(buf, 0, 256);\n var nstate = new u16(buf, 512, sz);\n var bb1 = 512 + (sz << 1);\n var syms = new u8(buf, bb1, sz);\n var nbits = new u8(buf, bb1 + sz);\n while (sym < 255 && probs > 0) {\n var bits = msb(probs + 1);\n var cbt = tpos >> 3;\n // mask\n var msk = (1 << (bits + 1)) - 1;\n var val = ((dat[cbt] | (dat[cbt + 1] << 8) | (dat[cbt + 2] << 16)) >> (tpos & 7)) & msk;\n // mask (1 fewer bit)\n var msk1fb = (1 << bits) - 1;\n // max small value\n var msv = msk - probs - 1;\n // small value\Line truncated
"mappings": "AAEA,IAAIA,GAAK,YAAaC,EAAK,WAAYC,GAAM,YAAaC,GAAM,WAAhE,IAA+FC,GAAM,WACjGC,GAAM,SAAUC,EAAGC,EAAGC,EAAG,CACzB,GAAIC,EAAG,UAAU,MACb,OAAOA,EAAG,UAAU,MAAM,KAAKH,EAAGC,EAAGC,CAAC,GACtCD,GAAK,MAAQA,EAAI,KACjBA,EAAI,IACJC,GAAK,MAAQA,EAAIF,EAAE,UACnBE,EAAIF,EAAE,QACV,IAAII,EAAI,IAAID,EAAGD,EAAID,CAAC,EACpB,OAAAG,EAAE,IAAIJ,EAAE,SAASC,EAAGC,CAAC,CAAC,EACfE,CACX,EACIC,GAAO,SAAUL,EAAGI,EAAG,EAAGF,EAAG,CAC7B,GAAIC,EAAG,UAAU,KACb,OAAOA,EAAG,UAAU,KAAK,KAAKH,EAAGI,EAAG,EAAGF,CAAC,EAK5C,KAJI,GAAK,MAAQ,EAAI,KACjB,EAAI,IACJA,GAAK,MAAQA,EAAIF,EAAE,UACnBE,EAAIF,EAAE,QACH,EAAIE,EAAG,EAAE,EACZF,EAAE,CAAC,EAAII,EACX,OAAOJ,CACX,EACIM,GAAM,SAAUN,EAAGO,EAAG,EAAGL,EAAG,CAC5B,GAAIC,EAAG,UAAU,WACb,OAAOA,EAAG,UAAU,WAAW,KAAKH,EAAGO,EAAG,EAAGL,CAAC,EAKlD,KAJI,GAAK,MAAQ,EAAI,KACjB,EAAI,IACJA,GAAK,MAAQA,EAAIF,EAAE,UACnBE,EAAIF,EAAE,QACH,EAAIE,GACPF,EAAEO,GAAG,EAAIP,EAAE,GAAG,CAEtB,EAaA,IAAIQ,GAAK,CACL,oBACA,kCACA,qBACA,wBACA,8BACA,gBACJ,EACIC,EAAM,SAAUC,EAAKC,EAAKC,EAAI,CAC9B,IAAIC,EAAI,IAAI,MAAMF,GAAOH,GAAGE,CAAG,CAAC,EAIhC,GAHAG,EAAE,KAAOH,EACL,MAAM,mBACN,MAAM,kBAAkBG,EAAGJ,CAAG,EAC9B,CAACG,EACD,MAAMC,EACV,OAAOA,CACX,EACIC,GAAK,SAAUC,EAAGC,EAAGC,EAAG,CAExB,QADIC,EAAI,EAAGC,EAAI,EACRD,EAAID,EAAG,EAAEC,EACZC,GAAKJ,EAAEC,GAAG,IAAME,GAAK,GACzB,OAAOC,CACX,EACIC,GAAK,SAAUL,EAAGC,EAAG,CAAE,OAAQD,EAAEC,CAAC,EAAKD,EAAEC,EAAI,CAAC,GAAK,EAAMD,EAAEC,EAAI,CAAC,GAAK,GAAOD,EAAEC,EAAI,CAAC,GAAK,MAAS,CAAG,EAEpGK,GAAO,SAAUC,EAAKC,EAAG,CACzB,IAAIC,EAAKF,EAAI,CAAC,EAAKA,EAAI,CAAC,GAAK,EAAMA,EAAI,CAAC,GAAK,GAC7C,GAAIE,GAAM,SAAYF,EAAI,CAAC,GAAK,IAAK,CAEjC,IAAIG,EAAMH,EAAI,CAAC,EAEXI,EAAMD,GAAO,EAAK,EAAGE,EAAMF,GAAO,EAAK,EAAGG,EAAKH,EAAM,EAAGI,EAAMJ,GAAO,EACrEA,EAAM,GACNhB,EAAI,CAAC,EAET,IAAIqB,EAAK,EAAIJ,EAETK,EAAKH,GAAM,EAAI,EAAIA,EAEnBI,EAAKlB,GAAGQ,EAAKQ,EAAIC,CAAE,EACvBD,GAAMC,EAEN,IAAIE,EAAMJ,EAAO,GAAKA,EAAOH,EAEzBQ,EAAMpB,GAAGQ,EAAKQ,EAAIG,CAAG,GAAMJ,GAAO,GAAM,KAExCM,EAAKD,EACT,GAAI,CAACR,EAAI,CAEL,IAAIU,EAAK,GAAM,IAAMd,EAAI,CAAC,GAAK,GAC/Ba,EAAKC,GAAMA,GAAM,IAAMd,EAAI,CAAC,EAAI,EACpC,CACIa,EAAK,YACL1B,EAAI,CAAC,EACT,IAAI4B,EAAM,IAAIC,GAAIf,GAAK,EAAKW,GAAOC,EAAMZ,EAAI,EAAIY,GAAM,EAAE,EACzD,OAAAE,EAAI,CAAC,EAAI,EAAGA,EAAI,CAAC,EAAI,EAAGA,EAAI,CAAC,EAAI,EAC1B,CACH,EAAGP,EAAKG,EACR,EAAG,EACH,EAAG,EACH,EAAGD,EACH,EAAIT,GAAKA,GAAK,EAAKA,EAAIc,EAAI,SAAS,EAAE,EACtC,EAAGF,EACH,EAAG,IAAII,GAAIF,EAAI,OAAQ,EAAG,CAAC,EAC3B,EAAGH,EACH,EAAGP,EACH,EAAG,KAAK,IAAI,OAAQQ,CAAE,CAC1B,CACJ,UACWX,GAAM,EAAMF,EAAI,CAAC,GAAK,KAAQ,SAErC,OAAOF,GAAGE,EAAK,CAAC,EAAI,EAExBb,EAAI,CAAC,CACT,EAEI+B,GAAM,SAAUC,EAAK,CAErB,QADIC,EAAO,EACH,GAAKA,GAASD,EAAK,EAAEC,EACzB,CACJ,OAAOA,EAAO,CAClB,EAEIC,GAAO,SAAUrB,EAAKQ,EAAIc,EAAK,CAE/B,IAAIC,GAAQf,GAAM,GAAK,EAEnBgB,GAAMxB,EAAIQ,CAAE,EAAI,IAAM,EACtBgB,EAAKF,GACLnC,EAAI,CAAC,EAcT,QAZIsC,EAAK,GAAKD,EAEVE,EAAQD,EAAIE,EAAM,GAAIC,EAAK,GAAIhC,EAAI,GAAIiC,EAAKJ,EAE5CV,EAAM,IAAIe,GAAG,KAAOL,GAAM,EAAE,EAC5BM,EAAO,IAAIC,GAAIjB,EAAK,EAAG,GAAG,EAE1BkB,EAAS,IAAIC,GAAInB,EAAK,EAAG,GAAG,EAC5BoB,EAAS,IAAID,GAAInB,EAAK,IAAKU,CAAE,EAC7BW,EAAM,KAAOX,GAAM,GACnBY,EAAO,IAAIrB,EAAGD,EAAKqB,EAAKX,CAAE,EAC1Ba,GAAQ,IAAItB,EAAGD,EAAKqB,EAAMX,CAAE,EACzBE,EAAM,KAAOD,EAAQ,GAAG,CAC3B,IAAIN,EAAOF,GAAIQ,EAAQ,CAAC,EACpBa,EAAMhB,GAAQ,EAEdiB,IAAO,GAAMpB,EAAO,GAAM,EAC1BD,GAAQnB,EAAIuC,CAAG,EAAKvC,EAAIuC,EAAM,CAAC,GAAK,EAAMvC,EAAIuC,EAAM,CAAC,GAAK,MAAShB,EAAO,GAAMiB,GAEhFC,GAAU,GAAKrB,GAAQ,EAEvBsB,EAAMF,GAAMd,EAAQ,EAEpBiB,EAAOxB,EAAMsB,EAejB,GAdIE,EAAOD,GACPnB,GAAQH,EAAMD,EAAMwB,IAEpBpB,GAAQH,EAAO,EACXD,EAAMsB,IACNtB,GAAOuB,IAEfX,EAAK,EAAEJ,CAAG,EAAI,EAAER,EACZA,GAAO,IACPO,GAASP,EACTkB,EAAK,EAAER,CAAE,EAAIF,GAGbD,GAASP,EACT,CAACA,EACD,EAAG,CAEC,IAAIyB,EAAMrB,GAAQ,EAClBK,GAAO5B,EAAI4C,CAAG,EAAK5C,EAAI4C,EAAM,CAAC,GAAK,KAAQrB,EAAO,GAAM,EACxDA,GAAQ,EACRI,GAAOC,CACX,OAASA,GAAM,EAEvB,EACID,EAAM,KAAOD,IACbvC,EAAI,CAAC,EAMT,QALI0D,EAAS,EAETC,GAASrB,GAAM,IAAMA,GAAM,GAAK,EAEhCsB,GAAQtB,EAAK,EACRuB,EAAI,EAAGA,GAAKrB,EAAK,EAAEqB,EAAG,CAC3B,IAAIC,EAAKlB,EAAKiB,CAAC,EACf,GAAIC,EAAK,EAAG,CACRhB,EAAOe,CAAC,EAAI,CAACC,EACb,QACJ,CAEA,IAAKrD,EAAI,EAAGA,EAAIqD,EAAI,EAAErD,EAAG,CACrByC,EAAKQ,CAAM,EAAIG,EACf,GACIH,EAAUA,EAASC,EAASC,SACvBF,GAAUhB,EACvB,CACJ,CAIA,IAFIgB,GACA1D,EAAI,CAAC,EACJS,EAAI,EAAGA,EAAI6B,EAAI,EAAE7B,EAAG,CAErB,IAAIsD,EAAKjB,EAAOI,EAAKzC,CAAC,CAAC,IAEnBuD,EAAKb,GAAM1C,CAAC,EAAI4B,EAAKN,GAAIgC,CAAE,EAC/Bf,EAAOvC,CAAC,GAAKsD,GAAMC,GAAM1B,CAC7B,CACA,MAAO,CAAEF,EAAO,GAAM,EAAG,CACjB,EAAGC,EACH,EAAGa,EACH,EAAGC,GACH,EAAGH,CACP,CAAC,CACT,EAEIiB,GAAM,SAAUpD,EAAKQ,EAAI,CAEzB,IAAIZ,EAAI,EAAGyD,EAAK,GAEZtC,EAAM,IAAIC,EAAG,GAAG,EAAGsC,EAAKtD,EAAIQ,CAAE,EAE9B+C,EAAKxC,EAAI,SAAS,EAAG,GAAG,EAExByC,EAAKzC,EAAI,SAAS,IAAK,GAAG,EAE1B0C,EAAK,IAAIvB,GAAInB,EAAI,OAAQ,GAAG,EAEhC,GAAIuC,EAAK,IAAK,CAEV,IAAII,EAAKrC,GAAKrB,EAAKQ,EAAK,EAAG,CAAC,EAAGmD,EAAMD,EAAG,CAAC,EAAGE,EAAMF,EAAG,CAAC,EACtDlD,GAAM8C,EACN,IAAIO,EAAOF,GAAO,EAEdG,EAAK9D,EAAIQ,CAAE,EACVsD,GACD3E,EAAI,CAAC,EAMT,QAJI4E,EAAM,EAAGC,EAAM,EAAGC,EAAOL,EAAI,EAAGM,GAAOD,EAGvCE,GAAQ,EAAE3D,GAAM,GAAK,EAAIU,GAAI4C,CAAE,EAE/BK,GAAQF,EACJ,EAAAE,EAAON,IAFN,CAIL,IAAItB,EAAM4B,GAAQ,EAIlB,GAHAJ,IAAS/D,EAAIuC,CAAG,EAAKvC,EAAIuC,EAAM,CAAC,GAAK,KAAQ4BLine truncated
"names": ["ab", "u8", "u16", "i16", "i32", "slc", "v", "s", "e", "u8", "n", "fill", "cpw", "t", "ec", "err", "ind", "msg", "nt", "e", "rb", "d", "b", "n", "i", "o", "b4", "rzfh", "dat", "w", "n3", "flg", "ss", "cc", "df", "fcf", "bt", "db", "di", "fsb", "fss", "ws", "wb", "buf", "u8", "i32", "msb", "val", "bits", "rfse", "mal", "tpos", "al", "sz", "probs", "sym", "re", "ht", "ab", "freq", "i16", "dstate", "u16", "nstate", "bb1", "syms", "nbits", "cbt", "msk", "msk1fb", "msv", "sval", "rbt", "sympos", "sstep", "smask", "s", "sf", "ns", "nb", "rhu", "wc", "hb", "hw", "rc", "ri", "_a", "ebt", "fdt", "epos", "lb", "st1", "st2", "btr1", "btr2", "fpos", "byte", "wes", "wt", "mb", "ts", "rem", "hbuf", "pv", "fill", "code", "dllt", "dmlt", "doct", "b2bl", "len", "bl", "llb", "llbl", "mlb", "mlbl", "dhu", "out", "hu", "eb", "st", "btr", "pos", "dhu4", "sz1", "sz2", "sz3", "rzb", "b0", "btype", "slc", "b3", "lbt", "lss", "lcs", "s4", "spl", "hud", "scm", "dts", "md", "rbuf", "_b", "mlt", "oct", "llt", "spos", "oubt", "lst", "ost", "mst", "llc", "lbtr", "mlc", "mbtr", "ofc", "obtr", "ofp", "off", "ml", "ll", "idx", "stin", "bs", "cct", "bufs", "ol", "chk", "decompress", "blk", "cpw", "cpp", "moduleArg", "Module", "quit_", "status", "toThrow", "_scriptName", "scriptDirectory", "locateFile", "path", "readAsync", "readBinary", "out", "err", "wasmBinary", "ABORT", "EXITSTATUS", "isFileURI", "filename", "runtimeInitialized", "getMemoryBuffer", "wasmMemory", "updateMemoryViews", "HEAP8", "b", "HEAP16", "HEAPU8", "HEAPU16", "HEAP32", "HEAPU32", "HEAPF32", "HEAPF64", "HEAP64", "HEAPU64", "preRun", "initRuntime", "wasmExports", "postRun", "abort", "what", "___trap", "wasmBinaryFile", "findWasmBinary", "getBinarySync", "file", "getWasmBinary", "binaryFile", "response", "instantiateArrayBuffer", "imports", "binary", "instance", "reason", "instantiateAsync", "instantiationResult", "getWasmImports", "wasmImports", "createWasm", "receiveInstance", "assignWasmExports", "receiveInstantiationResult", "result", "info", "exports", "ExitStatus", "getCppExceptionTag", "___cpp_exception", "getCppExceptionThrownObjectFromWebAssemblyException", "ex", "unwind_header", "___thrown_object_from_unwind_exception", "stackSave", "_emscripten_stack_get_current", "stackRestore", "val", "__emscripten_stack_restore", "stackAlloc", "sz", "__emscripten_stack_alloc", "UTF8Decoder", "findStringEnd", "heapOrArray", "idx", "maxBytesToRead", "ignoreNul", "maxIdx", "UTF8ArrayToString", "endPtr", "str", "u0", "u1", "u2", "ch", "UTF8ToString", "ptr", "getExceptionMessageCommon", "sp", "type_addr_addr", "message_addr_addr", "___get_exception_message", "type_addr", "message_addr", "type", "_free", "message", "getExceptionMessage", "___throw_exception_with_stack_trace", "__abort_js", "structRegistrations", "runDestructors", "destructors", "del", "readPointer", "pointer", "awaitingDependencies", "registeredTypes", "typeDependencies", "InternalError", "throwInternalError", "whenDependentTypesAreResolved", "myTypes", "dependentTypes", "getTypeConverters", "onComplete", "typeConverters", "myTypeConverters", "i", "registerType", "unregisteredTypes", "registered", "dt", "__embind_finalize_value_object", "structType", "reg", "rawConstructor", "rawDestructor", "fieldRecords", "fieldTypes", "field", "fields", "getterReturnType", "getter", "getterContext", "setterArgumentType", "setter", "setterContext", "o", "rv", "fieldName", "AsciiToString", "BindingError", "throwBindingError", "sharedRegisterType", "rawType", "registeredInstance", "options", "name", "callbacks", "cb", "integerReadValueFromPointer", "width", "signed", "__embind_register_bigint", "primitiveType", "size", "minRange", "maxRange", "isUnsignedType", "fromWireType", "value", "bitSize", "__embind_register_bool", "trueValue", "falseValue", "wt", "shallowCopyInternalPointer", "throwInstanceAlreadyDeleted", "obj", "getInstanceTypeName", "handle", "finalizationRegistry", "detachFinalizer", "runDestructor", "$$", "releaseClassHandle", "toDelete", "attachFinalizer", "hasSmartPtr", "deletionQueue", "flushPendingDeletes", "delayFunction", "init_ClassHandle", "proto", "ClassHandle", "other", "leftClass", "left", "rightClass", "right", "clone", "symbolDispose", "createNamedFunction", "func", "registeredPointers", "ensureOverloadTable", "methodName", "humanName", "prevFunc", "args", "exposePublicSymbol", "numArguments", "char_0", "char_9", "makeLegalFunctionName", "f", "RegisteredClass", "constructor", "instancePrototype", "baseClass", "getActualType", "upcast", "downcast", "upcastPointer", "ptrClass", "desiredClass", "embindRepr", "v", "t", "constNoSmartPtrRawPointerToWireType", "handleClass", "genericPointerToWireType", "clonedHandle", "Emval", "nonConstNoSmartPtrRawPointerToWireType", "downcastPointer", "registeredInstances", "getBasestPointer", "class_", "getInheritedInstance", "makeClassHandle", "prototype", "record", "hasSmartPtrType", "RegisteredPointer_fromWireType", "rawPointer", "makeDefaultHandle", "actualTypeLine truncated
}
+65
View File
@@ -0,0 +1,65 @@
{
"name": "@hpcc-js/wasm-zstd",
"version": "1.16.0",
"description": "hpcc-js - WASM zstd",
"type": "module",
"exports": {
".": {
"types": "./types/index.d.ts",
"default": "./dist/index.js"
}
},
"main": "./dist/index.js",
"types": "./types/index.d.ts",
"publishConfig": {
"access": "public"
},
"files": [
"dist/**/*",
"src/**/*",
"types/**/*"
],
"scripts": {
"clean": "rimraf coverage dist dist-test types .nyc_output",
"build-cpp": "cmake --build ../../build --target zstdlib",
"build-cpp-watch": "chokidar 'src-cpp/**.*' -c 'npm run build-cpp'",
"gen-types": "tsc --project tsconfig.json --emitDeclarationOnly",
"gen-types-watch": "npm run gen-types -- --watch",
"bundle": "node esbuild.js",
"bundle-dev": "npm run bundle -- --development",
"bundle-watch": "npm run bundle-dev -- --watch",
"build-dev": "run-p gen-types bundle-dev",
"build": "run-p gen-types bundle",
"lint-skypack": "npx -y @skypack/package-check",
"lint-eslint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\"",
"lint": "run-p lint-eslint",
"test-browser": "vitest run --project browser",
"test-node": "vitest run --project node",
"test": "vitest run",
"coverage": "vitest run --coverage",
"update": "npx -y npm-check-updates -u -t minor",
"update-major": "npx -y npm-check-updates -u"
},
"dependencies": {},
"devDependencies": {
"@hpcc-js/esbuild-plugins": "1.12.0",
"@hpcc-js/wasm-util": "1.0.0"
},
"keywords": [
"graphviz",
"typescript",
"webassembly",
"wasm",
"dot",
"neato",
"twopi"
],
"author": "hpcc-systems",
"repository": {
"type": "git",
"url": "git+https://github.com/hpcc-systems/hpcc-js-wasm.git"
},
"homepage": "https://hpcc-systems.github.io/hpcc-js-wasm/",
"license": "Apache-2.0",
"gitHead": "8f570c863d34cb7d08aa7bc54f48558f9bd3bcba"
}
+3
View File
@@ -0,0 +1,3 @@
export const PKG_NAME = "@hpcc-js/wasm-zstd";
export const PKG_VERSION = "1.7.0";
export const BUILD_VERSION = "4.0.0";
+1
View File
@@ -0,0 +1 @@
export * from "./zstd.ts";
+475
View File
@@ -0,0 +1,475 @@
// @ts-expect-error importing from a wasm file is resolved via a custom esbuild plugin
import load, { reset } from "../../../build/packages/zstd/zstdlib.wasm";
import type { MainModule, zstd, StreamResult, FrameContentSizeResult } from "../types/zstdlib.js";
import { MainModuleEx, type HeapU8 } from "@hpcc-js/wasm-util";
type ZstdExports = MainModule["zstd"];
// Ref: http://facebook.github.io/zstd/zstd_manual.html
// Ref: https://github.com/facebook/zstd
let g_zstd: Promise<Zstd> | undefined;
const WASM32_MAX = 0xffffffff;
function assertSafeLength(length: number, label: string): void {
if (!Number.isInteger(length) || length < 0 || length > WASM32_MAX) {
throw new Error(`${label} length ${length} is outside the WASM32-safe range`);
}
}
function concatUint8Arrays(chunks: Uint8Array[]): Uint8Array {
if (chunks.length === 0) {
return new Uint8Array(0);
}
if (chunks.length === 1) {
return chunks[0];
}
let total = 0;
for (const chunk of chunks) {
total += chunk.length;
}
const out = new Uint8Array(total);
let offset = 0;
for (const chunk of chunks) {
out.set(chunk, offset);
offset += chunk.length;
}
return out;
}
/**
* The Zstandard WASM library, provides a simplified wrapper around the Zstandard c++ library.
*
* See [Zstandard](https://facebook.github.io/zstd/) for more details.
*
* ```ts
* import { Zstd } from "@hpcc-js/wasm-zstd";
*
* const zstd = await Zstd.load();
*
* // Generate some "data"
* const data = new Uint8Array(Array.from({ length: 100000 }, (_, i) => i % 256));
*
* const compressed_data = zstd.compress(data);
* const decompressed_data = zstd.decompress(compressed_data);
* ```
*
* ::: warning
* `Zstd.load()` returns a process-wide singleton. Streaming compression and decompression
* mutate shared codec state and must be serialized by the caller. Do not interleave
* concurrent streaming operations on the same instance.
* :::
*/
export class Zstd {
private _mainModule: MainModuleEx<MainModule>;
private _zstdClass: ZstdExports;
private _zstd: zstd;
private _compressionLevel: number;
private _decompressFrameCompleted = false;
private _decompressRemaining = 0;
private _decompressSawInput = false;
private constructor(_module: MainModule) {
this._mainModule = new MainModuleEx(_module);
this._zstdClass = _module.zstd;
this._zstd = new this._zstdClass();
this._compressionLevel = this._zstdClass.defaultCLevel();
}
/**
* Compiles and instantiates the raw wasm.
*
* ::: info
* In general WebAssembly compilation is disallowed on the main thread if the buffer size is larger than 4KB, hence forcing `load` to be asynchronous;
* :::
*
* @returns A promise to an instance of the Zstd class.
*/
static load(): Promise<Zstd> {
if (!g_zstd) {
g_zstd = load().then((module: MainModule) => new Zstd(module));
}
return g_zstd!;
}
/**
* Unloades the compiled wasm instance.
*/
static unload() {
reset();
g_zstd?.then(zstd => {
zstd?._zstd?.delete();
});
g_zstd = undefined;
}
private copyHeap(data: HeapU8): Uint8Array {
return this._mainModule.heapView(data).slice();
}
private mallocChecked(size: number, label: string): HeapU8 {
assertSafeLength(size, label);
const heap = this._mainModule.malloc(size);
if (!heap.ptr) {
this._mainModule.free(heap);
throw new Error(`Failed to allocate ${size} bytes for ${label}`);
}
return heap;
}
private throwStreamError(operation: string, result: StreamResult): never {
throw new Error(`${operation} failed: ${result.errorName || "unknown error"}`);
}
private ensureStreamOk(operation: string, result: StreamResult): void {
if (result.error) {
this.throwStreamError(operation, result);
}
}
/**
* @returns The Zstd c++ version
*/
version(): string {
return this._zstdClass.version();
}
/**
* Resets both compression and decompression state (legacy API).
* Prefer {@link resetCompression} / {@link resetDecompression} so the two
* contexts are not reset accidentally together.
*/
reset(): void {
const result = this._zstd.reset();
this.ensureStreamOk("reset", result);
this._decompressFrameCompleted = false;
this._decompressRemaining = 0;
this._decompressSawInput = false;
}
/**
* Resets compression state and optionally sets the compression level.
* @param compressionLevel When omitted, the current level is kept.
*/
resetCompression(compressionLevel?: number): void {
if (compressionLevel !== undefined) {
this._compressionLevel = compressionLevel;
}
const result = this._zstd.resetCompression(this._compressionLevel);
this.ensureStreamOk("resetCompression", result);
}
/**
* Resets decompression state before a new streaming decode.
*/
resetDecompression(): void {
const result = this._zstd.resetDecompression();
this.ensureStreamOk("resetDecompression", result);
this._decompressFrameCompleted = false;
this._decompressRemaining = 0;
this._decompressSawInput = false;
}
/**
* Sets the compression level for streaming compression.
* @param level Compression level (use minCLevel() to maxCLevel())
*/
setCompressionLevel(level: number): void {
const result = this._zstd.setCompressionLevel(level);
this.ensureStreamOk("setCompressionLevel", result);
this._compressionLevel = level;
}
/**
* @param data Data to be compressed
* @param compressionLevel Compression v Speed tradeoff, when omitted it will default to `zstd.defaultCLevel()` which is currently 3.
* @returns Compressed data.
*
* :::tip
* A note on compressionLevel: The library supports regular compression levels from 1 up o 22. Levels >= 20, should be used with caution, as they require more memory. The library also offers negative compression levels, which extend the range of speed vs. ratio preferences. The lower the level, the faster the speed (at the cost of compression).
* :::
*/
compress(data: Uint8Array, compressionLevel: number = this.defaultCLevel()): Uint8Array {
assertSafeLength(data.length, "compress input");
const uncompressed = this._mainModule.dataToHeap(data);
try {
if (!uncompressed.ptr && data.length > 0) {
throw new Error("Failed to allocate compress input buffer");
}
const compressedSize = this._zstdClass.compressBound(data.length);
const compressed = this.mallocChecked(compressedSize, "compress output");
try {
compressed.size = this._zstdClass.compress(compressed.ptr, compressedSize, uncompressed.ptr, uncompressed.size, compressionLevel);
if (this._zstdClass.isError(compressed.size)) {
throw new Error(`compress failed: ${this._zstdClass.getErrorName(compressed.size)}`);
}
return this.copyHeap(compressed);
} finally {
this._mainModule.free(compressed);
}
} finally {
this._mainModule.free(uncompressed);
}
}
/**
* Compresses a chunk of data in streaming mode.
* Call {@link resetCompression} before the first chunk, then {@link compressChunk} for each chunk, and finally {@link compressEnd}.
* Intermediate calls may return an empty array when Zstandard buffers input.
* @param data Chunk of data to be compressed
* @returns Compressed chunk data produced for this input (may be empty)
*/
compressChunk(data: Uint8Array): Uint8Array {
assertSafeLength(data.length, "compressChunk input");
if (data.length === 0) {
return new Uint8Array(0);
}
const uncompressed = this._mainModule.dataToHeap(data);
try {
if (!uncompressed.ptr) {
throw new Error("Failed to allocate compressChunk input buffer");
}
const outCapacity = this._zstdClass.CStreamOutSize();
const chunks: Uint8Array[] = [];
let offset = 0;
while (offset < data.length) {
const compressed = this.mallocChecked(outCapacity, "compressChunk output");
try {
const result = this._zstd.compressChunk(
compressed.ptr,
outCapacity,
uncompressed.ptr + offset,
data.length - offset
);
this.ensureStreamOk("compressChunk", result);
if (result.consumed === 0 && result.produced === 0) {
throw new Error("compressChunk failed: no progress while consuming input");
}
offset += result.consumed;
if (result.produced > 0) {
compressed.size = result.produced;
chunks.push(this.copyHeap(compressed));
}
} finally {
this._mainModule.free(compressed);
}
}
return concatUint8Arrays(chunks);
} finally {
this._mainModule.free(uncompressed);
}
}
/**
* Finishes the streaming compression and returns any remaining compressed data.
* @returns Final compressed data
*/
compressEnd(): Uint8Array {
const outCapacity = this._zstdClass.CStreamOutSize();
const chunks: Uint8Array[] = [];
let remaining = 1;
while (remaining !== 0) {
const compressed = this.mallocChecked(outCapacity, "compressEnd output");
try {
const result = this._zstd.compressEnd(compressed.ptr, outCapacity);
this.ensureStreamOk("compressEnd", result);
if (result.produced === 0 && result.remaining !== 0) {
throw new Error("compressEnd failed: no progress while finishing stream");
}
remaining = result.remaining;
if (result.produced > 0) {
compressed.size = result.produced;
chunks.push(this.copyHeap(compressed));
}
} finally {
this._mainModule.free(compressed);
}
}
return concatUint8Arrays(chunks);
}
private frameContentSize(compressed: HeapU8): FrameContentSizeResult {
return this._zstdClass.getFrameContentSize(compressed.ptr, compressed.size);
}
/**
* @param compressedData Data to be decompressed
* @returns Uncompressed data.
*/
decompress(compressedData: Uint8Array): Uint8Array {
assertSafeLength(compressedData.length, "decompress input");
const compressed = this._mainModule.dataToHeap(compressedData);
try {
if (!compressed.ptr && compressedData.length > 0) {
throw new Error("Failed to allocate decompress input buffer");
}
const sizeInfo = this.frameContentSize(compressed);
if (sizeInfo.error) {
throw new Error(`Failed to get frame content size: ${sizeInfo.errorName}`);
}
let useFastPath = sizeInfo.known;
if (useFastPath) {
// ZSTD_decompress only handles one frame. Known-size concatenated
// frames would allocate only for the first frame and overflow.
const frameCompressedSize = this._zstdClass.findFrameCompressedSize(compressed.ptr, compressed.size);
if (this._zstdClass.isError(frameCompressedSize)) {
throw new Error(`Failed to find frame compressed size: ${this._zstdClass.getErrorName(frameCompressedSize)}`);
}
if (frameCompressedSize < compressed.size) {
useFastPath = false;
}
}
if (useFastPath) {
const uncompressed = this.mallocChecked(sizeInfo.size, "decompress output");
try {
uncompressed.size = this._zstdClass.decompress(
uncompressed.ptr,
sizeInfo.size,
compressed.ptr,
compressed.size
);
if (this._zstdClass.isError(uncompressed.size)) {
throw new Error(`decompress failed: ${this._zstdClass.getErrorName(uncompressed.size)}`);
}
return this.copyHeap(uncompressed);
} finally {
this._mainModule.free(uncompressed);
}
}
} finally {
this._mainModule.free(compressed);
}
return this.decompressViaStreaming(compressedData);
}
private decompressViaStreaming(compressedData: Uint8Array): Uint8Array {
this.resetDecompression();
const produced = this.decompressChunk(compressedData);
this.decompressEnd();
return produced;
}
/**
* Decompresses a chunk of data in streaming mode.
* Call {@link resetDecompression} before the first chunk, then {@link decompressChunk} for each chunk, and finally {@link decompressEnd}.
* Intermediate calls may return an empty array. Callers must not guess an output size.
* @param compressedData Chunk of compressed data
* @returns Decompressed chunk data produced for this input (may be empty)
*/
decompressChunk(compressedData: Uint8Array): Uint8Array {
assertSafeLength(compressedData.length, "decompressChunk input");
if (compressedData.length === 0) {
return new Uint8Array(0);
}
this._decompressSawInput = true;
const compressed = this._mainModule.dataToHeap(compressedData);
try {
if (!compressed.ptr) {
throw new Error("Failed to allocate decompressChunk input buffer");
}
const outCapacity = this._zstdClass.DStreamOutSize();
const chunks: Uint8Array[] = [];
let offset = 0;
let outputFilled = false;
// Continue while input remains, or the previous step filled the output buffer
// (pending decoder output may still need an empty-input flush).
while (offset < compressedData.length || outputFilled) {
const uncompressed = this.mallocChecked(outCapacity, "decompressChunk output");
try {
const srcSize = offset < compressedData.length
? compressedData.length - offset
: 0;
const srcPtr = srcSize > 0
? compressed.ptr + offset
: 0;
const result = this._zstd.decompressChunk(
uncompressed.ptr,
outCapacity,
srcPtr,
srcSize
);
this.ensureStreamOk("decompressChunk", result);
if (result.consumed === 0 && result.produced === 0) {
if (srcSize === 0) {
if (result.remaining > 0) {
// Need more compressed input — wait for the next chunk.
this._decompressRemaining = result.remaining;
}
// remaining === 0: fully flushed, or waiting for input above.
break;
}
throw new Error("decompressChunk failed: no progress while consuming input");
}
offset += result.consumed;
// Only flush with empty input while the current frame still has pending output.
// When remaining === 0 the frame is complete (even if the buffer filled exactly);
// a follow-up empty call can return a non-zero hint and must not look like truncation.
outputFilled = result.produced === outCapacity && result.remaining !== 0;
if (result.produced > 0) {
uncompressed.size = result.produced;
chunks.push(this.copyHeap(uncompressed));
}
if (result.remaining === 0) {
this._decompressFrameCompleted = true;
this._decompressRemaining = 0;
} else {
this._decompressRemaining = result.remaining;
}
} finally {
this._mainModule.free(uncompressed);
}
}
return concatUint8Arrays(chunks);
} finally {
this._mainModule.free(compressed);
}
}
/**
* Verifies that streaming decompression completed a full frame and was not truncated.
* Empty intermediate output is not treated as completion; call this after the final chunk.
*/
decompressEnd(): void {
if (!this._decompressSawInput) {
throw new Error("decompressEnd failed: empty compressed input is not a completed frame");
}
if (!this._decompressFrameCompleted || this._decompressRemaining !== 0) {
throw new Error("decompressEnd failed: truncated Zstandard input");
}
}
/**
* @returns Default compression level (see notes above above).
*/
defaultCLevel(): number {
return this._zstdClass.defaultCLevel();
}
minCLevel(): number {
return this._zstdClass.minCLevel();
}
maxCLevel(): number {
return this._zstdClass.maxCLevel();
}
}
+3
View File
@@ -0,0 +1,3 @@
export declare const PKG_NAME = "@hpcc-js/wasm-zstd";
export declare const PKG_VERSION = "1.7.0";
export declare const BUILD_VERSION = "4.0.0";
+1
View File
@@ -0,0 +1 @@
export * from "./zstd.ts";
+124
View File
@@ -0,0 +1,124 @@
/**
* The Zstandard WASM library, provides a simplified wrapper around the Zstandard c++ library.
*
* See [Zstandard](https://facebook.github.io/zstd/) for more details.
*
* ```ts
* import { Zstd } from "@hpcc-js/wasm-zstd";
*
* const zstd = await Zstd.load();
*
* // Generate some "data"
* const data = new Uint8Array(Array.from({ length: 100000 }, (_, i) => i % 256));
*
* const compressed_data = zstd.compress(data);
* const decompressed_data = zstd.decompress(compressed_data);
* ```
*
* ::: warning
* `Zstd.load()` returns a process-wide singleton. Streaming compression and decompression
* mutate shared codec state and must be serialized by the caller. Do not interleave
* concurrent streaming operations on the same instance.
* :::
*/
export declare class Zstd {
private _mainModule;
private _zstdClass;
private _zstd;
private _compressionLevel;
private _decompressFrameCompleted;
private _decompressRemaining;
private _decompressSawInput;
private constructor();
/**
* Compiles and instantiates the raw wasm.
*
* ::: info
* In general WebAssembly compilation is disallowed on the main thread if the buffer size is larger than 4KB, hence forcing `load` to be asynchronous;
* :::
*
* @returns A promise to an instance of the Zstd class.
*/
static load(): Promise<Zstd>;
/**
* Unloades the compiled wasm instance.
*/
static unload(): void;
private copyHeap;
private mallocChecked;
private throwStreamError;
private ensureStreamOk;
/**
* @returns The Zstd c++ version
*/
version(): string;
/**
* Resets both compression and decompression state (legacy API).
* Prefer {@link resetCompression} / {@link resetDecompression} so the two
* contexts are not reset accidentally together.
*/
reset(): void;
/**
* Resets compression state and optionally sets the compression level.
* @param compressionLevel When omitted, the current level is kept.
*/
resetCompression(compressionLevel?: number): void;
/**
* Resets decompression state before a new streaming decode.
*/
resetDecompression(): void;
/**
* Sets the compression level for streaming compression.
* @param level Compression level (use minCLevel() to maxCLevel())
*/
setCompressionLevel(level: number): void;
/**
* @param data Data to be compressed
* @param compressionLevel Compression v Speed tradeoff, when omitted it will default to `zstd.defaultCLevel()` which is currently 3.
* @returns Compressed data.
*
* :::tip
* A note on compressionLevel: The library supports regular compression levels from 1 up o 22. Levels >= 20, should be used with caution, as they require more memory. The library also offers negative compression levels, which extend the range of speed vs. ratio preferences. The lower the level, the faster the speed (at the cost of compression).
* :::
*/
compress(data: Uint8Array, compressionLevel?: number): Uint8Array;
/**
* Compresses a chunk of data in streaming mode.
* Call {@link resetCompression} before the first chunk, then {@link compressChunk} for each chunk, and finally {@link compressEnd}.
* Intermediate calls may return an empty array when Zstandard buffers input.
* @param data Chunk of data to be compressed
* @returns Compressed chunk data produced for this input (may be empty)
*/
compressChunk(data: Uint8Array): Uint8Array;
/**
* Finishes the streaming compression and returns any remaining compressed data.
* @returns Final compressed data
*/
compressEnd(): Uint8Array;
private frameContentSize;
/**
* @param compressedData Data to be decompressed
* @returns Uncompressed data.
*/
decompress(compressedData: Uint8Array): Uint8Array;
private decompressViaStreaming;
/**
* Decompresses a chunk of data in streaming mode.
* Call {@link resetDecompression} before the first chunk, then {@link decompressChunk} for each chunk, and finally {@link decompressEnd}.
* Intermediate calls may return an empty array. Callers must not guess an output size.
* @param compressedData Chunk of compressed data
* @returns Decompressed chunk data produced for this input (may be empty)
*/
decompressChunk(compressedData: Uint8Array): Uint8Array;
/**
* Verifies that streaming decompression completed a full frame and was not truncated.
* Empty intermediate output is not treated as completion; call this after the final chunk.
*/
decompressEnd(): void;
/**
* @returns Default compression level (see notes above above).
*/
defaultCLevel(): number;
minCLevel(): number;
maxCLevel(): number;
}
+84
View File
@@ -0,0 +1,84 @@
// TypeScript bindings for emscripten-generated code. Automatically generated at compile time.
declare var RuntimeExports: {
/**
* Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
* emscripten HEAP, returns a copy of that string as a Javascript String object.
*
* @param {number} ptr
* @param {number=} maxBytesToRead - An optional length that specifies the
* maximum number of bytes to read. You can omit this parameter to scan the
* string until the first 0 byte. If maxBytesToRead is passed, and the string
* at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
* string will cut short at that byte index.
* @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
* @return {string}
*/
UTF8ToString: (ptr: number, maxBytesToRead?: number | undefined, ignoreNul?: boolean | undefined) => string;
lengthBytesUTF8: (str: any) => number;
stringToUTF8: (str: any, outPtr: any, maxBytesToWrite: any) => any;
/** @type {!Uint8Array} */
HEAPU8: Uint8Array;
};
interface WasmModule {
_malloc(_0: number): number;
_free(_0: number): void;
}
type EmbindString = ArrayBuffer|Uint8Array|Uint8ClampedArray|Int8Array|string;
export interface ClassHandle {
isAliasOf(other: ClassHandle): boolean;
delete(): void;
deleteLater(): this;
isDeleted(): boolean;
// @ts-ignore - If targeting lower than ESNext, this symbol might not exist.
[Symbol.dispose](): void;
clone(): this;
}
export interface zstd extends ClassHandle {
reset(): StreamResult;
resetCompression(_0: number): StreamResult;
resetDecompression(): StreamResult;
setCompressionLevel(_0: number): StreamResult;
compressChunk(_0: number, _1: number, _2: number, _3: number): StreamResult;
compressEnd(_0: number, _1: number): StreamResult;
decompressChunk(_0: number, _1: number, _2: number, _3: number): StreamResult;
}
export type StreamResult = {
consumed: number,
produced: number,
remaining: number,
error: boolean,
errorName: EmbindString
};
export type FrameContentSizeResult = {
known: boolean,
error: boolean,
size: number,
errorName: EmbindString
};
interface EmbindModule {
zstd: {
new(): zstd;
minCLevel(): number;
maxCLevel(): number;
defaultCLevel(): number;
malloc(_0: number): number;
free(_0: number): void;
compress(_0: number, _1: number, _2: number, _3: number, _4: number): number;
decompress(_0: number, _1: number, _2: number, _3: number): number;
findFrameCompressedSize(_0: number, _1: number): number;
compressBound(_0: number): number;
CStreamOutSize(): number;
DStreamOutSize(): number;
isError(_0: number): number;
getFrameContentSize(_0: number, _1: number): FrameContentSizeResult;
version(): string;
getErrorName(_0: number): string;
};
}
export type MainModule = WasmModule & typeof RuntimeExports & EmbindModule;
export default function MainModuleFactory (options?: unknown): Promise<MainModule>;
+3
View File
@@ -0,0 +1,3 @@
# `@napi-rs/lzma-linux-x64-gnu`
This is the **x86_64-unknown-linux-gnu** binary for `@napi-rs/lzma`
Binary file not shown.
+39
View File
@@ -0,0 +1,39 @@
{
"name": "@napi-rs/lzma-linux-x64-gnu",
"version": "1.5.1",
"cpu": [
"x64"
],
"main": "lzma.linux-x64-gnu.node",
"files": [
"lzma.linux-x64-gnu.node"
],
"description": "lzma / lzma2 / xz compression for Node.js and the browser, backed by pure-Rust lzma-rust2 via https://napi.rs",
"keywords": [
"Node-API",
"napi",
"lzma",
"compress",
"decompress",
"xz",
"napi-rs"
],
"license": "MIT",
"engines": {
"node": "^22.20 || ^24.12 || >=25"
},
"repository": {
"url": "git+https://github.com/Brooooooklyn/lzma.git",
"type": "git"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public"
},
"os": [
"linux"
],
"libc": [
"glibc"
]
}
+3
View File
@@ -0,0 +1,3 @@
# `@rollup/rollup-linux-x64-gnu`
This is the **x86_64-unknown-linux-gnu** binary for `rollup`
+25
View File
@@ -0,0 +1,25 @@
{
"name": "@rollup/rollup-linux-x64-gnu",
"version": "4.63.2",
"os": [
"linux"
],
"cpu": [
"x64"
],
"files": [
"rollup.linux-x64-gnu.node"
],
"description": "Native bindings for Rollup",
"author": "Lukas Taegert-Atkinson",
"homepage": "https://rollupjs.org/",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/rollup/rollup.git"
},
"libc": [
"glibc"
],
"main": "./rollup.linux-x64-gnu.node"
}
Binary file not shown.
+243
View File
@@ -0,0 +1,243 @@
# SQLite Wasm
SQLite Wasm conveniently wrapped as an ES Module.
## Bug reports
> [!Warning]
>
> This project wraps the code of
> [SQLite Wasm](https://sqlite.org/wasm/doc/trunk/index.md) with _no_ changes,
> apart from added TypeScript types. Please do _not_ file issues or feature
> requests regarding the underlying SQLite Wasm code here. Instead, please
> follow the
> [SQLite bug filing instructions](https://www.sqlite.org/src/wiki?name=Bug+Reports).
> Filing TypeScript type related issues and feature requests is fine.
## Node.js support
> [!Warning]
>
> Node.js is currently only supported for in-memory databases without
> persistence.
## Installation
```bash
npm install @sqlite.org/sqlite-wasm
```
## Usage
There are three ways to use SQLite Wasm:
- [in the main thread with a wrapped worker](#in-a-wrapped-worker-with-opfs-if-available)
(🏆 preferred option)
- [in a worker](#in-a-worker-with-opfs-if-available)
- [in the main thread](#in-the-main-thread-without-opfs)
Only the worker versions allow you to use the origin private file system (OPFS)
storage back-end.
### In a wrapped worker (with OPFS if available):
> [!Warning]
>
> For this to work, you need to set the following headers on your server:
>
> `Cross-Origin-Opener-Policy: same-origin`
>
> `Cross-Origin-Embedder-Policy: require-corp`
```js
import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';
const log = console.log;
const error = console.error;
const initializeSQLite = async () => {
try {
log('Loading and initializing SQLite3 module...');
const promiser = await new Promise((resolve) => {
const _promiser = sqlite3Worker1Promiser({
onready: () => resolve(_promiser),
});
});
log('Done initializing. Running demo...');
const configResponse = await promiser('config-get', {});
log('Running SQLite3 version', configResponse.result.version.libVersion);
const openResponse = await promiser('open', {
filename: 'file:mydb.sqlite3?vfs=opfs',
});
const { dbId } = openResponse;
log(
'OPFS is available, created persisted database at',
openResponse.result.filename.replace(/^file:(.*?)\?vfs=opfs$/, '$1'),
);
// Your SQLite code here.
} catch (err) {
if (!(err instanceof Error)) {
err = new Error(err.result.message);
}
error(err.name, err.message);
}
};
initializeSQLite();
```
The `promiser` object above implements the
[Worker1 API](https://sqlite.org/wasm/doc/trunk/api-worker1.md#worker1-methods).
### In a worker (with OPFS if available):
> [!Warning]
>
> For this to work, you need to set the following headers on your server:
>
> `Cross-Origin-Opener-Policy: same-origin`
>
> `Cross-Origin-Embedder-Policy: require-corp`
```js
// In `main.js`.
const worker = new Worker('worker.js', { type: 'module' });
```
```js
// In `worker.js`.
import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
const log = console.log;
const error = console.error;
const start = (sqlite3) => {
log('Running SQLite3 version', sqlite3.version.libVersion);
const db =
'opfs' in sqlite3
? new sqlite3.oo1.OpfsDb('/mydb.sqlite3')
: new sqlite3.oo1.DB('/mydb.sqlite3', 'ct');
log(
'opfs' in sqlite3
? `OPFS is available, created persisted database at ${db.filename}`
: `OPFS is not available, created transient database ${db.filename}`,
);
// Your SQLite code here.
};
const initializeSQLite = async () => {
try {
log('Loading and initializing SQLite3 module...');
const sqlite3 = await sqlite3InitModule({ print: log, printErr: error });
log('Done initializing. Running demo...');
start(sqlite3);
} catch (err) {
error('Initialization error:', err.name, err.message);
}
};
initializeSQLite();
```
The `db` object above implements the
[Object Oriented API #1](https://sqlite.org/wasm/doc/trunk/api-oo1.md).
### In the main thread (without OPFS):
```js
import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
const log = console.log;
const error = console.error;
const start = (sqlite3) => {
log('Running SQLite3 version', sqlite3.version.libVersion);
const db = new sqlite3.oo1.DB('/mydb.sqlite3', 'ct');
// Your SQLite code here.
};
const initializeSQLite = async () => {
try {
log('Loading and initializing SQLite3 module...');
const sqlite3 = await sqlite3InitModule({
print: log,
printErr: error,
});
log('Done initializing. Running demo...');
start(sqlite3);
} catch (err) {
error('Initialization error:', err.name, err.message);
}
};
initializeSQLite();
```
The `db` object above implements the
[Object Oriented API #1](https://sqlite.org/wasm/doc/trunk/api-oo1.md).
## Usage with vite
If you are using [vite](https://vitejs.dev/), you need to add the following
config option in `vite.config.js`:
```js
import { defineConfig } from 'vite';
export default defineConfig({
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
},
optimizeDeps: {
exclude: ['@sqlite.org/sqlite-wasm'],
},
});
```
Check out a
[sample project](https://stackblitz.com/edit/vitejs-vite-ttrbwh?file=main.js)
that shows this in action.
## Demo
See the [demo](https://github.com/sqlite/sqlite-wasm/tree/main/demo) folder for
examples of how to use this in the main thread and in a worker. (Note that the
worker variant requires special HTTP headers, so it can't be hosted on GitHub
Pages.) An example that shows how to use this with vite is available on
[StackBlitz](https://stackblitz.com/edit/vitejs-vite-ttrbwh?file=main.js).
## Projects using this package
See the list of
[npm dependents](https://www.npmjs.com/browse/depended/@sqlite.org/sqlite-wasm)
for this package.
## Deploying a new version
(These steps can only be executed by maintainers.)
1. Update the version number in `package.json` reflecting the current
[SQLite version number](https://sqlite.org/download.html) and add a build
identifier suffix like `-build1`. The complete version number should read
something like `3.41.2-build1`.
1. Run `npm run build` to build the ES Module. This downloads the latest SQLite
Wasm binary and builds the ES Module.
1. Run `npm run deploy` to commit the changes, push to GitHub, and publish the
new version to npm.
## License
Apache 2.0.
## Acknowledgements
This project is based on [SQLite Wasm](https://sqlite.org/wasm), which it
conveniently wraps as an ES Module and publishes to npm as
[`@sqlite.org/sqlite-wasm`](https://www.npmjs.com/package/@sqlite.org/sqlite-wasm).
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env node
import fs from 'fs';
import fetch from 'node-fetch';
import decompress from 'decompress';
async function getSqliteWasmDownloadLink() {
const response = await fetch('https://sqlite.org/download.html');
const html = await response.text();
const sqliteWasmLink =
'https://sqlite.org/' +
html
.replace(
/^.*?<!-- Download product data for scripts to read(.*?)-->.*?$/gms,
'$1',
)
.split(/\n/)
.filter((row) => /sqlite-wasm/.test(row))[0]
.split(/,/)[2];
console.log(`Found SQLite Wasm download link: ${sqliteWasmLink}`);
return sqliteWasmLink;
}
async function downloadAndUnzipSqliteWasm(sqliteWasmDownloadLink) {
if (!sqliteWasmDownloadLink) {
throw new Error('Unable to find SQLite Wasm download link');
}
console.log('Downloading and unzipping SQLite Wasm...');
const response = await fetch(sqliteWasmDownloadLink);
if (!response.ok || response.status !== 200) {
throw new Error(
`Unable to download SQLite Wasm from ${sqliteWasmDownloadLink}`,
);
}
const buffer = await response.arrayBuffer();
fs.writeFileSync('sqlite-wasm.zip', Buffer.from(buffer));
const files = await decompress('sqlite-wasm.zip', 'sqlite-wasm', {
strip: 1,
filter: (file) =>
/jswasm/.test(file.path) && /(\.mjs|\.wasm|\.js)$/.test(file.path),
});
console.log(
`Downloaded and unzipped:\n${files
.map((file) => (/\//.test(file.path) ? '‣ ' + file.path + '\n' : ''))
.join('')}`,
);
fs.rmSync('sqlite-wasm.zip');
}
async function main() {
try {
const sqliteWasmLink = await getSqliteWasmDownloadLink();
await downloadAndUnzipSqliteWasm(sqliteWasmLink);
fs.copyFileSync(
'./node_modules/module-workers-polyfill/module-workers-polyfill.min.js',
'./demo/module-workers-polyfill.min.js',
);
} catch (err) {
console.error(err.name, err.message);
}
}
main();
+8118
View File
File diff suppressed because it is too large. Load diff
+7
View File
@@ -0,0 +1,7 @@
import { default as sqlite3InitModule } from './sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs';
import './sqlite-wasm/jswasm/sqlite3-worker1-promiser.mjs';
const sqlite3Worker1Promiser = globalThis.sqlite3Worker1Promiser;
export default sqlite3InitModule;
export { sqlite3Worker1Promiser };
+3
View File
@@ -0,0 +1,3 @@
import { default as sqlite3InitModule } from './sqlite-wasm/jswasm/sqlite3-node.mjs';
export default sqlite3InitModule;
+72
View File
@@ -0,0 +1,72 @@
{
"name": "@sqlite.org/sqlite-wasm",
"version": "3.50.4-build1",
"description": "SQLite Wasm conveniently wrapped as an ES Module.",
"keywords": [
"sqlite",
"sqlite3",
"sqlite-wasm",
"sqlite3-wasm",
"webassembly",
"wasm",
"esm",
"opfs",
"origin-private-file-system"
],
"main": "index.mjs",
"node": "node.mjs",
"type": "module",
"files": [
"index.d.ts",
"index.mjs",
"node.mjs",
"sqlite-wasm/"
],
"types": "index.d.ts",
"exports": {
".": {
"types": "./index.d.ts",
"node": "./node.mjs",
"import": "./index.mjs",
"main": "./index.mjs",
"browser": "./index.mjs"
},
"./package.json": "./package.json",
"./sqlite3.wasm": "./sqlite-wasm/jswasm/sqlite3.wasm"
},
"bin": {
"sqlite-wasm": "bin/index.js"
},
"scripts": {
"publint": "npx publint",
"check-types": "tsc",
"clean": "shx rm -rf sqlite-wasm",
"build": "npm run clean && node bin/index.js",
"start": "npx http-server --coop",
"start:node": "cd demo && node node.mjs",
"fix": "npx prettier . --write",
"prepublishOnly": "npm run build && npm run fix && npm run publint && npm run check-types",
"deploy": "npm run prepublishOnly && git add . && git commit -am 'New release' && git push && npm publish --access public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/sqlite/sqlite-wasm.git"
},
"author": "Thomas Steiner (tomac@google.com)",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/sqlite/sqlite-wasm/issues"
},
"homepage": "https://github.com/sqlite/sqlite-wasm#readme",
"devDependencies": {
"decompress": "^4.2.1",
"http-server": "github:vapier/http-server",
"module-workers-polyfill": "^0.3.2",
"node-fetch": "^3.3.2",
"prettier": "^3.6.2",
"prettier-plugin-jsdoc": "^1.3.3",
"publint": "^0.3.12",
"shx": "^0.4.0",
"typescript": "^5.9.2"
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,691 @@
/*
2022-09-16
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
A Worker which manages asynchronous OPFS handles on behalf of a
synchronous API which controls it via a combination of Worker
messages, SharedArrayBuffer, and Atomics. It is the asynchronous
counterpart of the API defined in sqlite3-vfs-opfs.js.
Highly indebted to:
https://github.com/rhashimoto/wa-sqlite/blob/master/src/examples/OriginPrivateFileSystemVFS.js
for demonstrating how to use the OPFS APIs.
This file is to be loaded as a Worker. It does not have any direct
access to the sqlite3 JS/WASM bits, so any bits which it needs (most
notably SQLITE_xxx integer codes) have to be imported into it via an
initialization process.
This file represents an implementation detail of a larger piece of
code, and not a public interface. Its details may change at any time
and are not intended to be used by any client-level code.
2022-11-27: Chrome v108 changes some async methods to synchronous, as
documented at:
https://developer.chrome.com/blog/sync-methods-for-accesshandles/
Firefox v111 and Safari 16.4, both released in March 2023, also
include this.
We cannot change to the sync forms at this point without breaking
clients who use Chrome v104-ish or higher. truncate(), getSize(),
flush(), and close() are now (as of v108) synchronous. Calling them
with an "await", as we have to for the async forms, is still legal
with the sync forms but is superfluous. Calling the async forms with
theFunc().then(...) is not compatible with the change to
synchronous, but we do do not use those APIs that way. i.e. we don't
_need_ to change anything for this, but at some point (after Chrome
versions (approximately) 104-107 are extinct) should change our
usage of those methods to remove the "await".
*/
'use strict';
const wPost = (type, ...args) => postMessage({ type, payload: args });
const installAsyncProxy = function () {
const toss = function (...args) {
throw new Error(args.join(' '));
};
if (globalThis.window === globalThis) {
toss(
'This code cannot run from the main thread.',
'Load it as a Worker from a separate Worker.',
);
} else if (!navigator?.storage?.getDirectory) {
toss('This API requires navigator.storage.getDirectory.');
}
const state = Object.create(null);
state.verbose = 1;
const loggers = {
0: console.error.bind(console),
1: console.warn.bind(console),
2: console.log.bind(console),
};
const logImpl = (level, ...args) => {
if (state.verbose > level) loggers[level]('OPFS asyncer:', ...args);
};
const log = (...args) => logImpl(2, ...args);
const warn = (...args) => logImpl(1, ...args);
const error = (...args) => logImpl(0, ...args);
const __openFiles = Object.create(null);
const __implicitLocks = new Set();
const getResolvedPath = function (filename, splitIt) {
const p = new URL(filename, 'file://irrelevant').pathname;
return splitIt ? p.split('/').filter((v) => !!v) : p;
};
const getDirForFilename = async function f(absFilename, createDirs = false) {
const path = getResolvedPath(absFilename, true);
const filename = path.pop();
let dh = state.rootDir;
for (const dirName of path) {
if (dirName) {
dh = await dh.getDirectoryHandle(dirName, { create: !!createDirs });
}
}
return [dh, filename];
};
const closeSyncHandle = async (fh) => {
if (fh.syncHandle) {
log('Closing sync handle for', fh.filenameAbs);
const h = fh.syncHandle;
delete fh.syncHandle;
delete fh.xLock;
__implicitLocks.delete(fh.fid);
return h.close();
}
};
const closeSyncHandleNoThrow = async (fh) => {
try {
await closeSyncHandle(fh);
} catch (e) {
warn('closeSyncHandleNoThrow() ignoring:', e, fh);
}
};
const releaseImplicitLocks = async () => {
if (__implicitLocks.size) {
for (const fid of __implicitLocks) {
const fh = __openFiles[fid];
await closeSyncHandleNoThrow(fh);
log('Auto-unlocked', fid, fh.filenameAbs);
}
}
};
const releaseImplicitLock = async (fh) => {
if (fh.releaseImplicitLocks && __implicitLocks.has(fh.fid)) {
return closeSyncHandleNoThrow(fh);
}
};
class GetSyncHandleError extends Error {
constructor(errorObject, ...msg) {
super(
[...msg, ': ' + errorObject.name + ':', errorObject.message].join(' '),
{
cause: errorObject,
},
);
this.name = 'GetSyncHandleError';
}
}
GetSyncHandleError.convertRc = (e, rc) => {
if (e instanceof GetSyncHandleError) {
if (
e.cause.name === 'NoModificationAllowedError' ||
(e.cause.name === 'DOMException' &&
0 === e.cause.message.indexOf('Access Handles cannot'))
) {
return state.sq3Codes.SQLITE_BUSY;
} else if ('NotFoundError' === e.cause.name) {
return state.sq3Codes.SQLITE_CANTOPEN;
}
} else if ('NotFoundError' === e?.name) {
return state.sq3Codes.SQLITE_CANTOPEN;
}
return rc;
};
const getSyncHandle = async (fh, opName) => {
if (!fh.syncHandle) {
const t = performance.now();
log('Acquiring sync handle for', fh.filenameAbs);
const maxTries = 6,
msBase = state.asyncIdleWaitTime * 2;
let i = 1,
ms = msBase;
for (; true; ms = msBase * ++i) {
try {
fh.syncHandle = await fh.fileHandle.createSyncAccessHandle();
break;
} catch (e) {
if (i === maxTries) {
throw new GetSyncHandleError(
e,
'Error getting sync handle for',
opName + '().',
maxTries,
'attempts failed.',
fh.filenameAbs,
);
}
warn(
'Error getting sync handle for',
opName + '(). Waiting',
ms,
'ms and trying again.',
fh.filenameAbs,
e,
);
Atomics.wait(state.sabOPView, state.opIds.retry, 0, ms);
}
}
log(
'Got',
opName + '() sync handle for',
fh.filenameAbs,
'in',
performance.now() - t,
'ms',
);
if (!fh.xLock) {
__implicitLocks.add(fh.fid);
log(
'Acquired implicit lock for',
opName + '()',
fh.fid,
fh.filenameAbs,
);
}
}
return fh.syncHandle;
};
const storeAndNotify = (opName, value) => {
log(opName + '() => notify(', value, ')');
Atomics.store(state.sabOPView, state.opIds.rc, value);
Atomics.notify(state.sabOPView, state.opIds.rc);
};
const affirmNotRO = function (opName, fh) {
if (fh.readOnly) toss(opName + '(): File is read-only: ' + fh.filenameAbs);
};
let flagAsyncShutdown = false;
const vfsAsyncImpls = {
'opfs-async-shutdown': async () => {
flagAsyncShutdown = true;
storeAndNotify('opfs-async-shutdown', 0);
},
mkdir: async (dirname) => {
let rc = 0;
try {
await getDirForFilename(dirname + '/filepart', true);
} catch (e) {
state.s11n.storeException(2, e);
rc = state.sq3Codes.SQLITE_IOERR;
}
storeAndNotify('mkdir', rc);
},
xAccess: async (filename) => {
let rc = 0;
try {
const [dh, fn] = await getDirForFilename(filename);
await dh.getFileHandle(fn);
} catch (e) {
state.s11n.storeException(2, e);
rc = state.sq3Codes.SQLITE_IOERR;
}
storeAndNotify('xAccess', rc);
},
xClose: async function (fid) {
const opName = 'xClose';
__implicitLocks.delete(fid);
const fh = __openFiles[fid];
let rc = 0;
if (fh) {
delete __openFiles[fid];
await closeSyncHandle(fh);
if (fh.deleteOnClose) {
try {
await fh.dirHandle.removeEntry(fh.filenamePart);
} catch (e) {
warn('Ignoring dirHandle.removeEntry() failure of', fh, e);
}
}
} else {
state.s11n.serialize();
rc = state.sq3Codes.SQLITE_NOTFOUND;
}
storeAndNotify(opName, rc);
},
xDelete: async function (...args) {
const rc = await vfsAsyncImpls.xDeleteNoWait(...args);
storeAndNotify('xDelete', rc);
},
xDeleteNoWait: async function (filename, syncDir = 0, recursive = false) {
let rc = 0;
try {
while (filename) {
const [hDir, filenamePart] = await getDirForFilename(filename, false);
if (!filenamePart) break;
await hDir.removeEntry(filenamePart, { recursive });
if (0x1234 !== syncDir) break;
recursive = false;
filename = getResolvedPath(filename, true);
filename.pop();
filename = filename.join('/');
}
} catch (e) {
state.s11n.storeException(2, e);
rc = state.sq3Codes.SQLITE_IOERR_DELETE;
}
return rc;
},
xFileSize: async function (fid) {
const fh = __openFiles[fid];
let rc = 0;
try {
const sz = await (await getSyncHandle(fh, 'xFileSize')).getSize();
state.s11n.serialize(Number(sz));
} catch (e) {
state.s11n.storeException(1, e);
rc = GetSyncHandleError.convertRc(e, state.sq3Codes.SQLITE_IOERR);
}
await releaseImplicitLock(fh);
storeAndNotify('xFileSize', rc);
},
xLock: async function (fid, lockType) {
const fh = __openFiles[fid];
let rc = 0;
const oldLockType = fh.xLock;
fh.xLock = lockType;
if (!fh.syncHandle) {
try {
await getSyncHandle(fh, 'xLock');
__implicitLocks.delete(fid);
} catch (e) {
state.s11n.storeException(1, e);
rc = GetSyncHandleError.convertRc(
e,
state.sq3Codes.SQLITE_IOERR_LOCK,
);
fh.xLock = oldLockType;
}
}
storeAndNotify('xLock', rc);
},
xOpen: async function (fid, filename, flags, opfsFlags) {
const opName = 'xOpen';
const create = state.sq3Codes.SQLITE_OPEN_CREATE & flags;
try {
let hDir, filenamePart;
try {
[hDir, filenamePart] = await getDirForFilename(filename, !!create);
} catch (e) {
state.s11n.storeException(1, e);
storeAndNotify(opName, state.sq3Codes.SQLITE_NOTFOUND);
return;
}
if (state.opfsFlags.OPFS_UNLINK_BEFORE_OPEN & opfsFlags) {
try {
await hDir.removeEntry(filenamePart);
} catch (e) {}
}
const hFile = await hDir.getFileHandle(filenamePart, { create });
const fh = Object.assign(Object.create(null), {
fid: fid,
filenameAbs: filename,
filenamePart: filenamePart,
dirHandle: hDir,
fileHandle: hFile,
sabView: state.sabFileBufView,
readOnly: !create && !!(state.sq3Codes.SQLITE_OPEN_READONLY & flags),
deleteOnClose: !!(state.sq3Codes.SQLITE_OPEN_DELETEONCLOSE & flags),
});
fh.releaseImplicitLocks =
opfsFlags & state.opfsFlags.OPFS_UNLOCK_ASAP ||
state.opfsFlags.defaultUnlockAsap;
__openFiles[fid] = fh;
storeAndNotify(opName, 0);
} catch (e) {
error(opName, e);
state.s11n.storeException(1, e);
storeAndNotify(opName, state.sq3Codes.SQLITE_IOERR);
}
},
xRead: async function (fid, n, offset64) {
let rc = 0,
nRead;
const fh = __openFiles[fid];
try {
nRead = (await getSyncHandle(fh, 'xRead')).read(
fh.sabView.subarray(0, n),
{ at: Number(offset64) },
);
if (nRead < n) {
fh.sabView.fill(0, nRead, n);
rc = state.sq3Codes.SQLITE_IOERR_SHORT_READ;
}
} catch (e) {
error('xRead() failed', e, fh);
state.s11n.storeException(1, e);
rc = GetSyncHandleError.convertRc(e, state.sq3Codes.SQLITE_IOERR_READ);
}
await releaseImplicitLock(fh);
storeAndNotify('xRead', rc);
},
xSync: async function (fid, flags) {
const fh = __openFiles[fid];
let rc = 0;
if (!fh.readOnly && fh.syncHandle) {
try {
await fh.syncHandle.flush();
} catch (e) {
state.s11n.storeException(2, e);
rc = state.sq3Codes.SQLITE_IOERR_FSYNC;
}
}
storeAndNotify('xSync', rc);
},
xTruncate: async function (fid, size) {
let rc = 0;
const fh = __openFiles[fid];
try {
affirmNotRO('xTruncate', fh);
await (await getSyncHandle(fh, 'xTruncate')).truncate(size);
} catch (e) {
error('xTruncate():', e, fh);
state.s11n.storeException(2, e);
rc = GetSyncHandleError.convertRc(
e,
state.sq3Codes.SQLITE_IOERR_TRUNCATE,
);
}
await releaseImplicitLock(fh);
storeAndNotify('xTruncate', rc);
},
xUnlock: async function (fid, lockType) {
let rc = 0;
const fh = __openFiles[fid];
if (fh.syncHandle && state.sq3Codes.SQLITE_LOCK_NONE === lockType) {
try {
await closeSyncHandle(fh);
} catch (e) {
state.s11n.storeException(1, e);
rc = state.sq3Codes.SQLITE_IOERR_UNLOCK;
}
}
storeAndNotify('xUnlock', rc);
},
xWrite: async function (fid, n, offset64) {
let rc;
const fh = __openFiles[fid];
try {
affirmNotRO('xWrite', fh);
rc =
n ===
(await getSyncHandle(fh, 'xWrite')).write(fh.sabView.subarray(0, n), {
at: Number(offset64),
})
? 0
: state.sq3Codes.SQLITE_IOERR_WRITE;
} catch (e) {
error('xWrite():', e, fh);
state.s11n.storeException(1, e);
rc = GetSyncHandleError.convertRc(e, state.sq3Codes.SQLITE_IOERR_WRITE);
}
await releaseImplicitLock(fh);
storeAndNotify('xWrite', rc);
},
};
const initS11n = () => {
if (state.s11n) return state.s11n;
const textDecoder = new TextDecoder(),
textEncoder = new TextEncoder('utf-8'),
viewU8 = new Uint8Array(
state.sabIO,
state.sabS11nOffset,
state.sabS11nSize,
),
viewDV = new DataView(
state.sabIO,
state.sabS11nOffset,
state.sabS11nSize,
);
state.s11n = Object.create(null);
const TypeIds = Object.create(null);
TypeIds.number = {
id: 1,
size: 8,
getter: 'getFloat64',
setter: 'setFloat64',
};
TypeIds.bigint = {
id: 2,
size: 8,
getter: 'getBigInt64',
setter: 'setBigInt64',
};
TypeIds.boolean = {
id: 3,
size: 4,
getter: 'getInt32',
setter: 'setInt32',
};
TypeIds.string = { id: 4 };
const getTypeId = (v) =>
TypeIds[typeof v] ||
toss('Maintenance required: this value type cannot be serialized.', v);
const getTypeIdById = (tid) => {
switch (tid) {
case TypeIds.number.id:
return TypeIds.number;
case TypeIds.bigint.id:
return TypeIds.bigint;
case TypeIds.boolean.id:
return TypeIds.boolean;
case TypeIds.string.id:
return TypeIds.string;
default:
toss('Invalid type ID:', tid);
}
};
state.s11n.deserialize = function (clear = false) {
const argc = viewU8[0];
const rc = argc ? [] : null;
if (argc) {
const typeIds = [];
let offset = 1,
i,
n,
v;
for (i = 0; i < argc; ++i, ++offset) {
typeIds.push(getTypeIdById(viewU8[offset]));
}
for (i = 0; i < argc; ++i) {
const t = typeIds[i];
if (t.getter) {
v = viewDV[t.getter](offset, state.littleEndian);
offset += t.size;
} else {
n = viewDV.getInt32(offset, state.littleEndian);
offset += 4;
v = textDecoder.decode(viewU8.slice(offset, offset + n));
offset += n;
}
rc.push(v);
}
}
if (clear) viewU8[0] = 0;
return rc;
};
state.s11n.serialize = function (...args) {
if (args.length) {
const typeIds = [];
let i = 0,
offset = 1;
viewU8[0] = args.length & 0xff;
for (; i < args.length; ++i, ++offset) {
typeIds.push(getTypeId(args[i]));
viewU8[offset] = typeIds[i].id;
}
for (i = 0; i < args.length; ++i) {
const t = typeIds[i];
if (t.setter) {
viewDV[t.setter](offset, args[i], state.littleEndian);
offset += t.size;
} else {
const s = textEncoder.encode(args[i]);
viewDV.setInt32(offset, s.byteLength, state.littleEndian);
offset += 4;
viewU8.set(s, offset);
offset += s.byteLength;
}
}
} else {
viewU8[0] = 0;
}
};
state.s11n.storeException = state.asyncS11nExceptions
? (priority, e) => {
if (priority <= state.asyncS11nExceptions) {
state.s11n.serialize([e.name, ': ', e.message].join(''));
}
}
: () => {};
return state.s11n;
};
const waitLoop = async function f() {
const opHandlers = Object.create(null);
for (let k of Object.keys(state.opIds)) {
const vi = vfsAsyncImpls[k];
if (!vi) continue;
const o = Object.create(null);
opHandlers[state.opIds[k]] = o;
o.key = k;
o.f = vi;
}
while (!flagAsyncShutdown) {
try {
if (
'not-equal' !==
Atomics.wait(
state.sabOPView,
state.opIds.whichOp,
0,
state.asyncIdleWaitTime,
)
) {
await releaseImplicitLocks();
continue;
}
const opId = Atomics.load(state.sabOPView, state.opIds.whichOp);
Atomics.store(state.sabOPView, state.opIds.whichOp, 0);
const hnd =
opHandlers[opId] ?? toss('No waitLoop handler for whichOp #', opId);
const args = state.s11n.deserialize(true) || [];
if (hnd.f) await hnd.f(...args);
else error('Missing callback for opId', opId);
} catch (e) {
error('in waitLoop():', e);
}
}
};
navigator.storage
.getDirectory()
.then(function (d) {
state.rootDir = d;
globalThis.onmessage = function ({ data }) {
switch (data.type) {
case 'opfs-async-init': {
const opt = data.args;
for (const k in opt) state[k] = opt[k];
state.verbose = opt.verbose ?? 1;
state.sabOPView = new Int32Array(state.sabOP);
state.sabFileBufView = new Uint8Array(
state.sabIO,
0,
state.fileBufferSize,
);
state.sabS11nView = new Uint8Array(
state.sabIO,
state.sabS11nOffset,
state.sabS11nSize,
);
Object.keys(vfsAsyncImpls).forEach((k) => {
if (!Number.isFinite(state.opIds[k])) {
toss('Maintenance required: missing state.opIds[', k, ']');
}
});
initS11n();
log('init state', state);
wPost('opfs-async-inited');
waitLoop();
break;
}
case 'opfs-async-restart':
if (flagAsyncShutdown) {
warn(
'Restarting after opfs-async-shutdown. Might or might not work.',
);
flagAsyncShutdown = false;
waitLoop();
}
break;
}
};
wPost('opfs-async-loaded');
})
.catch((e) => error('error initializing OPFS asyncer:', e));
};
if (!globalThis.SharedArrayBuffer) {
wPost(
'opfs-unavailable',
'Missing SharedArrayBuffer API.',
'The server must emit the COOP/COEP response headers to enable that.',
);
} else if (!globalThis.Atomics) {
wPost(
'opfs-unavailable',
'Missing Atomics API.',
'The server must emit the COOP/COEP response headers to enable that.',
);
} else if (
!globalThis.FileSystemHandle ||
!globalThis.FileSystemDirectoryHandle ||
!globalThis.FileSystemFileHandle ||
!globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle ||
!navigator?.storage?.getDirectory
) {
wPost('opfs-unavailable', 'Missing required OPFS APIs.');
} else {
installAsyncProxy();
}
@@ -0,0 +1,35 @@
/*
2022-05-23
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
This is a JS Worker file for the main sqlite3 api. It loads
sqlite3.js, initializes the module, and postMessage()'s a message
after the module is initialized:
{type: 'sqlite3-api', result: 'worker1-ready'}
This seemingly superfluous level of indirection is necessary when
loading sqlite3.js via a Worker. Instantiating a worker with new
Worker("sqlite.js") will not (cannot) call sqlite3InitModule() to
initialize the module due to a timing/order-of-operations conflict
(and that symbol is not exported in a way that a Worker loading it
that way can see it). Thus JS code wanting to load the sqlite3
Worker-specific API needs to pass _this_ file (or equivalent) to the
Worker constructor and then listen for an event in the form shown
above in order to know when the module has completed initialization.
This file accepts a URL arguments to adjust how it loads sqlite3.js:
- `sqlite3.dir`, if set, treats the given directory name as the
directory from which `sqlite3.js` will be loaded.
*/
import { default as sqlite3InitModule } from './sqlite3-bundler-friendly.mjs';
sqlite3InitModule().then((sqlite3) => sqlite3.initWorker1API());
@@ -0,0 +1,193 @@
/*
2022-08-24
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
This file implements a Promise-based proxy for the sqlite3 Worker
API #1. It is intended to be included either from the main thread or
a Worker, but only if (A) the environment supports nested Workers
and (B) it's _not_ a Worker which loads the sqlite3 WASM/JS
module. This file's features will load that module and provide a
slightly simpler client-side interface than the slightly-lower-level
Worker API does.
This script necessarily exposes one global symbol, but clients may
freely `delete` that symbol after calling it.
*/
'use strict';
globalThis.sqlite3Worker1Promiser = function callee(
config = callee.defaultConfig,
) {
if (1 === arguments.length && 'function' === typeof arguments[0]) {
const f = config;
config = Object.assign(Object.create(null), callee.defaultConfig);
config.onready = f;
} else {
config = Object.assign(Object.create(null), callee.defaultConfig, config);
}
const handlerMap = Object.create(null);
const noop = function () {};
const err = config.onerror || noop;
const debug = config.debug || noop;
const idTypeMap = config.generateMessageId ? undefined : Object.create(null);
const genMsgId =
config.generateMessageId ||
function (msg) {
return (
msg.type + '#' + (idTypeMap[msg.type] = (idTypeMap[msg.type] || 0) + 1)
);
};
const toss = (...args) => {
throw new Error(args.join(' '));
};
if (!config.worker) config.worker = callee.defaultConfig.worker;
if ('function' === typeof config.worker) config.worker = config.worker();
let dbId;
let promiserFunc;
config.worker.onmessage = function (ev) {
ev = ev.data;
debug('worker1.onmessage', ev);
let msgHandler = handlerMap[ev.messageId];
if (!msgHandler) {
if (ev && 'sqlite3-api' === ev.type && 'worker1-ready' === ev.result) {
if (config.onready) config.onready(promiserFunc);
return;
}
msgHandler = handlerMap[ev.type];
if (msgHandler && msgHandler.onrow) {
msgHandler.onrow(ev);
return;
}
if (config.onunhandled) config.onunhandled(arguments[0]);
else err('sqlite3Worker1Promiser() unhandled worker message:', ev);
return;
}
delete handlerMap[ev.messageId];
switch (ev.type) {
case 'error':
msgHandler.reject(ev);
return;
case 'open':
if (!dbId) dbId = ev.dbId;
break;
case 'close':
if (ev.dbId === dbId) dbId = undefined;
break;
default:
break;
}
try {
msgHandler.resolve(ev);
} catch (e) {
msgHandler.reject(e);
}
};
return (promiserFunc = function () {
let msg;
if (1 === arguments.length) {
msg = arguments[0];
} else if (2 === arguments.length) {
msg = Object.create(null);
msg.type = arguments[0];
msg.args = arguments[1];
msg.dbId = msg.args.dbId;
} else {
toss('Invalid arguments for sqlite3Worker1Promiser()-created factory.');
}
if (!msg.dbId && msg.type !== 'open') msg.dbId = dbId;
msg.messageId = genMsgId(msg);
msg.departureTime = performance.now();
const proxy = Object.create(null);
proxy.message = msg;
let rowCallbackId;
if ('exec' === msg.type && msg.args) {
if ('function' === typeof msg.args.callback) {
rowCallbackId = msg.messageId + ':row';
proxy.onrow = msg.args.callback;
msg.args.callback = rowCallbackId;
handlerMap[rowCallbackId] = proxy;
} else if ('string' === typeof msg.args.callback) {
toss(
'exec callback may not be a string when using the Promise interface.',
);
}
}
let p = new Promise(function (resolve, reject) {
proxy.resolve = resolve;
proxy.reject = reject;
handlerMap[msg.messageId] = proxy;
debug(
'Posting',
msg.type,
'message to Worker dbId=' + (dbId || 'default') + ':',
msg,
);
config.worker.postMessage(msg);
});
if (rowCallbackId) p = p.finally(() => delete handlerMap[rowCallbackId]);
return p;
});
};
globalThis.sqlite3Worker1Promiser.defaultConfig = {
worker: function () {
let theJs = 'sqlite3-worker1.js';
if (this.currentScript) {
const src = this.currentScript.src.split('/');
src.pop();
theJs = src.join('/') + '/' + theJs;
} else if (globalThis.location) {
const urlParams = new URL(globalThis.location.href).searchParams;
if (urlParams.has('sqlite3.dir')) {
theJs = urlParams.get('sqlite3.dir') + '/' + theJs;
}
}
return new Worker(theJs + globalThis.location.search);
}.bind({
currentScript: globalThis?.document?.currentScript,
}),
onerror: (...args) => console.error('worker1 promiser error', ...args),
};
sqlite3Worker1Promiser.v2 = function (config) {
let oldFunc;
if ('function' == typeof config) {
oldFunc = config;
config = {};
} else if ('function' === typeof config?.onready) {
oldFunc = config.onready;
delete config.onready;
}
const promiseProxy = Object.create(null);
config = Object.assign(config || Object.create(null), {
onready: async function (func) {
try {
if (oldFunc) await oldFunc(func);
promiseProxy.resolve(func);
} catch (e) {
promiseProxy.reject(e);
}
},
});
const p = new Promise(function (resolve, reject) {
promiseProxy.resolve = resolve;
promiseProxy.reject = reject;
});
try {
this.original(config);
} catch (e) {
promiseProxy.reject(e);
}
return p;
}.bind({
original: sqlite3Worker1Promiser,
});
@@ -0,0 +1,187 @@
/*
2022-08-24
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
This file implements a Promise-based proxy for the sqlite3 Worker
API #1. It is intended to be included either from the main thread or
a Worker, but only if (A) the environment supports nested Workers
and (B) it's _not_ a Worker which loads the sqlite3 WASM/JS
module. This file's features will load that module and provide a
slightly simpler client-side interface than the slightly-lower-level
Worker API does.
This script necessarily exposes one global symbol, but clients may
freely `delete` that symbol after calling it.
*/
'use strict';
globalThis.sqlite3Worker1Promiser = function callee(
config = callee.defaultConfig,
) {
if (1 === arguments.length && 'function' === typeof arguments[0]) {
const f = config;
config = Object.assign(Object.create(null), callee.defaultConfig);
config.onready = f;
} else {
config = Object.assign(Object.create(null), callee.defaultConfig, config);
}
const handlerMap = Object.create(null);
const noop = function () {};
const err = config.onerror || noop;
const debug = config.debug || noop;
const idTypeMap = config.generateMessageId ? undefined : Object.create(null);
const genMsgId =
config.generateMessageId ||
function (msg) {
return (
msg.type + '#' + (idTypeMap[msg.type] = (idTypeMap[msg.type] || 0) + 1)
);
};
const toss = (...args) => {
throw new Error(args.join(' '));
};
if (!config.worker) config.worker = callee.defaultConfig.worker;
if ('function' === typeof config.worker) config.worker = config.worker();
let dbId;
let promiserFunc;
config.worker.onmessage = function (ev) {
ev = ev.data;
debug('worker1.onmessage', ev);
let msgHandler = handlerMap[ev.messageId];
if (!msgHandler) {
if (ev && 'sqlite3-api' === ev.type && 'worker1-ready' === ev.result) {
if (config.onready) config.onready(promiserFunc);
return;
}
msgHandler = handlerMap[ev.type];
if (msgHandler && msgHandler.onrow) {
msgHandler.onrow(ev);
return;
}
if (config.onunhandled) config.onunhandled(arguments[0]);
else err('sqlite3Worker1Promiser() unhandled worker message:', ev);
return;
}
delete handlerMap[ev.messageId];
switch (ev.type) {
case 'error':
msgHandler.reject(ev);
return;
case 'open':
if (!dbId) dbId = ev.dbId;
break;
case 'close':
if (ev.dbId === dbId) dbId = undefined;
break;
default:
break;
}
try {
msgHandler.resolve(ev);
} catch (e) {
msgHandler.reject(e);
}
};
return (promiserFunc = function () {
let msg;
if (1 === arguments.length) {
msg = arguments[0];
} else if (2 === arguments.length) {
msg = Object.create(null);
msg.type = arguments[0];
msg.args = arguments[1];
msg.dbId = msg.args.dbId;
} else {
toss('Invalid arguments for sqlite3Worker1Promiser()-created factory.');
}
if (!msg.dbId && msg.type !== 'open') msg.dbId = dbId;
msg.messageId = genMsgId(msg);
msg.departureTime = performance.now();
const proxy = Object.create(null);
proxy.message = msg;
let rowCallbackId;
if ('exec' === msg.type && msg.args) {
if ('function' === typeof msg.args.callback) {
rowCallbackId = msg.messageId + ':row';
proxy.onrow = msg.args.callback;
msg.args.callback = rowCallbackId;
handlerMap[rowCallbackId] = proxy;
} else if ('string' === typeof msg.args.callback) {
toss(
'exec callback may not be a string when using the Promise interface.',
);
}
}
let p = new Promise(function (resolve, reject) {
proxy.resolve = resolve;
proxy.reject = reject;
handlerMap[msg.messageId] = proxy;
debug(
'Posting',
msg.type,
'message to Worker dbId=' + (dbId || 'default') + ':',
msg,
);
config.worker.postMessage(msg);
});
if (rowCallbackId) p = p.finally(() => delete handlerMap[rowCallbackId]);
return p;
});
};
globalThis.sqlite3Worker1Promiser.defaultConfig = {
worker: function () {
return new Worker(
new URL('sqlite3-worker1-bundler-friendly.mjs', import.meta.url),
{
type: 'module',
},
);
},
onerror: (...args) => console.error('worker1 promiser error', ...args),
};
sqlite3Worker1Promiser.v2 = function (config) {
let oldFunc;
if ('function' == typeof config) {
oldFunc = config;
config = {};
} else if ('function' === typeof config?.onready) {
oldFunc = config.onready;
delete config.onready;
}
const promiseProxy = Object.create(null);
config = Object.assign(config || Object.create(null), {
onready: async function (func) {
try {
if (oldFunc) await oldFunc(func);
promiseProxy.resolve(func);
} catch (e) {
promiseProxy.reject(e);
}
},
});
const p = new Promise(function (resolve, reject) {
promiseProxy.resolve = resolve;
promiseProxy.reject = reject;
});
try {
this.original(config);
} catch (e) {
promiseProxy.reject(e);
}
return p;
}.bind({
original: sqlite3Worker1Promiser,
});
export default sqlite3Worker1Promiser.v2;
@@ -0,0 +1,46 @@
/*
2022-05-23
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
This is a JS Worker file for the main sqlite3 api. It loads
sqlite3.js, initializes the module, and postMessage()'s a message
after the module is initialized:
{type: 'sqlite3-api', result: 'worker1-ready'}
This seemingly superfluous level of indirection is necessary when
loading sqlite3.js via a Worker. Instantiating a worker with new
Worker("sqlite.js") will not (cannot) call sqlite3InitModule() to
initialize the module due to a timing/order-of-operations conflict
(and that symbol is not exported in a way that a Worker loading it
that way can see it). Thus JS code wanting to load the sqlite3
Worker-specific API needs to pass _this_ file (or equivalent) to the
Worker constructor and then listen for an event in the form shown
above in order to know when the module has completed initialization.
This file accepts a URL arguments to adjust how it loads sqlite3.js:
- `sqlite3.dir`, if set, treats the given directory name as the
directory from which `sqlite3.js` will be loaded.
*/
'use strict';
{
const urlParams = globalThis.location
? new URL(globalThis.location.href).searchParams
: new URLSearchParams();
let theJs = 'sqlite3.js';
if (urlParams.has('sqlite3.dir')) {
theJs = urlParams.get('sqlite3.dir') + '/' + theJs;
}
importScripts(theJs);
}
sqlite3InitModule().then((sqlite3) => sqlite3.initWorker1API());
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
Binary file not shown.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
+15
View File
@@ -0,0 +1,15 @@
# Installation
> `npm install --save @types/estree`
# Summary
This package contains type definitions for estree (https://github.com/estree/estree).
# Details
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/estree.
### Additional Details
* Last updated: Wed, 06 May 2026 21:01:00 GMT
* Dependencies: none
# Credits
These definitions were written by [RReverser](https://github.com/RReverser).
+167
View File
@@ -0,0 +1,167 @@
declare namespace ESTree {
interface FlowTypeAnnotation extends Node {}
interface FlowBaseTypeAnnotation extends FlowTypeAnnotation {}
interface FlowLiteralTypeAnnotation extends FlowTypeAnnotation, Literal {}
interface FlowDeclaration extends Declaration {}
interface AnyTypeAnnotation extends FlowBaseTypeAnnotation {}
interface ArrayTypeAnnotation extends FlowTypeAnnotation {
elementType: FlowTypeAnnotation;
}
interface BooleanLiteralTypeAnnotation extends FlowLiteralTypeAnnotation {}
interface BooleanTypeAnnotation extends FlowBaseTypeAnnotation {}
interface ClassImplements extends Node {
id: Identifier;
typeParameters?: TypeParameterInstantiation | null;
}
interface ClassProperty {
key: Expression;
value?: Expression | null;
typeAnnotation?: TypeAnnotation | null;
computed: boolean;
static: boolean;
}
interface DeclareClass extends FlowDeclaration {
id: Identifier;
typeParameters?: TypeParameterDeclaration | null;
body: ObjectTypeAnnotation;
extends: InterfaceExtends[];
}
interface DeclareFunction extends FlowDeclaration {
id: Identifier;
}
interface DeclareModule extends FlowDeclaration {
id: Literal | Identifier;
body: BlockStatement;
}
interface DeclareVariable extends FlowDeclaration {
id: Identifier;
}
interface FunctionTypeAnnotation extends FlowTypeAnnotation {
params: FunctionTypeParam[];
returnType: FlowTypeAnnotation;
rest?: FunctionTypeParam | null;
typeParameters?: TypeParameterDeclaration | null;
}
interface FunctionTypeParam {
name: Identifier;
typeAnnotation: FlowTypeAnnotation;
optional: boolean;
}
interface GenericTypeAnnotation extends FlowTypeAnnotation {
id: Identifier | QualifiedTypeIdentifier;
typeParameters?: TypeParameterInstantiation | null;
}
interface InterfaceExtends extends Node {
id: Identifier | QualifiedTypeIdentifier;
typeParameters?: TypeParameterInstantiation | null;
}
interface InterfaceDeclaration extends FlowDeclaration {
id: Identifier;
typeParameters?: TypeParameterDeclaration | null;
extends: InterfaceExtends[];
body: ObjectTypeAnnotation;
}
interface IntersectionTypeAnnotation extends FlowTypeAnnotation {
types: FlowTypeAnnotation[];
}
interface MixedTypeAnnotation extends FlowBaseTypeAnnotation {}
interface NullableTypeAnnotation extends FlowTypeAnnotation {
typeAnnotation: TypeAnnotation;
}
interface NumberLiteralTypeAnnotation extends FlowLiteralTypeAnnotation {}
interface NumberTypeAnnotation extends FlowBaseTypeAnnotation {}
interface StringLiteralTypeAnnotation extends FlowLiteralTypeAnnotation {}
interface StringTypeAnnotation extends FlowBaseTypeAnnotation {}
interface TupleTypeAnnotation extends FlowTypeAnnotation {
types: FlowTypeAnnotation[];
}
interface TypeofTypeAnnotation extends FlowTypeAnnotation {
argument: FlowTypeAnnotation;
}
interface TypeAlias extends FlowDeclaration {
id: Identifier;
typeParameters?: TypeParameterDeclaration | null;
right: FlowTypeAnnotation;
}
interface TypeAnnotation extends Node {
typeAnnotation: FlowTypeAnnotation;
}
interface TypeCastExpression extends Expression {
expression: Expression;
typeAnnotation: TypeAnnotation;
}
interface TypeParameterDeclaration extends Node {
params: Identifier[];
}
interface TypeParameterInstantiation extends Node {
params: FlowTypeAnnotation[];
}
interface ObjectTypeAnnotation extends FlowTypeAnnotation {
properties: ObjectTypeProperty[];
indexers: ObjectTypeIndexer[];
callProperties: ObjectTypeCallProperty[];
}
interface ObjectTypeCallProperty extends Node {
value: FunctionTypeAnnotation;
static: boolean;
}
interface ObjectTypeIndexer extends Node {
id: Identifier;
key: FlowTypeAnnotation;
value: FlowTypeAnnotation;
static: boolean;
}
interface ObjectTypeProperty extends Node {
key: Expression;
value: FlowTypeAnnotation;
optional: boolean;
static: boolean;
}
interface QualifiedTypeIdentifier extends Node {
qualification: Identifier | QualifiedTypeIdentifier;
id: Identifier;
}
interface UnionTypeAnnotation extends FlowTypeAnnotation {
types: FlowTypeAnnotation[];
}
interface VoidTypeAnnotation extends FlowBaseTypeAnnotation {}
}
+694
View File
@@ -0,0 +1,694 @@
// This definition file follows a somewhat unusual format. ESTree allows
// runtime type checks based on the `type` parameter. In order to explain this
// to typescript we want to use discriminated union types:
// https://github.com/Microsoft/TypeScript/pull/9163
//
// For ESTree this is a bit tricky because the high level interfaces like
// Node or Function are pulling double duty. We want to pass common fields down
// to the interfaces that extend them (like Identifier or
// ArrowFunctionExpression), but you can't extend a type union or enforce
// common fields on them. So we've split the high level interfaces into two
// types, a base type which passes down inherited fields, and a type union of
// all types which extend the base type. Only the type union is exported, and
// the union is how other types refer to the collection of inheriting types.
//
// This makes the definitions file here somewhat more difficult to maintain,
// but it has the notable advantage of making ESTree much easier to use as
// an end user.
export interface BaseNodeWithoutComments {
// Every leaf interface that extends BaseNode must specify a type property.
// The type property should be a string literal. For example, Identifier
// has: `type: "Identifier"`
type: string;
loc?: SourceLocation | null | undefined;
range?: [number, number] | undefined;
}
export interface BaseNode extends BaseNodeWithoutComments {
leadingComments?: Comment[] | undefined;
trailingComments?: Comment[] | undefined;
}
export interface NodeMap {
AssignmentProperty: AssignmentProperty;
CatchClause: CatchClause;
Class: Class;
ClassBody: ClassBody;
Expression: Expression;
Function: Function;
Identifier: Identifier;
Literal: Literal;
MethodDefinition: MethodDefinition;
ModuleDeclaration: ModuleDeclaration;
ModuleSpecifier: ModuleSpecifier;
Pattern: Pattern;
PrivateIdentifier: PrivateIdentifier;
Program: Program;
Property: Property;
PropertyDefinition: PropertyDefinition;
SpreadElement: SpreadElement;
Statement: Statement;
Super: Super;
SwitchCase: SwitchCase;
TemplateElement: TemplateElement;
VariableDeclarator: VariableDeclarator;
}
export type Node = NodeMap[keyof NodeMap];
export interface Comment extends BaseNodeWithoutComments {
type: "Line" | "Block";
value: string;
}
export interface SourceLocation {
source?: string | null | undefined;
start: Position;
end: Position;
}
export interface Position {
/** >= 1 */
line: number;
/** >= 0 */
column: number;
}
export interface Program extends BaseNode {
type: "Program";
sourceType: "script" | "module";
body: Array<Directive | Statement | ModuleDeclaration>;
comments?: Comment[] | undefined;
}
export interface Directive extends BaseNode {
type: "ExpressionStatement";
expression: Literal;
directive: string;
}
export interface BaseFunction extends BaseNode {
params: Pattern[];
generator?: boolean | undefined;
async?: boolean | undefined;
// The body is either BlockStatement or Expression because arrow functions
// can have a body that's either. FunctionDeclarations and
// FunctionExpressions have only BlockStatement bodies.
body: BlockStatement | Expression;
}
export type Function = FunctionDeclaration | FunctionExpression | ArrowFunctionExpression;
export type Statement =
| ExpressionStatement
| BlockStatement
| StaticBlock
| EmptyStatement
| DebuggerStatement
| WithStatement
| ReturnStatement
| LabeledStatement
| BreakStatement
| ContinueStatement
| IfStatement
| SwitchStatement
| ThrowStatement
| TryStatement
| WhileStatement
| DoWhileStatement
| ForStatement
| ForInStatement
| ForOfStatement
| Declaration;
export interface BaseStatement extends BaseNode {}
export interface EmptyStatement extends BaseStatement {
type: "EmptyStatement";
}
export interface BlockStatement extends BaseStatement {
type: "BlockStatement";
body: Statement[];
innerComments?: Comment[] | undefined;
}
export interface StaticBlock extends Omit<BlockStatement, "type"> {
type: "StaticBlock";
}
export interface ExpressionStatement extends BaseStatement {
type: "ExpressionStatement";
expression: Expression;
}
export interface IfStatement extends BaseStatement {
type: "IfStatement";
test: Expression;
consequent: Statement;
alternate?: Statement | null | undefined;
}
export interface LabeledStatement extends BaseStatement {
type: "LabeledStatement";
label: Identifier;
body: Statement;
}
export interface BreakStatement extends BaseStatement {
type: "BreakStatement";
label?: Identifier | null | undefined;
}
export interface ContinueStatement extends BaseStatement {
type: "ContinueStatement";
label?: Identifier | null | undefined;
}
export interface WithStatement extends BaseStatement {
type: "WithStatement";
object: Expression;
body: Statement;
}
export interface SwitchStatement extends BaseStatement {
type: "SwitchStatement";
discriminant: Expression;
cases: SwitchCase[];
}
export interface ReturnStatement extends BaseStatement {
type: "ReturnStatement";
argument?: Expression | null | undefined;
}
export interface ThrowStatement extends BaseStatement {
type: "ThrowStatement";
argument: Expression;
}
export interface TryStatement extends BaseStatement {
type: "TryStatement";
block: BlockStatement;
handler?: CatchClause | null | undefined;
finalizer?: BlockStatement | null | undefined;
}
export interface WhileStatement extends BaseStatement {
type: "WhileStatement";
test: Expression;
body: Statement;
}
export interface DoWhileStatement extends BaseStatement {
type: "DoWhileStatement";
body: Statement;
test: Expression;
}
export interface ForStatement extends BaseStatement {
type: "ForStatement";
init?: VariableDeclaration | Expression | null | undefined;
test?: Expression | null | undefined;
update?: Expression | null | undefined;
body: Statement;
}
export interface BaseForXStatement extends BaseStatement {
left: VariableDeclaration | Pattern;
right: Expression;
body: Statement;
}
export interface ForInStatement extends BaseForXStatement {
type: "ForInStatement";
}
export interface DebuggerStatement extends BaseStatement {
type: "DebuggerStatement";
}
export type Declaration = FunctionDeclaration | VariableDeclaration | ClassDeclaration;
export interface BaseDeclaration extends BaseStatement {}
export interface MaybeNamedFunctionDeclaration extends BaseFunction, BaseDeclaration {
type: "FunctionDeclaration";
/** It is null when a function declaration is a part of the `export default function` statement */
id: Identifier | null;
body: BlockStatement;
}
export interface FunctionDeclaration extends MaybeNamedFunctionDeclaration {
id: Identifier;
}
export interface VariableDeclaration extends BaseDeclaration {
type: "VariableDeclaration";
declarations: VariableDeclarator[];
kind: "var" | "let" | "const" | "using" | "await using";
}
export interface VariableDeclarator extends BaseNode {
type: "VariableDeclarator";
id: Pattern;
init?: Expression | null | undefined;
}
export interface ExpressionMap {
ArrayExpression: ArrayExpression;
ArrowFunctionExpression: ArrowFunctionExpression;
AssignmentExpression: AssignmentExpression;
AwaitExpression: AwaitExpression;
BinaryExpression: BinaryExpression;
CallExpression: CallExpression;
ChainExpression: ChainExpression;
ClassExpression: ClassExpression;
ConditionalExpression: ConditionalExpression;
FunctionExpression: FunctionExpression;
Identifier: Identifier;
ImportExpression: ImportExpression;
Literal: Literal;
LogicalExpression: LogicalExpression;
MemberExpression: MemberExpression;
MetaProperty: MetaProperty;
NewExpression: NewExpression;
ObjectExpression: ObjectExpression;
SequenceExpression: SequenceExpression;
TaggedTemplateExpression: TaggedTemplateExpression;
TemplateLiteral: TemplateLiteral;
ThisExpression: ThisExpression;
UnaryExpression: UnaryExpression;
UpdateExpression: UpdateExpression;
YieldExpression: YieldExpression;
}
export type Expression = ExpressionMap[keyof ExpressionMap];
export interface BaseExpression extends BaseNode {}
export type ChainElement = SimpleCallExpression | MemberExpression;
export interface ChainExpression extends BaseExpression {
type: "ChainExpression";
expression: ChainElement;
}
export interface ThisExpression extends BaseExpression {
type: "ThisExpression";
}
export interface ArrayExpression extends BaseExpression {
type: "ArrayExpression";
elements: Array<Expression | SpreadElement | null>;
}
export interface ObjectExpression extends BaseExpression {
type: "ObjectExpression";
properties: Array<Property | SpreadElement>;
}
export interface PrivateIdentifier extends BaseNode {
type: "PrivateIdentifier";
name: string;
}
export interface Property extends BaseNode {
type: "Property";
key: Expression;
value: Expression | Pattern; // Could be an AssignmentProperty
kind: "init" | "get" | "set";
method: boolean;
shorthand: boolean;
computed: boolean;
}
export interface PropertyDefinition extends BaseNode {
type: "PropertyDefinition";
key: Expression | PrivateIdentifier;
value?: Expression | null | undefined;
computed: boolean;
static: boolean;
}
export interface FunctionExpression extends BaseFunction, BaseExpression {
id?: Identifier | null | undefined;
type: "FunctionExpression";
body: BlockStatement;
}
export interface SequenceExpression extends BaseExpression {
type: "SequenceExpression";
expressions: Expression[];
}
export interface UnaryExpression extends BaseExpression {
type: "UnaryExpression";
operator: UnaryOperator;
prefix: true;
argument: Expression;
}
export interface BinaryExpression extends BaseExpression {
type: "BinaryExpression";
operator: BinaryOperator;
left: Expression | PrivateIdentifier;
right: Expression;
}
export interface AssignmentExpression extends BaseExpression {
type: "AssignmentExpression";
operator: AssignmentOperator;
left: Pattern | MemberExpression;
right: Expression;
}
export interface UpdateExpression extends BaseExpression {
type: "UpdateExpression";
operator: UpdateOperator;
argument: Expression;
prefix: boolean;
}
export interface LogicalExpression extends BaseExpression {
type: "LogicalExpression";
operator: LogicalOperator;
left: Expression;
right: Expression;
}
export interface ConditionalExpression extends BaseExpression {
type: "ConditionalExpression";
test: Expression;
alternate: Expression;
consequent: Expression;
}
export interface BaseCallExpression extends BaseExpression {
callee: Expression | Super;
arguments: Array<Expression | SpreadElement>;
}
export type CallExpression = SimpleCallExpression | NewExpression;
export interface SimpleCallExpression extends BaseCallExpression {
type: "CallExpression";
optional: boolean;
}
export interface NewExpression extends BaseCallExpression {
type: "NewExpression";
}
export interface MemberExpression extends BaseExpression, BasePattern {
type: "MemberExpression";
object: Expression | Super;
property: Expression | PrivateIdentifier;
computed: boolean;
optional: boolean;
}
export type Pattern = Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression;
export interface BasePattern extends BaseNode {}
export interface SwitchCase extends BaseNode {
type: "SwitchCase";
test?: Expression | null | undefined;
consequent: Statement[];
}
export interface CatchClause extends BaseNode {
type: "CatchClause";
param: Pattern | null;
body: BlockStatement;
}
export interface Identifier extends BaseNode, BaseExpression, BasePattern {
type: "Identifier";
name: string;
}
export type Literal = SimpleLiteral | RegExpLiteral | BigIntLiteral;
export interface SimpleLiteral extends BaseNode, BaseExpression {
type: "Literal";
value: string | boolean | number | null;
raw?: string | undefined;
}
export interface RegExpLiteral extends BaseNode, BaseExpression {
type: "Literal";
value?: RegExp | null | undefined;
regex: {
pattern: string;
flags: string;
};
raw?: string | undefined;
}
export interface BigIntLiteral extends BaseNode, BaseExpression {
type: "Literal";
value?: bigint | null | undefined;
bigint: string;
raw?: string | undefined;
}
export type UnaryOperator = "-" | "+" | "!" | "~" | "typeof" | "void" | "delete";
export type BinaryOperator =
| "=="
| "!="
| "==="
| "!=="
| "<"
| "<="
| ">"
| ">="
| "<<"
| ">>"
| ">>>"
| "+"
| "-"
| "*"
| "/"
| "%"
| "**"
| "|"
| "^"
| "&"
| "in"
| "instanceof";
export type LogicalOperator = "||" | "&&" | "??";
export type AssignmentOperator =
| "="
| "+="
| "-="
| "*="
| "/="
| "%="
| "**="
| "<<="
| ">>="
| ">>>="
| "|="
| "^="
| "&="
| "||="
| "&&="
| "??=";
export type UpdateOperator = "++" | "--";
export interface ForOfStatement extends BaseForXStatement {
type: "ForOfStatement";
await: boolean;
}
export interface Super extends BaseNode {
type: "Super";
}
export interface SpreadElement extends BaseNode {
type: "SpreadElement";
argument: Expression;
}
export interface ArrowFunctionExpression extends BaseExpression, BaseFunction {
type: "ArrowFunctionExpression";
expression: boolean;
body: BlockStatement | Expression;
}
export interface YieldExpression extends BaseExpression {
type: "YieldExpression";
argument?: Expression | null | undefined;
delegate: boolean;
}
export interface TemplateLiteral extends BaseExpression {
type: "TemplateLiteral";
quasis: TemplateElement[];
expressions: Expression[];
}
export interface TaggedTemplateExpression extends BaseExpression {
type: "TaggedTemplateExpression";
tag: Expression;
quasi: TemplateLiteral;
}
export interface TemplateElement extends BaseNode {
type: "TemplateElement";
tail: boolean;
value: {
/** It is null when the template literal is tagged and the text has an invalid escape (e.g. - tag`\unicode and \u{55}`) */
cooked?: string | null | undefined;
raw: string;
};
}
export interface AssignmentProperty extends Property {
value: Pattern;
kind: "init";
method: boolean; // false
}
export interface ObjectPattern extends BasePattern {
type: "ObjectPattern";
properties: Array<AssignmentProperty | RestElement>;
}
export interface ArrayPattern extends BasePattern {
type: "ArrayPattern";
elements: Array<Pattern | null>;
}
export interface RestElement extends BasePattern {
type: "RestElement";
argument: Pattern;
}
export interface AssignmentPattern extends BasePattern {
type: "AssignmentPattern";
left: Pattern;
right: Expression;
}
export type Class = ClassDeclaration | ClassExpression;
export interface BaseClass extends BaseNode {
superClass?: Expression | null | undefined;
body: ClassBody;
}
export interface ClassBody extends BaseNode {
type: "ClassBody";
body: Array<MethodDefinition | PropertyDefinition | StaticBlock>;
}
export interface MethodDefinition extends BaseNode {
type: "MethodDefinition";
key: Expression | PrivateIdentifier;
value: FunctionExpression;
kind: "constructor" | "method" | "get" | "set";
computed: boolean;
static: boolean;
}
export interface MaybeNamedClassDeclaration extends BaseClass, BaseDeclaration {
type: "ClassDeclaration";
/** It is null when a class declaration is a part of the `export default class` statement */
id: Identifier | null;
}
export interface ClassDeclaration extends MaybeNamedClassDeclaration {
id: Identifier;
}
export interface ClassExpression extends BaseClass, BaseExpression {
type: "ClassExpression";
id?: Identifier | null | undefined;
}
export interface MetaProperty extends BaseExpression {
type: "MetaProperty";
meta: Identifier;
property: Identifier;
}
export type ModuleDeclaration =
| ImportDeclaration
| ExportNamedDeclaration
| ExportDefaultDeclaration
| ExportAllDeclaration;
export interface BaseModuleDeclaration extends BaseNode {}
export type ModuleSpecifier = ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ExportSpecifier;
export interface BaseModuleSpecifier extends BaseNode {
local: Identifier;
}
export interface ImportDeclaration extends BaseModuleDeclaration {
type: "ImportDeclaration";
specifiers: Array<ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier>;
attributes: ImportAttribute[];
source: Literal;
}
export interface ImportSpecifier extends BaseModuleSpecifier {
type: "ImportSpecifier";
imported: Identifier | Literal;
}
export interface ImportAttribute extends BaseNode {
type: "ImportAttribute";
key: Identifier | Literal;
value: Literal;
}
export interface ImportExpression extends BaseExpression {
type: "ImportExpression";
source: Expression;
options?: Expression | null | undefined;
}
export interface ImportDefaultSpecifier extends BaseModuleSpecifier {
type: "ImportDefaultSpecifier";
}
export interface ImportNamespaceSpecifier extends BaseModuleSpecifier {
type: "ImportNamespaceSpecifier";
}
export interface ExportNamedDeclaration extends BaseModuleDeclaration {
type: "ExportNamedDeclaration";
declaration?: Declaration | null | undefined;
specifiers: ExportSpecifier[];
attributes: ImportAttribute[];
source?: Literal | null | undefined;
}
export interface ExportSpecifier extends Omit<BaseModuleSpecifier, "local"> {
type: "ExportSpecifier";
local: Identifier | Literal;
exported: Identifier | Literal;
}
export interface ExportDefaultDeclaration extends BaseModuleDeclaration {
type: "ExportDefaultDeclaration";
declaration: MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration | Expression;
}
export interface ExportAllDeclaration extends BaseModuleDeclaration {
type: "ExportAllDeclaration";
exported: Identifier | Literal | null;
attributes: ImportAttribute[];
source: Literal;
}
export interface AwaitExpression extends BaseExpression {
type: "AwaitExpression";
argument: Expression;
}
+27
View File
@@ -0,0 +1,27 @@
{
"name": "@types/estree",
"version": "1.0.9",
"description": "TypeScript definitions for estree",
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/estree",
"license": "MIT",
"contributors": [
{
"name": "RReverser",
"githubUsername": "RReverser",
"url": "https://github.com/RReverser"
}
],
"main": "",
"types": "index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
"directory": "types/estree"
},
"scripts": {},
"dependencies": {},
"peerDependencies": {},
"typesPublisherContentHash": "db16da859cb0bee641414117047a4becba2e9f39d3e14a6745f887c47ef68482",
"typeScriptVersion": "5.3",
"nonNpm": true
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Evan Wallace
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+3
View File
@@ -0,0 +1,3 @@
# esbuild
This is a JavaScript bundler and minifier. See https://github.com/evanw/esbuild and the [JavaScript API documentation](https://esbuild.github.io/api/) for details.
Generated Vendored Executable
BIN
View File
Binary file not shown.
+300
View File
@@ -0,0 +1,300 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// lib/npm/node-platform.ts
var fs = require("fs");
var os = require("os");
var path = require("path");
var ESBUILD_BINARY_PATH = process.env.ESBUILD_BINARY_PATH || ESBUILD_BINARY_PATH;
var isValidBinaryPath = (x) => !!x && x !== "/usr/bin/esbuild";
var knownWindowsPackages = {
"win32 arm64 LE": "@esbuild/win32-arm64",
"win32 ia32 LE": "@esbuild/win32-ia32",
"win32 x64 LE": "@esbuild/win32-x64"
};
var knownUnixlikePackages = {
"aix ppc64 BE": "@esbuild/aix-ppc64",
"android arm64 LE": "@esbuild/android-arm64",
"darwin arm64 LE": "@esbuild/darwin-arm64",
"darwin x64 LE": "@esbuild/darwin-x64",
"freebsd arm64 LE": "@esbuild/freebsd-arm64",
"freebsd x64 LE": "@esbuild/freebsd-x64",
"linux arm LE": "@esbuild/linux-arm",
"linux arm64 LE": "@esbuild/linux-arm64",
"linux ia32 LE": "@esbuild/linux-ia32",
"linux mips64el LE": "@esbuild/linux-mips64el",
"linux ppc64 LE": "@esbuild/linux-ppc64",
"linux riscv64 LE": "@esbuild/linux-riscv64",
"linux s390x BE": "@esbuild/linux-s390x",
"linux x64 LE": "@esbuild/linux-x64",
"linux loong64 LE": "@esbuild/linux-loong64",
"netbsd arm64 LE": "@esbuild/netbsd-arm64",
"netbsd x64 LE": "@esbuild/netbsd-x64",
"openbsd arm64 LE": "@esbuild/openbsd-arm64",
"openbsd x64 LE": "@esbuild/openbsd-x64",
"sunos x64 LE": "@esbuild/sunos-x64"
};
var knownWebAssemblyFallbackPackages = {
"android arm LE": "@esbuild/android-arm",
"android x64 LE": "@esbuild/android-x64",
"openharmony arm64 LE": "@esbuild/openharmony-arm64"
};
function pkgAndSubpathForCurrentPlatform() {
let pkg;
let subpath;
let isWASM = false;
let platformKey = `${process.platform} ${os.arch()} ${os.endianness()}`;
if (platformKey in knownWindowsPackages) {
pkg = knownWindowsPackages[platformKey];
subpath = "esbuild.exe";
} else if (platformKey in knownUnixlikePackages) {
pkg = knownUnixlikePackages[platformKey];
subpath = "bin/esbuild";
} else if (platformKey in knownWebAssemblyFallbackPackages) {
pkg = knownWebAssemblyFallbackPackages[platformKey];
subpath = "bin/esbuild";
isWASM = true;
} else {
throw new Error(`Unsupported platform: ${platformKey}`);
}
return { pkg, subpath, isWASM };
}
function downloadedBinPath(pkg, subpath) {
const esbuildLibDir = path.dirname(require.resolve("esbuild"));
return path.join(esbuildLibDir, `downloaded-${pkg.replace("/", "-")}-${path.basename(subpath)}`);
}
// lib/npm/node-install.ts
var fs2 = require("fs");
var os2 = require("os");
var path2 = require("path");
var zlib = require("zlib");
var https = require("https");
var crypto = require("crypto");
var child_process = require("child_process");
var packageJSON = require(path2.join(__dirname, "package.json"));
var toPath = path2.join(__dirname, "bin", "esbuild");
var isToPathJS = true;
function validateBinaryVersion(...command) {
command.push("--version");
let stdout;
try {
stdout = child_process.execFileSync(command.shift(), command, {
// Without this, this install script strangely crashes with the error
// "EACCES: permission denied, write" but only on Ubuntu Linux when node is
// installed from the Snap Store. This is not a problem when you download
// the official version of node. The problem appears to be that stderr
// (i.e. file descriptor 2) isn't writable?
//
// More info:
// - https://snapcraft.io/ (what the Snap Store is)
// - https://nodejs.org/dist/ (download the official version of node)
// - https://github.com/evanw/esbuild/issues/1711#issuecomment-1027554035
//
stdio: "pipe"
}).toString().trim();
} catch (err) {
if (os2.platform() === "darwin" && /_SecTrustEvaluateWithError/.test(err + "")) {
let os3 = "this version of macOS";
try {
os3 = "macOS " + child_process.execFileSync("sw_vers", ["-productVersion"]).toString().trim();
} catch {
}
throw new Error(`The "esbuild" package cannot be installed because ${os3} is too outdated.
The Go compiler (which esbuild relies on) no longer supports ${os3},
which means the "esbuild" binary executable can't be run. You can either:
* Update your version of macOS to one that the Go compiler supports
* Use the "esbuild-wasm" package instead of the "esbuild" package
* Build esbuild yourself using an older version of the Go compiler
`);
}
throw err;
}
if (stdout !== packageJSON.version) {
throw new Error(`Expected ${JSON.stringify(packageJSON.version)} but got ${JSON.stringify(stdout)}`);
}
}
function isYarn() {
const { npm_config_user_agent } = process.env;
if (npm_config_user_agent) {
return /\byarn\//.test(npm_config_user_agent);
}
return false;
}
function fetch(url) {
return new Promise((resolve, reject) => {
https.get(url, (res) => {
if ((res.statusCode === 301 || res.statusCode === 302) && res.headers.location)
return fetch(res.headers.location).then(resolve, reject);
if (res.statusCode !== 200)
return reject(new Error(`Server responded with ${res.statusCode}`));
let chunks = [];
res.on("data", (chunk) => chunks.push(chunk));
res.on("end", () => resolve(Buffer.concat(chunks)));
}).on("error", reject);
});
}
function extractFileFromTarGzip(buffer, subpath) {
try {
buffer = zlib.unzipSync(buffer);
} catch (err) {
throw new Error(`Invalid gzip data in archive: ${err && err.message || err}`);
}
let str = (i, n) => String.fromCharCode(...buffer.subarray(i, i + n)).replace(/\0.*$/, "");
let offset = 0;
subpath = `package/${subpath}`;
while (offset < buffer.length) {
let name = str(offset, 100);
let size = parseInt(str(offset + 124, 12), 8);
offset += 512;
if (!isNaN(size) && size >= 0) {
if (name === subpath) return buffer.subarray(offset, offset + size);
offset += size + 511 & ~511;
}
}
throw new Error(`Could not find ${JSON.stringify(subpath)} in archive`);
}
function installUsingNPM(pkg, subpath, binPath) {
const env = { ...process.env, npm_config_global: void 0 };
const esbuildLibDir = path2.dirname(require.resolve("esbuild"));
const installDir = path2.join(esbuildLibDir, "npm-install");
fs2.mkdirSync(installDir);
try {
fs2.writeFileSync(path2.join(installDir, "package.json"), "{}");
child_process.execSync(
`npm install --loglevel=error --prefer-offline --no-audit --progress=false ${pkg}@${packageJSON.version}`,
{ cwd: installDir, stdio: "pipe", env }
);
const installedBinPath = path2.join(installDir, "node_modules", pkg, subpath);
binaryIntegrityCheck(pkg, subpath, fs2.readFileSync(installedBinPath));
fs2.renameSync(installedBinPath, binPath);
} finally {
try {
removeRecursive(installDir);
} catch {
}
}
}
function removeRecursive(dir) {
for (const entry of fs2.readdirSync(dir)) {
const entryPath = path2.join(dir, entry);
let stats;
try {
stats = fs2.lstatSync(entryPath);
} catch {
continue;
}
if (stats.isDirectory()) removeRecursive(entryPath);
else fs2.unlinkSync(entryPath);
}
fs2.rmdirSync(dir);
}
function applyManualBinaryPathOverride(overridePath) {
const pathString = JSON.stringify(overridePath);
fs2.writeFileSync(toPath, `#!/usr/bin/env node
require('child_process').execFileSync(${pathString}, process.argv.slice(2), { stdio: 'inherit' });
`);
const libMain = path2.join(__dirname, "lib", "main.js");
const code = fs2.readFileSync(libMain, "utf8");
fs2.writeFileSync(libMain, `var ESBUILD_BINARY_PATH = ${pathString};
${code}`);
}
function maybeOptimizePackage(binPath, isWASM) {
if (os2.platform() !== "win32" && !isYarn() && !isWASM) {
const tempPath = path2.join(__dirname, "bin-esbuild");
try {
fs2.linkSync(binPath, tempPath);
fs2.renameSync(tempPath, toPath);
isToPathJS = false;
fs2.unlinkSync(tempPath);
} catch {
}
}
}
function binaryIntegrityCheck(pkg, subpath, bytes) {
const hash = crypto.createHash("sha256").update(bytes).digest("hex");
const key = `${pkg}/${subpath}`;
const expected = packageJSON["esbuild.binaryHashes"][key];
if (!expected) throw new Error(`Missing hash for "${key}"`);
if (hash !== expected) throw new Error(`"${hash.slice(0, 8)}..." doesn't match "${expected.slice(0, 8)}..." for "${pkg}"`);
}
async function downloadDirectlyFromNPM(pkg, subpath, binPath) {
const url = `https://registry.npmjs.org/${pkg}/-/${pkg.replace("@esbuild/", "")}-${packageJSON.version}.tgz`;
console.error(`[esbuild] Trying to download ${JSON.stringify(url)}`);
try {
const bytes = extractFileFromTarGzip(await fetch(url), subpath);
binaryIntegrityCheck(pkg, subpath, bytes);
fs2.writeFileSync(binPath, bytes);
fs2.chmodSync(binPath, 493);
} catch (e) {
console.error(`[esbuild] Failed to download ${JSON.stringify(url)}: ${e && e.message || e}`);
throw e;
}
}
async function checkAndPreparePackage() {
if (isValidBinaryPath(ESBUILD_BINARY_PATH)) {
if (!fs2.existsSync(ESBUILD_BINARY_PATH)) {
console.warn(`[esbuild] Ignoring bad configuration: ESBUILD_BINARY_PATH=${ESBUILD_BINARY_PATH}`);
} else {
applyManualBinaryPathOverride(ESBUILD_BINARY_PATH);
return;
}
}
const { pkg, subpath, isWASM } = pkgAndSubpathForCurrentPlatform();
let binPath;
try {
binPath = require.resolve(`${pkg}/${subpath}`);
} catch (e) {
console.error(`[esbuild] Failed to find package "${pkg}" on the file system
This can happen if you use the "--no-optional" flag. The "optionalDependencies"
package.json feature is used by esbuild to install the correct binary executable
for your current platform. This install script will now attempt to work around
this. If that fails, you need to remove the "--no-optional" flag to use esbuild.
`);
if (isWASM) throw new Error(`Failed to install package "${pkg}"`);
binPath = downloadedBinPath(pkg, subpath);
try {
console.error(`[esbuild] Trying to install package "${pkg}" using npm`);
installUsingNPM(pkg, subpath, binPath);
} catch (e2) {
console.error(`[esbuild] Failed to install package "${pkg}" using npm: ${e2 && e2.message || e2}`);
try {
await downloadDirectlyFromNPM(pkg, subpath, binPath);
} catch (e3) {
throw new Error(`Failed to install package "${pkg}"`);
}
}
}
maybeOptimizePackage(binPath, isWASM);
}
checkAndPreparePackage().then(() => {
if (isToPathJS) {
validateBinaryVersion(process.execPath, toPath);
} else {
validateBinaryVersion(toPath);
}
});
+720
View File
@@ -0,0 +1,720 @@
export type Platform = 'browser' | 'node' | 'neutral'
export type Format = 'iife' | 'cjs' | 'esm'
export type Loader = 'base64' | 'binary' | 'copy' | 'css' | 'dataurl' | 'default' | 'empty' | 'file' | 'js' | 'json' | 'jsx' | 'local-css' | 'text' | 'ts' | 'tsx'
export type LogLevel = 'verbose' | 'debug' | 'info' | 'warning' | 'error' | 'silent'
export type LogStyle = 'default' | 'visualstudio'
export type Charset = 'ascii' | 'utf8'
export type Drop = 'console' | 'debugger'
export type AbsPaths = 'code' | 'log' | 'metafile'
interface CommonOptions {
/** Documentation: https://esbuild.github.io/api/#sourcemap */
sourcemap?: boolean | 'linked' | 'inline' | 'external' | 'both'
/** Documentation: https://esbuild.github.io/api/#legal-comments */
legalComments?: 'none' | 'inline' | 'eof' | 'linked' | 'external'
/** Documentation: https://esbuild.github.io/api/#source-root */
sourceRoot?: string
/** Documentation: https://esbuild.github.io/api/#sources-content */
sourcesContent?: boolean
/** Documentation: https://esbuild.github.io/api/#format */
format?: Format
/** Documentation: https://esbuild.github.io/api/#global-name */
globalName?: string
/** Documentation: https://esbuild.github.io/api/#target */
target?: string | string[]
/** Documentation: https://esbuild.github.io/api/#supported */
supported?: Record<string, boolean>
/** Documentation: https://esbuild.github.io/api/#platform */
platform?: Platform
/** Documentation: https://esbuild.github.io/api/#mangle-props */
mangleProps?: RegExp
/** Documentation: https://esbuild.github.io/api/#mangle-props */
reserveProps?: RegExp
/** Documentation: https://esbuild.github.io/api/#mangle-props */
mangleQuoted?: boolean
/** Documentation: https://esbuild.github.io/api/#mangle-props */
mangleCache?: Record<string, string | false>
/** Documentation: https://esbuild.github.io/api/#drop */
drop?: Drop[]
/** Documentation: https://esbuild.github.io/api/#drop-labels */
dropLabels?: string[]
/** Documentation: https://esbuild.github.io/api/#minify */
minify?: boolean
/** Documentation: https://esbuild.github.io/api/#minify */
minifyWhitespace?: boolean
/** Documentation: https://esbuild.github.io/api/#minify */
minifyIdentifiers?: boolean
/** Documentation: https://esbuild.github.io/api/#minify */
minifySyntax?: boolean
/** Documentation: https://esbuild.github.io/api/#line-limit */
lineLimit?: number
/** Documentation: https://esbuild.github.io/api/#charset */
charset?: Charset
/** Documentation: https://esbuild.github.io/api/#tree-shaking */
treeShaking?: boolean
/** Documentation: https://esbuild.github.io/api/#ignore-annotations */
ignoreAnnotations?: boolean
/** Documentation: https://esbuild.github.io/api/#jsx */
jsx?: 'transform' | 'preserve' | 'automatic'
/** Documentation: https://esbuild.github.io/api/#jsx-factory */
jsxFactory?: string
/** Documentation: https://esbuild.github.io/api/#jsx-fragment */
jsxFragment?: string
/** Documentation: https://esbuild.github.io/api/#jsx-import-source */
jsxImportSource?: string
/** Documentation: https://esbuild.github.io/api/#jsx-development */
jsxDev?: boolean
/** Documentation: https://esbuild.github.io/api/#jsx-side-effects */
jsxSideEffects?: boolean
/** Documentation: https://esbuild.github.io/api/#define */
define?: { [key: string]: string }
/** Documentation: https://esbuild.github.io/api/#pure */
pure?: string[]
/** Documentation: https://esbuild.github.io/api/#keep-names */
keepNames?: boolean
/** Documentation: https://esbuild.github.io/api/#abs-paths */
absPaths?: AbsPaths[]
/** Documentation: https://esbuild.github.io/api/#color */
color?: boolean
/** Documentation: https://esbuild.github.io/api/#log-level */
logLevel?: LogLevel
/** Documentation: https://esbuild.github.io/api/#log-limit */
logLimit?: number
/** Documentation: https://esbuild.github.io/api/#log-override */
logOverride?: Record<string, LogLevel>
/** Documentation: https://esbuild.github.io/api/#log-style */
logStyle?: LogStyle
/** Documentation: https://esbuild.github.io/api/#tsconfig-raw */
tsconfigRaw?: string | TsconfigRaw
}
export interface TsconfigRaw {
compilerOptions?: {
alwaysStrict?: boolean
baseUrl?: string
experimentalDecorators?: boolean
importsNotUsedAsValues?: 'remove' | 'preserve' | 'error'
jsx?: 'preserve' | 'react-native' | 'react' | 'react-jsx' | 'react-jsxdev'
jsxFactory?: string
jsxFragmentFactory?: string
jsxImportSource?: string
paths?: Record<string, string[]>
preserveValueImports?: boolean
strict?: boolean
target?: string
useDefineForClassFields?: boolean
verbatimModuleSyntax?: boolean
}
}
export interface BuildOptions extends CommonOptions {
/** Documentation: https://esbuild.github.io/api/#bundle */
bundle?: boolean
/** Documentation: https://esbuild.github.io/api/#splitting */
splitting?: boolean
/** Documentation: https://esbuild.github.io/api/#preserve-symlinks */
preserveSymlinks?: boolean
/** Documentation: https://esbuild.github.io/api/#outfile */
outfile?: string
/** Documentation: https://esbuild.github.io/api/#metafile */
metafile?: boolean
/** Documentation: https://esbuild.github.io/api/#outdir */
outdir?: string
/** Documentation: https://esbuild.github.io/api/#outbase */
outbase?: string
/** Documentation: https://esbuild.github.io/api/#external */
external?: string[]
/** Documentation: https://esbuild.github.io/api/#packages */
packages?: 'bundle' | 'external'
/** Documentation: https://esbuild.github.io/api/#alias */
alias?: Record<string, string>
/** Documentation: https://esbuild.github.io/api/#loader */
loader?: { [ext: string]: Loader }
/** Documentation: https://esbuild.github.io/api/#resolve-extensions */
resolveExtensions?: string[]
/** Documentation: https://esbuild.github.io/api/#main-fields */
mainFields?: string[]
/** Documentation: https://esbuild.github.io/api/#conditions */
conditions?: string[]
/** Documentation: https://esbuild.github.io/api/#write */
write?: boolean
/** Documentation: https://esbuild.github.io/api/#allow-overwrite */
allowOverwrite?: boolean
/** Documentation: https://esbuild.github.io/api/#tsconfig */
tsconfig?: string
/** Documentation: https://esbuild.github.io/api/#out-extension */
outExtension?: { [ext: string]: string }
/** Documentation: https://esbuild.github.io/api/#public-path */
publicPath?: string
/** Documentation: https://esbuild.github.io/api/#entry-names */
entryNames?: string
/** Documentation: https://esbuild.github.io/api/#chunk-names */
chunkNames?: string
/** Documentation: https://esbuild.github.io/api/#asset-names */
assetNames?: string
/** Documentation: https://esbuild.github.io/api/#inject */
inject?: string[]
/** Documentation: https://esbuild.github.io/api/#banner */
banner?: { [type: string]: string }
/** Documentation: https://esbuild.github.io/api/#footer */
footer?: { [type: string]: string }
/** Documentation: https://esbuild.github.io/api/#entry-points */
entryPoints?: (string | { in: string, out: string })[] | Record<string, string>
/** Documentation: https://esbuild.github.io/api/#stdin */
stdin?: StdinOptions
/** Documentation: https://esbuild.github.io/plugins/ */
plugins?: Plugin[]
/** Documentation: https://esbuild.github.io/api/#working-directory */
absWorkingDir?: string
/** Documentation: https://esbuild.github.io/api/#node-paths */
nodePaths?: string[]; // The "NODE_PATH" variable from Node.js
}
export interface StdinOptions {
contents: string | Uint8Array
resolveDir?: string
sourcefile?: string
loader?: Loader
}
export interface Message {
id: string
pluginName: string
text: string
location: Location | null
notes: Note[]
/**
* Optional user-specified data that is passed through unmodified. You can
* use this to stash the original error, for example.
*/
detail: any
}
export interface Note {
text: string
location: Location | null
}
export interface Location {
file: string
namespace: string
/** 1-based */
line: number
/** 0-based, in bytes */
column: number
/** in bytes */
length: number
lineText: string
suggestion: string
}
export interface OutputFile {
path: string
contents: Uint8Array
hash: string
/** "contents" as text (changes automatically with "contents") */
readonly text: string
}
export interface BuildResult<ProvidedOptions extends BuildOptions = BuildOptions> {
errors: Message[]
warnings: Message[]
/** Only when "write: false" */
outputFiles: OutputFile[] | (ProvidedOptions['write'] extends false ? never : undefined)
/** Only when "metafile: true" */
metafile: Metafile | (ProvidedOptions['metafile'] extends true ? never : undefined)
/** Only when "mangleCache" is present */
mangleCache: Record<string, string | false> | (ProvidedOptions['mangleCache'] extends Object ? never : undefined)
}
export interface BuildFailure extends Error {
errors: Message[]
warnings: Message[]
}
/** Documentation: https://esbuild.github.io/api/#serve-arguments */
export interface ServeOptions {
port?: number
host?: string
servedir?: string
keyfile?: string
certfile?: string
fallback?: string
cors?: CORSOptions
onRequest?: (args: ServeOnRequestArgs) => void
}
/** Documentation: https://esbuild.github.io/api/#cors */
export interface CORSOptions {
origin?: string | string[]
}
export interface ServeOnRequestArgs {
remoteAddress: string
method: string
path: string
status: number
/** The time to generate the response, not to send it */
timeInMS: number
}
/** Documentation: https://esbuild.github.io/api/#serve-return-values */
export interface ServeResult {
port: number
hosts: string[]
}
export interface TransformOptions extends CommonOptions {
/** Documentation: https://esbuild.github.io/api/#sourcefile */
sourcefile?: string
/** Documentation: https://esbuild.github.io/api/#loader */
loader?: Loader
/** Documentation: https://esbuild.github.io/api/#banner */
banner?: string
/** Documentation: https://esbuild.github.io/api/#footer */
footer?: string
}
export interface TransformResult<ProvidedOptions extends TransformOptions = TransformOptions> {
code: string
map: string
warnings: Message[]
/** Only when "mangleCache" is present */
mangleCache: Record<string, string | false> | (ProvidedOptions['mangleCache'] extends Object ? never : undefined)
/** Only when "legalComments" is "external" */
legalComments: string | (ProvidedOptions['legalComments'] extends 'external' ? never : undefined)
}
export interface TransformFailure extends Error {
errors: Message[]
warnings: Message[]
}
export interface Plugin {
name: string
setup: (build: PluginBuild) => (void | Promise<void>)
}
export interface PluginBuild {
/** Documentation: https://esbuild.github.io/plugins/#build-options */
initialOptions: BuildOptions
/** Documentation: https://esbuild.github.io/plugins/#resolve */
resolve(path: string, options?: ResolveOptions): Promise<ResolveResult>
/** Documentation: https://esbuild.github.io/plugins/#on-start */
onStart(callback: () =>
(OnStartResult | null | void | Promise<OnStartResult | null | void>)): void
/** Documentation: https://esbuild.github.io/plugins/#on-end */
onEnd(callback: (result: BuildResult) =>
(OnEndResult | null | void | Promise<OnEndResult | null | void>)): void
/** Documentation: https://esbuild.github.io/plugins/#on-resolve */
onResolve(options: OnResolveOptions, callback: (args: OnResolveArgs) =>
(OnResolveResult | null | undefined | Promise<OnResolveResult | null | undefined>)): void
/** Documentation: https://esbuild.github.io/plugins/#on-load */
onLoad(options: OnLoadOptions, callback: (args: OnLoadArgs) =>
(OnLoadResult | null | undefined | Promise<OnLoadResult | null | undefined>)): void
/** Documentation: https://esbuild.github.io/plugins/#on-dispose */
onDispose(callback: () => void): void
// This is a full copy of the esbuild library in case you need it
esbuild: {
context: typeof context,
build: typeof build,
buildSync: typeof buildSync,
transform: typeof transform,
transformSync: typeof transformSync,
formatMessages: typeof formatMessages,
formatMessagesSync: typeof formatMessagesSync,
analyzeMetafile: typeof analyzeMetafile,
analyzeMetafileSync: typeof analyzeMetafileSync,
initialize: typeof initialize,
version: typeof version,
}
}
/** Documentation: https://esbuild.github.io/plugins/#resolve-options */
export interface ResolveOptions {
pluginName?: string
importer?: string
namespace?: string
resolveDir?: string
kind?: ImportKind
pluginData?: any
with?: Record<string, string>
}
/** Documentation: https://esbuild.github.io/plugins/#resolve-results */
export interface ResolveResult {
errors: Message[]
warnings: Message[]
path: string
external: boolean
sideEffects: boolean
namespace: string
suffix: string
pluginData: any
}
export interface OnStartResult {
errors?: PartialMessage[]
warnings?: PartialMessage[]
}
export interface OnEndResult {
errors?: PartialMessage[]
warnings?: PartialMessage[]
}
/** Documentation: https://esbuild.github.io/plugins/#on-resolve-options */
export interface OnResolveOptions {
filter: RegExp
namespace?: string
}
/** Documentation: https://esbuild.github.io/plugins/#on-resolve-arguments */
export interface OnResolveArgs {
path: string
importer: string
namespace: string
resolveDir: string
kind: ImportKind
pluginData: any
with: Record<string, string>
}
export type ImportKind =
| 'entry-point'
// JS
| 'import-statement'
| 'require-call'
| 'dynamic-import'
| 'require-resolve'
// CSS
| 'import-rule'
| 'composes-from'
| 'url-token'
/** Documentation: https://esbuild.github.io/plugins/#on-resolve-results */
export interface OnResolveResult {
pluginName?: string
errors?: PartialMessage[]
warnings?: PartialMessage[]
path?: string
external?: boolean
sideEffects?: boolean
namespace?: string
suffix?: string
pluginData?: any
watchFiles?: string[]
watchDirs?: string[]
}
/** Documentation: https://esbuild.github.io/plugins/#on-load-options */
export interface OnLoadOptions {
filter: RegExp
namespace?: string
}
/** Documentation: https://esbuild.github.io/plugins/#on-load-arguments */
export interface OnLoadArgs {
path: string
namespace: string
suffix: string
pluginData: any
with: Record<string, string>
}
/** Documentation: https://esbuild.github.io/plugins/#on-load-results */
export interface OnLoadResult {
pluginName?: string
errors?: PartialMessage[]
warnings?: PartialMessage[]
contents?: string | Uint8Array
resolveDir?: string
loader?: Loader
pluginData?: any
watchFiles?: string[]
watchDirs?: string[]
}
export interface PartialMessage {
id?: string
pluginName?: string
text?: string
location?: Partial<Location> | null
notes?: PartialNote[]
detail?: any
}
export interface PartialNote {
text?: string
location?: Partial<Location> | null
}
/** Documentation: https://esbuild.github.io/api/#metafile */
export interface Metafile {
inputs: {
[path: string]: {
bytes: number
imports: {
path: string
kind: ImportKind
external?: boolean
original?: string
with?: Record<string, string>
}[]
format?: 'cjs' | 'esm'
with?: Record<string, string>
}
}
outputs: {
[path: string]: {
bytes: number
inputs: {
[path: string]: {
bytesInOutput: number
}
}
imports: {
path: string
kind: ImportKind | 'file-loader'
external?: boolean
}[]
exports: string[]
entryPoint?: string
cssBundle?: string
}
}
}
export interface FormatMessagesOptions {
kind: 'error' | 'warning'
color?: boolean
terminalWidth?: number
logStyle?: LogStyle
}
export interface AnalyzeMetafileOptions {
color?: boolean
verbose?: boolean
}
/** Documentation: https://esbuild.github.io/api/#watch-arguments */
export interface WatchOptions {
delay?: number // In milliseconds
}
export interface BuildContext<ProvidedOptions extends BuildOptions = BuildOptions> {
/** Documentation: https://esbuild.github.io/api/#rebuild */
rebuild(): Promise<BuildResult<ProvidedOptions>>
/** Documentation: https://esbuild.github.io/api/#watch */
watch(options?: WatchOptions): Promise<void>
/** Documentation: https://esbuild.github.io/api/#serve */
serve(options?: ServeOptions): Promise<ServeResult>
cancel(): Promise<void>
dispose(): Promise<void>
}
// This is a TypeScript type-level function which replaces any keys in "In"
// that aren't in "Out" with "never". We use this to reject properties with
// typos in object literals. See: https://stackoverflow.com/questions/49580725
type SameShape<Out, In extends Out> = In & { [Key in Exclude<keyof In, keyof Out>]: never }
/**
* This function invokes the "esbuild" command-line tool for you. It returns a
* promise that either resolves with a "BuildResult" object or rejects with a
* "BuildFailure" object.
*
* - Works in node: yes
* - Works in browser: yes
*
* Documentation: https://esbuild.github.io/api/#build
*/
export declare function build<T extends BuildOptions>(options: SameShape<BuildOptions, T>): Promise<BuildResult<T>>
/**
* This is the advanced long-running form of "build" that supports additional
* features such as watch mode and a local development server.
*
* - Works in node: yes
* - Works in browser: no
*
* Documentation: https://esbuild.github.io/api/#build
*/
export declare function context<T extends BuildOptions>(options: SameShape<BuildOptions, T>): Promise<BuildContext<T>>
/**
* This function transforms a single JavaScript file. It can be used to minify
* JavaScript, convert TypeScript/JSX to JavaScript, or convert newer JavaScript
* to older JavaScript. It returns a promise that is either resolved with a
* "TransformResult" object or rejected with a "TransformFailure" object.
*
* - Works in node: yes
* - Works in browser: yes
*
* Documentation: https://esbuild.github.io/api/#transform
*/
export declare function transform<T extends TransformOptions>(input: string | Uint8Array, options?: SameShape<TransformOptions, T>): Promise<TransformResult<T>>
/**
* Converts log messages to formatted message strings suitable for printing in
* the terminal. This allows you to reuse the built-in behavior of esbuild's
* log message formatter. This is a batch-oriented API for efficiency.
*
* - Works in node: yes
* - Works in browser: yes
*/
export declare function formatMessages(messages: PartialMessage[], options: FormatMessagesOptions): Promise<string[]>
/**
* Pretty-prints an analysis of the metafile JSON to a string. This is just for
* convenience to be able to match esbuild's pretty-printing exactly. If you want
* to customize it, you can just inspect the data in the metafile yourself.
*
* - Works in node: yes
* - Works in browser: yes
*
* Documentation: https://esbuild.github.io/api/#analyze
*/
export declare function analyzeMetafile(metafile: Metafile | string, options?: AnalyzeMetafileOptions): Promise<string>
/**
* A synchronous version of "build".
*
* - Works in node: yes
* - Works in browser: no
*
* Documentation: https://esbuild.github.io/api/#build
*/
export declare function buildSync<T extends BuildOptions>(options: SameShape<BuildOptions, T>): BuildResult<T>
/**
* A synchronous version of "transform".
*
* - Works in node: yes
* - Works in browser: no
*
* Documentation: https://esbuild.github.io/api/#transform
*/
export declare function transformSync<T extends TransformOptions>(input: string | Uint8Array, options?: SameShape<TransformOptions, T>): TransformResult<T>
/**
* A synchronous version of "formatMessages".
*
* - Works in node: yes
* - Works in browser: no
*/
export declare function formatMessagesSync(messages: PartialMessage[], options: FormatMessagesOptions): string[]
/**
* A synchronous version of "analyzeMetafile".
*
* - Works in node: yes
* - Works in browser: no
*
* Documentation: https://esbuild.github.io/api/#analyze
*/
export declare function analyzeMetafileSync(metafile: Metafile | string, options?: AnalyzeMetafileOptions): string
/**
* This configures the browser-based version of esbuild. It is necessary to
* call this first and wait for the returned promise to be resolved before
* making other API calls when using esbuild in the browser.
*
* - Works in node: yes
* - Works in browser: yes ("options" is required)
*
* Documentation: https://esbuild.github.io/api/#browser
*/
export declare function initialize(options: InitializeOptions): Promise<void>
export interface InitializeOptions {
/**
* The URL of the "esbuild.wasm" file. This must be provided when running
* esbuild in the browser.
*/
wasmURL?: string | URL
/**
* The result of calling "new WebAssembly.Module(buffer)" where "buffer"
* is a typed array or ArrayBuffer containing the binary code of the
* "esbuild.wasm" file.
*
* You can use this as an alternative to "wasmURL" for environments where it's
* not possible to download the WebAssembly module.
*/
wasmModule?: WebAssembly.Module
/**
* By default esbuild runs the WebAssembly-based browser API in a web worker
* to avoid blocking the UI thread. This can be disabled by setting "worker"
* to false.
*/
worker?: boolean
}
export let version: string
// Call this function to terminate esbuild's child process. The child process
// is not terminated and re-created after each API call because it's more
// efficient to keep it around when there are multiple API calls.
//
// In node this happens automatically before the parent node process exits. So
// you only need to call this if you know you will not make any more esbuild
// API calls and you want to clean up resources.
//
// Unlike node, Deno lacks the necessary APIs to clean up child processes
// automatically. You must manually call stop() in Deno when you're done
// using esbuild or Deno will continue running forever.
//
// Another reason you might want to call this is if you are using esbuild from
// within a Deno test. Deno fails tests that create a child process without
// killing it before the test ends, so you have to call this function (and
// await the returned promise) in every Deno test that uses esbuild.
export declare function stop(): Promise<void>
// Note: These declarations exist to avoid type errors when you omit "dom" from
// "lib" in your "tsconfig.json" file. TypeScript confusingly declares the
// global "WebAssembly" type in "lib.dom.d.ts" even though it has nothing to do
// with the browser DOM and is present in many non-browser JavaScript runtimes
// (e.g. node and deno). Declaring it here allows esbuild's API to be used in
// these scenarios.
//
// There's an open issue about getting this problem corrected (although these
// declarations will need to remain even if this is fixed for backward
// compatibility with older TypeScript versions):
//
// https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/826
//
declare global {
namespace WebAssembly {
interface Module {
}
}
interface URL {
}
}
+2536
View File
File diff suppressed because it is too large. Load diff
+74
View File
@@ -0,0 +1,74 @@
{
"name": "esbuild",
"version": "0.28.2",
"description": "An extremely fast JavaScript and CSS bundler and minifier.",
"repository": {
"type": "git",
"url": "git+https://github.com/evanw/esbuild.git"
},
"scripts": {
"postinstall": "node install.js"
},
"main": "lib/main.js",
"types": "lib/main.d.ts",
"engines": {
"node": ">=18"
},
"bin": {
"esbuild": "bin/esbuild"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.28.2",
"@esbuild/android-arm": "0.28.2",
"@esbuild/android-arm64": "0.28.2",
"@esbuild/android-x64": "0.28.2",
"@esbuild/darwin-arm64": "0.28.2",
"@esbuild/darwin-x64": "0.28.2",
"@esbuild/freebsd-arm64": "0.28.2",
"@esbuild/freebsd-x64": "0.28.2",
"@esbuild/linux-arm": "0.28.2",
"@esbuild/linux-arm64": "0.28.2",
"@esbuild/linux-ia32": "0.28.2",
"@esbuild/linux-loong64": "0.28.2",
"@esbuild/linux-mips64el": "0.28.2",
"@esbuild/linux-ppc64": "0.28.2",
"@esbuild/linux-riscv64": "0.28.2",
"@esbuild/linux-s390x": "0.28.2",
"@esbuild/linux-x64": "0.28.2",
"@esbuild/netbsd-arm64": "0.28.2",
"@esbuild/netbsd-x64": "0.28.2",
"@esbuild/openbsd-arm64": "0.28.2",
"@esbuild/openbsd-x64": "0.28.2",
"@esbuild/openharmony-arm64": "0.28.2",
"@esbuild/sunos-x64": "0.28.2",
"@esbuild/win32-arm64": "0.28.2",
"@esbuild/win32-ia32": "0.28.2",
"@esbuild/win32-x64": "0.28.2"
},
"license": "MIT",
"esbuild.binaryHashes": {
"@esbuild/aix-ppc64/bin/esbuild": "6de148b932fc5d3b28a97f9f0bc4de8e2b47db478b8ad679e0eaa6b96e00420d",
"@esbuild/android-arm64/bin/esbuild": "84efbbd2cbf21bbfec2aaf304bee79cb2a4a05fe2ea7b861a87f7b8f213ac27d",
"@esbuild/darwin-arm64/bin/esbuild": "10b6243df618d374bb2d5c9cfbe7052e1405f6aa4e53a6164f11a91b9f2e1384",
"@esbuild/darwin-x64/bin/esbuild": "7fe5c9c905fff0a05d92db98929434ab4d3b6dd92d7a7688922db74380c75df3",
"@esbuild/freebsd-arm64/bin/esbuild": "6aba108a68b93064e491bfb1ecfa28843b4d4e504dff0627f53f68f6bb015c01",
"@esbuild/freebsd-x64/bin/esbuild": "8a237e222bee0e50556e7b00d83ec2ff43721bf72f19811a5f0ee56f1d40177c",
"@esbuild/linux-arm/bin/esbuild": "d88f751b22095b2f3b42c8c2e8a3f36fabc1705438c5d6e78366b681f8b4e7a5",
"@esbuild/linux-arm64/bin/esbuild": "90bd269553d258e80b19e3ccab4f98f0831f87442a2f056510ce24fd1b425fc2",
"@esbuild/linux-ia32/bin/esbuild": "b1e2d87d79f9a2baa0d3043cdf0dc6716f9f2eea66c58f47588641fd6019f36f",
"@esbuild/linux-loong64/bin/esbuild": "55a66f9854d6798f36b2b5471db74f2e552481887ea14d8bda1634a512383a43",
"@esbuild/linux-mips64el/bin/esbuild": "6bf7921a3af4a801051e056d85c360fe24bb446f488ef3da25f0b8e5cf973db1",
"@esbuild/linux-ppc64/bin/esbuild": "c30df60d09bb0ba4853d7b06e244ce966890d61ce60cadd9b22335f6379c316a",
"@esbuild/linux-riscv64/bin/esbuild": "36bdcdc8230eef385838cdfeb0d9a1565cbe4b9ace30097a511d77e894de36a1",
"@esbuild/linux-s390x/bin/esbuild": "bbbc1f92a76a5ca6e2976065222e42b02797363a1f119490dda315f74047741f",
"@esbuild/linux-x64/bin/esbuild": "e1698a3d5c6c0798fee4fd3b5cc816651f460c63d390a7a26ea4beb0b1884100",
"@esbuild/netbsd-arm64/bin/esbuild": "62548519d7ae875d060aa8c94bfb8ed38ef191671a5173d9f626bdb6b7516970",
"@esbuild/netbsd-x64/bin/esbuild": "f9d0e59d2b404559e3a0c958164d96960ebf0e04583b878b1d64d8f1c3698fcc",
"@esbuild/openbsd-arm64/bin/esbuild": "e10c45a0b62456632da41df058d7626b2e7cfe710780a2dc7f9f84681753f3aa",
"@esbuild/openbsd-x64/bin/esbuild": "720bbe607736716f2ecd37962436c5589d801966e868a2ae4e0e7e62d1e4e887",
"@esbuild/sunos-x64/bin/esbuild": "01a3bd9183631ca749f34d15601ea21ba6834614184c5c859f99d54bd683203d",
"@esbuild/win32-arm64/esbuild.exe": "530fb3933af14eefe85dfd06502f826e6ef60fdf4e75228ea67c696db312ecb1",
"@esbuild/win32-ia32/esbuild.exe": "b2e62af5c17e00939583be0a0762fdc469f352869a617edc91371b00454c76f0",
"@esbuild/win32-x64/esbuild.exe": "c7bee37877d0aa6a046e52783fa0a2cf1a9ce5579d68bb3083bda99d4bff18ef"
}
}
Generated Vendored
+7
View File
@@ -0,0 +1,7 @@
Copyright 2023 Abdullah Atta
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+91
View File
@@ -0,0 +1,91 @@
<p align="center">
<img src="https://github.com/thecodrr/fdir/raw/master/assets/fdir.gif" width="75%"/>
<h1 align="center">The Fastest Directory Crawler & Globber for NodeJS</h1>
<p align="center">
<a href="https://www.npmjs.com/package/fdir"><img src="https://img.shields.io/npm/v/fdir?style=for-the-badge"/></a>
<a href="https://www.npmjs.com/package/fdir"><img src="https://img.shields.io/npm/dw/fdir?style=for-the-badge"/></a>
<a href="https://codeclimate.com/github/thecodrr/fdir/maintainability"><img src="https://img.shields.io/codeclimate/maintainability-percentage/thecodrr/fdir?style=for-the-badge"/></a>
<a href="https://coveralls.io/github/thecodrr/fdir?branch=master"><img src="https://img.shields.io/coveralls/github/thecodrr/fdir?style=for-the-badge"/></a>
<a href="https://www.npmjs.com/package/fdir"><img src="https://img.shields.io/bundlephobia/minzip/fdir?style=for-the-badge"/></a>
<a href="https://www.producthunt.com/posts/fdir-every-millisecond-matters"><img src="https://img.shields.io/badge/ProductHunt-Upvote-red?style=for-the-badge&logo=product-hunt"/></a>
<a href="https://dev.to/thecodrr/how-i-wrote-the-fastest-directory-crawler-ever-3p9c"><img src="https://img.shields.io/badge/dev.to-Read%20Blog-black?style=for-the-badge&logo=dev.to"/></a>
<a href="./LICENSE"><img src="https://img.shields.io/github/license/thecodrr/fdir?style=for-the-badge"/></a>
</p>
</p>
⚡ **The Fastest:** Nothing similar (in the NodeJS world) beats `fdir` in speed. It can easily crawl a directory containing **1 million files in < 1 second.**
💡 **Stupidly Easy:** `fdir` uses expressive Builder pattern to build the crawler increasing code readability.
🤖 **Zero Dependencies\*:** `fdir` only uses NodeJS `fs` & `path` modules.
🕺 **Astonishingly Small:** < 2KB in size gzipped & minified.
🖮 **Hackable:** Extending `fdir` is extremely simple now that the new Builder API is here. Feel free to experiment around.
_\* `picomatch` must be installed manually by the user to support globbing._
## 🚄 Quickstart
### Installation
You can install using `npm`:
```sh
$ npm i fdir
```
or Yarn:
```sh
$ yarn add fdir
```
### Usage
```ts
import { fdir } from "fdir";
// create the builder
const api = new fdir().withFullPaths().crawl("path/to/dir");
// get all files in a directory synchronously
const files = api.sync();
// or asynchronously
api.withPromise().then((files) => {
// do something with the result here.
});
```
## Documentation:
Documentation for all methods is available [here](/documentation.md).
## 📊 Benchmarks:
Please check the benchmark against the latest version [here](/BENCHMARKS.md).
## 🙏Used by:
`fdir` is downloaded over 200k+ times a week by projects around the world. Here's a list of some notable projects using `fdir` in production:
> Note: if you think your project should be here, feel free to open an issue. Notable is anything with a considerable amount of GitHub stars.
1. [rollup/plugins](https://github.com/rollup/plugins)
2. [SuperchupuDev/tinyglobby](https://github.com/SuperchupuDev/tinyglobby)
3. [pulumi/pulumi](https://github.com/pulumi/pulumi)
4. [dotenvx/dotenvx](https://github.com/dotenvx/dotenvx)
5. [mdn/yari](https://github.com/mdn/yari)
6. [streetwriters/notesnook](https://github.com/streetwriters/notesnook)
7. [imba/imba](https://github.com/imba/imba)
8. [moroshko/react-scanner](https://github.com/moroshko/react-scanner)
9. [netlify/build](https://github.com/netlify/build)
10. [yassinedoghri/astro-i18next](https://github.com/yassinedoghri/astro-i18next)
11. [selfrefactor/rambda](https://github.com/selfrefactor/rambda)
12. [whyboris/Video-Hub-App](https://github.com/whyboris/Video-Hub-App)
## 🦮 LICENSE
Copyright &copy; 2024 Abdullah Atta under MIT. [Read full text here.](https://github.com/thecodrr/fdir/raw/master/LICENSE)
+588
View File
@@ -0,0 +1,588 @@
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
const path = __toESM(require("path"));
const fs = __toESM(require("fs"));
//#region src/utils.ts
function cleanPath(path$1) {
let normalized = (0, path.normalize)(path$1);
if (normalized.length > 1 && normalized[normalized.length - 1] === path.sep) normalized = normalized.substring(0, normalized.length - 1);
return normalized;
}
const SLASHES_REGEX = /[\\/]/g;
function convertSlashes(path$1, separator) {
return path$1.replace(SLASHES_REGEX, separator);
}
const WINDOWS_ROOT_DIR_REGEX = /^[a-z]:[\\/]$/i;
function isRootDirectory(path$1) {
return path$1 === "/" || WINDOWS_ROOT_DIR_REGEX.test(path$1);
}
function normalizePath(path$1, options) {
const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options;
const pathNeedsCleaning = process.platform === "win32" && path$1.includes("/") || path$1.startsWith(".");
if (resolvePaths) path$1 = (0, path.resolve)(path$1);
if (normalizePath$1 || pathNeedsCleaning) path$1 = cleanPath(path$1);
if (path$1 === ".") return "";
const needsSeperator = path$1[path$1.length - 1] !== pathSeparator;
return convertSlashes(needsSeperator ? path$1 + pathSeparator : path$1, pathSeparator);
}
//#endregion
//#region src/api/functions/join-path.ts
function joinPathWithBasePath(filename, directoryPath) {
return directoryPath + filename;
}
function joinPathWithRelativePath(root, options) {
return function(filename, directoryPath) {
const sameRoot = directoryPath.startsWith(root);
if (sameRoot) return directoryPath.slice(root.length) + filename;
else return convertSlashes((0, path.relative)(root, directoryPath), options.pathSeparator) + options.pathSeparator + filename;
};
}
function joinPath(filename) {
return filename;
}
function joinDirectoryPath(filename, directoryPath, separator) {
return directoryPath + filename + separator;
}
function build$7(root, options) {
const { relativePaths, includeBasePath } = options;
return relativePaths && root ? joinPathWithRelativePath(root, options) : includeBasePath ? joinPathWithBasePath : joinPath;
}
//#endregion
//#region src/api/functions/push-directory.ts
function pushDirectoryWithRelativePath(root) {
return function(directoryPath, paths) {
paths.push(directoryPath.substring(root.length) || ".");
};
}
function pushDirectoryFilterWithRelativePath(root) {
return function(directoryPath, paths, filters) {
const relativePath = directoryPath.substring(root.length) || ".";
if (filters.every((filter) => filter(relativePath, true))) paths.push(relativePath);
};
}
const pushDirectory = (directoryPath, paths) => {
paths.push(directoryPath || ".");
};
const pushDirectoryFilter = (directoryPath, paths, filters) => {
const path$1 = directoryPath || ".";
if (filters.every((filter) => filter(path$1, true))) paths.push(path$1);
};
const empty$2 = () => {};
function build$6(root, options) {
const { includeDirs, filters, relativePaths } = options;
if (!includeDirs) return empty$2;
if (relativePaths) return filters && filters.length ? pushDirectoryFilterWithRelativePath(root) : pushDirectoryWithRelativePath(root);
return filters && filters.length ? pushDirectoryFilter : pushDirectory;
}
//#endregion
//#region src/api/functions/push-file.ts
const pushFileFilterAndCount = (filename, _paths, counts, filters) => {
if (filters.every((filter) => filter(filename, false))) counts.files++;
};
const pushFileFilter = (filename, paths, _counts, filters) => {
if (filters.every((filter) => filter(filename, false))) paths.push(filename);
};
const pushFileCount = (_filename, _paths, counts, _filters) => {
counts.files++;
};
const pushFile = (filename, paths) => {
paths.push(filename);
};
const empty$1 = () => {};
function build$5(options) {
const { excludeFiles, filters, onlyCounts } = options;
if (excludeFiles) return empty$1;
if (filters && filters.length) return onlyCounts ? pushFileFilterAndCount : pushFileFilter;
else if (onlyCounts) return pushFileCount;
else return pushFile;
}
//#endregion
//#region src/api/functions/get-array.ts
const getArray = (paths) => {
return paths;
};
const getArrayGroup = () => {
return [""].slice(0, 0);
};
function build$4(options) {
return options.group ? getArrayGroup : getArray;
}
//#endregion
//#region src/api/functions/group-files.ts
const groupFiles = (groups, directory, files) => {
groups.push({
directory,
files,
dir: directory
});
};
const empty = () => {};
function build$3(options) {
return options.group ? groupFiles : empty;
}
//#endregion
//#region src/api/functions/resolve-symlink.ts
const resolveSymlinksAsync = function(path$1, state, callback$1) {
const { queue, fs: fs$1, options: { suppressErrors } } = state;
queue.enqueue();
fs$1.realpath(path$1, (error, resolvedPath) => {
if (error) return queue.dequeue(suppressErrors ? null : error, state);
fs$1.stat(resolvedPath, (error$1, stat) => {
if (error$1) return queue.dequeue(suppressErrors ? null : error$1, state);
if (stat.isDirectory() && isRecursive(path$1, resolvedPath, state)) return queue.dequeue(null, state);
callback$1(stat, resolvedPath);
queue.dequeue(null, state);
});
});
};
const resolveSymlinks = function(path$1, state, callback$1) {
const { queue, fs: fs$1, options: { suppressErrors } } = state;
queue.enqueue();
try {
const resolvedPath = fs$1.realpathSync(path$1);
const stat = fs$1.statSync(resolvedPath);
if (stat.isDirectory() && isRecursive(path$1, resolvedPath, state)) return;
callback$1(stat, resolvedPath);
} catch (e) {
if (!suppressErrors) throw e;
}
};
function build$2(options, isSynchronous) {
if (!options.resolveSymlinks || options.excludeSymlinks) return null;
return isSynchronous ? resolveSymlinks : resolveSymlinksAsync;
}
function isRecursive(path$1, resolved, state) {
if (state.options.useRealPaths) return isRecursiveUsingRealPaths(resolved, state);
let parent = (0, path.dirname)(path$1);
let depth = 1;
while (parent !== state.root && depth < 2) {
const resolvedPath = state.symlinks.get(parent);
const isSameRoot = !!resolvedPath && (resolvedPath === resolved || resolvedPath.startsWith(resolved) || resolved.startsWith(resolvedPath));
if (isSameRoot) depth++;
else parent = (0, path.dirname)(parent);
}
state.symlinks.set(path$1, resolved);
return depth > 1;
}
function isRecursiveUsingRealPaths(resolved, state) {
return state.visited.includes(resolved + state.options.pathSeparator);
}
//#endregion
//#region src/api/functions/invoke-callback.ts
const onlyCountsSync = (state) => {
return state.counts;
};
const groupsSync = (state) => {
return state.groups;
};
const defaultSync = (state) => {
return state.paths;
};
const limitFilesSync = (state) => {
return state.paths.slice(0, state.options.maxFiles);
};
const onlyCountsAsync = (state, error, callback$1) => {
report(error, callback$1, state.counts, state.options.suppressErrors);
return null;
};
const defaultAsync = (state, error, callback$1) => {
report(error, callback$1, state.paths, state.options.suppressErrors);
return null;
};
const limitFilesAsync = (state, error, callback$1) => {
report(error, callback$1, state.paths.slice(0, state.options.maxFiles), state.options.suppressErrors);
return null;
};
const groupsAsync = (state, error, callback$1) => {
report(error, callback$1, state.groups, state.options.suppressErrors);
return null;
};
function report(error, callback$1, output, suppressErrors) {
if (error && !suppressErrors) callback$1(error, output);
else callback$1(null, output);
}
function build$1(options, isSynchronous) {
const { onlyCounts, group, maxFiles } = options;
if (onlyCounts) return isSynchronous ? onlyCountsSync : onlyCountsAsync;
else if (group) return isSynchronous ? groupsSync : groupsAsync;
else if (maxFiles) return isSynchronous ? limitFilesSync : limitFilesAsync;
else return isSynchronous ? defaultSync : defaultAsync;
}
//#endregion
//#region src/api/functions/walk-directory.ts
const readdirOpts = { withFileTypes: true };
const walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
state.queue.enqueue();
if (currentDepth < 0) return state.queue.dequeue(null, state);
const { fs: fs$1 } = state;
state.visited.push(crawlPath);
state.counts.directories++;
fs$1.readdir(crawlPath || ".", readdirOpts, (error, entries = []) => {
callback$1(entries, directoryPath, currentDepth);
state.queue.dequeue(state.options.suppressErrors ? null : error, state);
});
};
const walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
const { fs: fs$1 } = state;
if (currentDepth < 0) return;
state.visited.push(crawlPath);
state.counts.directories++;
let entries = [];
try {
entries = fs$1.readdirSync(crawlPath || ".", readdirOpts);
} catch (e) {
if (!state.options.suppressErrors) throw e;
}
callback$1(entries, directoryPath, currentDepth);
};
function build(isSynchronous) {
return isSynchronous ? walkSync : walkAsync;
}
//#endregion
//#region src/api/queue.ts
/**
* This is a custom stateless queue to track concurrent async fs calls.
* It increments a counter whenever a call is queued and decrements it
* as soon as it completes. When the counter hits 0, it calls onQueueEmpty.
*/
var Queue = class {
count = 0;
constructor(onQueueEmpty) {
this.onQueueEmpty = onQueueEmpty;
}
enqueue() {
this.count++;
return this.count;
}
dequeue(error, output) {
if (this.onQueueEmpty && (--this.count <= 0 || error)) {
this.onQueueEmpty(error, output);
if (error) {
output.controller.abort();
this.onQueueEmpty = void 0;
}
}
}
};
//#endregion
//#region src/api/counter.ts
var Counter = class {
_files = 0;
_directories = 0;
set files(num) {
this._files = num;
}
get files() {
return this._files;
}
set directories(num) {
this._directories = num;
}
get directories() {
return this._directories;
}
/**
* @deprecated use `directories` instead
*/
/* c8 ignore next 3 */
get dirs() {
return this._directories;
}
};
//#endregion
//#region src/api/aborter.ts
/**
* AbortController is not supported on Node 14 so we use this until we can drop
* support for Node 14.
*/
var Aborter = class {
aborted = false;
abort() {
this.aborted = true;
}
};
//#endregion
//#region src/api/walker.ts
var Walker = class {
root;
isSynchronous;
state;
joinPath;
pushDirectory;
pushFile;
getArray;
groupFiles;
resolveSymlink;
walkDirectory;
callbackInvoker;
constructor(root, options, callback$1) {
this.isSynchronous = !callback$1;
this.callbackInvoker = build$1(options, this.isSynchronous);
this.root = normalizePath(root, options);
this.state = {
root: isRootDirectory(this.root) ? this.root : this.root.slice(0, -1),
paths: [""].slice(0, 0),
groups: [],
counts: new Counter(),
options,
queue: new Queue((error, state) => this.callbackInvoker(state, error, callback$1)),
symlinks: /* @__PURE__ */ new Map(),
visited: [""].slice(0, 0),
controller: new Aborter(),
fs: options.fs || fs
};
this.joinPath = build$7(this.root, options);
this.pushDirectory = build$6(this.root, options);
this.pushFile = build$5(options);
this.getArray = build$4(options);
this.groupFiles = build$3(options);
this.resolveSymlink = build$2(options, this.isSynchronous);
this.walkDirectory = build(this.isSynchronous);
}
start() {
this.pushDirectory(this.root, this.state.paths, this.state.options.filters);
this.walkDirectory(this.state, this.root, this.root, this.state.options.maxDepth, this.walk);
return this.isSynchronous ? this.callbackInvoker(this.state, null) : null;
}
walk = (entries, directoryPath, depth) => {
const { paths, options: { filters, resolveSymlinks: resolveSymlinks$1, excludeSymlinks, exclude, maxFiles, signal, useRealPaths, pathSeparator }, controller } = this.state;
if (controller.aborted || signal && signal.aborted || maxFiles && paths.length > maxFiles) return;
const files = this.getArray(this.state.paths);
for (let i = 0; i < entries.length; ++i) {
const entry = entries[i];
if (entry.isFile() || entry.isSymbolicLink() && !resolveSymlinks$1 && !excludeSymlinks) {
const filename = this.joinPath(entry.name, directoryPath);
this.pushFile(filename, files, this.state.counts, filters);
} else if (entry.isDirectory()) {
let path$1 = joinDirectoryPath(entry.name, directoryPath, this.state.options.pathSeparator);
if (exclude && exclude(entry.name, path$1)) continue;
this.pushDirectory(path$1, paths, filters);
this.walkDirectory(this.state, path$1, path$1, depth - 1, this.walk);
} else if (this.resolveSymlink && entry.isSymbolicLink()) {
let path$1 = joinPathWithBasePath(entry.name, directoryPath);
this.resolveSymlink(path$1, this.state, (stat, resolvedPath) => {
if (stat.isDirectory()) {
resolvedPath = normalizePath(resolvedPath, this.state.options);
if (exclude && exclude(entry.name, useRealPaths ? resolvedPath : path$1 + pathSeparator)) return;
this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath : path$1 + pathSeparator, depth - 1, this.walk);
} else {
resolvedPath = useRealPaths ? resolvedPath : path$1;
const filename = (0, path.basename)(resolvedPath);
const directoryPath$1 = normalizePath((0, path.dirname)(resolvedPath), this.state.options);
resolvedPath = this.joinPath(filename, directoryPath$1);
this.pushFile(resolvedPath, files, this.state.counts, filters);
}
});
}
}
this.groupFiles(this.state.groups, directoryPath, files);
};
};
//#endregion
//#region src/api/async.ts
function promise(root, options) {
return new Promise((resolve$1, reject) => {
callback(root, options, (err, output) => {
if (err) return reject(err);
resolve$1(output);
});
});
}
function callback(root, options, callback$1) {
let walker = new Walker(root, options, callback$1);
walker.start();
}
//#endregion
//#region src/api/sync.ts
function sync(root, options) {
const walker = new Walker(root, options);
return walker.start();
}
//#endregion
//#region src/builder/api-builder.ts
var APIBuilder = class {
constructor(root, options) {
this.root = root;
this.options = options;
}
withPromise() {
return promise(this.root, this.options);
}
withCallback(cb) {
callback(this.root, this.options, cb);
}
sync() {
return sync(this.root, this.options);
}
};
//#endregion
//#region src/builder/index.ts
let pm = null;
/* c8 ignore next 6 */
try {
require.resolve("picomatch");
pm = require("picomatch");
} catch {}
var Builder = class {
globCache = {};
options = {
maxDepth: Infinity,
suppressErrors: true,
pathSeparator: path.sep,
filters: []
};
globFunction;
constructor(options) {
this.options = {
...this.options,
...options
};
this.globFunction = this.options.globFunction;
}
group() {
this.options.group = true;
return this;
}
withPathSeparator(separator) {
this.options.pathSeparator = separator;
return this;
}
withBasePath() {
this.options.includeBasePath = true;
return this;
}
withRelativePaths() {
this.options.relativePaths = true;
return this;
}
withDirs() {
this.options.includeDirs = true;
return this;
}
withMaxDepth(depth) {
this.options.maxDepth = depth;
return this;
}
withMaxFiles(limit) {
this.options.maxFiles = limit;
return this;
}
withFullPaths() {
this.options.resolvePaths = true;
this.options.includeBasePath = true;
return this;
}
withErrors() {
this.options.suppressErrors = false;
return this;
}
withSymlinks({ resolvePaths = true } = {}) {
this.options.resolveSymlinks = true;
this.options.useRealPaths = resolvePaths;
return this.withFullPaths();
}
withAbortSignal(signal) {
this.options.signal = signal;
return this;
}
normalize() {
this.options.normalizePath = true;
return this;
}
filter(predicate) {
this.options.filters.push(predicate);
return this;
}
onlyDirs() {
this.options.excludeFiles = true;
this.options.includeDirs = true;
return this;
}
exclude(predicate) {
this.options.exclude = predicate;
return this;
}
onlyCounts() {
this.options.onlyCounts = true;
return this;
}
crawl(root) {
return new APIBuilder(root || ".", this.options);
}
withGlobFunction(fn) {
this.globFunction = fn;
return this;
}
/**
* @deprecated Pass options using the constructor instead:
* ```ts
* new fdir(options).crawl("/path/to/root");
* ```
* This method will be removed in v7.0
*/
/* c8 ignore next 4 */
crawlWithOptions(root, options) {
this.options = {
...this.options,
...options
};
return new APIBuilder(root || ".", this.options);
}
glob(...patterns) {
if (this.globFunction) return this.globWithOptions(patterns);
return this.globWithOptions(patterns, ...[{ dot: true }]);
}
globWithOptions(patterns, ...options) {
const globFn = this.globFunction || pm;
/* c8 ignore next 5 */
if (!globFn) throw new Error("Please specify a glob function to use glob matching.");
var isMatch = this.globCache[patterns.join("\0")];
if (!isMatch) {
isMatch = globFn(patterns, ...options);
this.globCache[patterns.join("\0")] = isMatch;
}
this.options.filters.push((path$1) => isMatch(path$1));
return this;
}
};
//#endregion
exports.fdir = Builder;
+155
View File
@@ -0,0 +1,155 @@
/// <reference types="node" />
import * as nativeFs from "fs";
import picomatch from "picomatch";
//#region src/api/aborter.d.ts
/**
* AbortController is not supported on Node 14 so we use this until we can drop
* support for Node 14.
*/
declare class Aborter {
aborted: boolean;
abort(): void;
}
//#endregion
//#region src/api/queue.d.ts
type OnQueueEmptyCallback = (error: Error | null, output: WalkerState) => void;
/**
* This is a custom stateless queue to track concurrent async fs calls.
* It increments a counter whenever a call is queued and decrements it
* as soon as it completes. When the counter hits 0, it calls onQueueEmpty.
*/
declare class Queue {
private onQueueEmpty?;
count: number;
constructor(onQueueEmpty?: OnQueueEmptyCallback | undefined);
enqueue(): number;
dequeue(error: Error | null, output: WalkerState): void;
}
//#endregion
//#region src/types.d.ts
type Counts = {
files: number;
directories: number;
/**
* @deprecated use `directories` instead. Will be removed in v7.0.
*/
dirs: number;
};
type Group = {
directory: string;
files: string[];
/**
* @deprecated use `directory` instead. Will be removed in v7.0.
*/
dir: string;
};
type GroupOutput = Group[];
type OnlyCountsOutput = Counts;
type PathsOutput = string[];
type Output = OnlyCountsOutput | PathsOutput | GroupOutput;
type FSLike = {
readdir: typeof nativeFs.readdir;
readdirSync: typeof nativeFs.readdirSync;
realpath: typeof nativeFs.realpath;
realpathSync: typeof nativeFs.realpathSync;
stat: typeof nativeFs.stat;
statSync: typeof nativeFs.statSync;
};
type WalkerState = {
root: string;
paths: string[];
groups: Group[];
counts: Counts;
options: Options;
queue: Queue;
controller: Aborter;
fs: FSLike;
symlinks: Map<string, string>;
visited: string[];
};
type ResultCallback<TOutput extends Output> = (error: Error | null, output: TOutput) => void;
type FilterPredicate = (path: string, isDirectory: boolean) => boolean;
type ExcludePredicate = (dirName: string, dirPath: string) => boolean;
type PathSeparator = "/" | "\\";
type Options<TGlobFunction = unknown> = {
includeBasePath?: boolean;
includeDirs?: boolean;
normalizePath?: boolean;
maxDepth: number;
maxFiles?: number;
resolvePaths?: boolean;
suppressErrors: boolean;
group?: boolean;
onlyCounts?: boolean;
filters: FilterPredicate[];
resolveSymlinks?: boolean;
useRealPaths?: boolean;
excludeFiles?: boolean;
excludeSymlinks?: boolean;
exclude?: ExcludePredicate;
relativePaths?: boolean;
pathSeparator: PathSeparator;
signal?: AbortSignal;
globFunction?: TGlobFunction;
fs?: FSLike;
};
type GlobMatcher = (test: string) => boolean;
type GlobFunction = (glob: string | string[], ...params: unknown[]) => GlobMatcher;
type GlobParams<T> = T extends ((globs: string | string[], ...params: infer TParams extends unknown[]) => GlobMatcher) ? TParams : [];
//#endregion
//#region src/builder/api-builder.d.ts
declare class APIBuilder<TReturnType extends Output> {
private readonly root;
private readonly options;
constructor(root: string, options: Options);
withPromise(): Promise<TReturnType>;
withCallback(cb: ResultCallback<TReturnType>): void;
sync(): TReturnType;
}
//#endregion
//#region src/builder/index.d.ts
declare class Builder<TReturnType extends Output = PathsOutput, TGlobFunction = typeof picomatch> {
private readonly globCache;
private options;
private globFunction?;
constructor(options?: Partial<Options<TGlobFunction>>);
group(): Builder<GroupOutput, TGlobFunction>;
withPathSeparator(separator: "/" | "\\"): this;
withBasePath(): this;
withRelativePaths(): this;
withDirs(): this;
withMaxDepth(depth: number): this;
withMaxFiles(limit: number): this;
withFullPaths(): this;
withErrors(): this;
withSymlinks({
resolvePaths
}?: {
resolvePaths?: boolean | undefined;
}): this;
withAbortSignal(signal: AbortSignal): this;
normalize(): this;
filter(predicate: FilterPredicate): this;
onlyDirs(): this;
exclude(predicate: ExcludePredicate): this;
onlyCounts(): Builder<OnlyCountsOutput, TGlobFunction>;
crawl(root?: string): APIBuilder<TReturnType>;
withGlobFunction<TFunc>(fn: TFunc): Builder<TReturnType, TFunc>;
/**
* @deprecated Pass options using the constructor instead:
* ```ts
* new fdir(options).crawl("/path/to/root");
* ```
* This method will be removed in v7.0
*/
crawlWithOptions(root: string, options: Partial<Options<TGlobFunction>>): APIBuilder<TReturnType>;
glob(...patterns: string[]): Builder<TReturnType, TGlobFunction>;
globWithOptions(patterns: string[]): Builder<TReturnType, TGlobFunction>;
globWithOptions(patterns: string[], ...options: GlobParams<TGlobFunction>): Builder<TReturnType, TGlobFunction>;
}
//#endregion
//#region src/index.d.ts
type Fdir = typeof Builder;
//#endregion
export { Counts, ExcludePredicate, FSLike, Fdir, FilterPredicate, GlobFunction, GlobMatcher, GlobParams, Group, GroupOutput, OnlyCountsOutput, Options, Output, PathSeparator, PathsOutput, ResultCallback, WalkerState, Builder as fdir };
+155
View File
@@ -0,0 +1,155 @@
/// <reference types="node" />
import * as nativeFs from "fs";
import picomatch from "picomatch";
//#region src/api/aborter.d.ts
/**
* AbortController is not supported on Node 14 so we use this until we can drop
* support for Node 14.
*/
declare class Aborter {
aborted: boolean;
abort(): void;
}
//#endregion
//#region src/api/queue.d.ts
type OnQueueEmptyCallback = (error: Error | null, output: WalkerState) => void;
/**
* This is a custom stateless queue to track concurrent async fs calls.
* It increments a counter whenever a call is queued and decrements it
* as soon as it completes. When the counter hits 0, it calls onQueueEmpty.
*/
declare class Queue {
private onQueueEmpty?;
count: number;
constructor(onQueueEmpty?: OnQueueEmptyCallback | undefined);
enqueue(): number;
dequeue(error: Error | null, output: WalkerState): void;
}
//#endregion
//#region src/types.d.ts
type Counts = {
files: number;
directories: number;
/**
* @deprecated use `directories` instead. Will be removed in v7.0.
*/
dirs: number;
};
type Group = {
directory: string;
files: string[];
/**
* @deprecated use `directory` instead. Will be removed in v7.0.
*/
dir: string;
};
type GroupOutput = Group[];
type OnlyCountsOutput = Counts;
type PathsOutput = string[];
type Output = OnlyCountsOutput | PathsOutput | GroupOutput;
type FSLike = {
readdir: typeof nativeFs.readdir;
readdirSync: typeof nativeFs.readdirSync;
realpath: typeof nativeFs.realpath;
realpathSync: typeof nativeFs.realpathSync;
stat: typeof nativeFs.stat;
statSync: typeof nativeFs.statSync;
};
type WalkerState = {
root: string;
paths: string[];
groups: Group[];
counts: Counts;
options: Options;
queue: Queue;
controller: Aborter;
fs: FSLike;
symlinks: Map<string, string>;
visited: string[];
};
type ResultCallback<TOutput extends Output> = (error: Error | null, output: TOutput) => void;
type FilterPredicate = (path: string, isDirectory: boolean) => boolean;
type ExcludePredicate = (dirName: string, dirPath: string) => boolean;
type PathSeparator = "/" | "\\";
type Options<TGlobFunction = unknown> = {
includeBasePath?: boolean;
includeDirs?: boolean;
normalizePath?: boolean;
maxDepth: number;
maxFiles?: number;
resolvePaths?: boolean;
suppressErrors: boolean;
group?: boolean;
onlyCounts?: boolean;
filters: FilterPredicate[];
resolveSymlinks?: boolean;
useRealPaths?: boolean;
excludeFiles?: boolean;
excludeSymlinks?: boolean;
exclude?: ExcludePredicate;
relativePaths?: boolean;
pathSeparator: PathSeparator;
signal?: AbortSignal;
globFunction?: TGlobFunction;
fs?: FSLike;
};
type GlobMatcher = (test: string) => boolean;
type GlobFunction = (glob: string | string[], ...params: unknown[]) => GlobMatcher;
type GlobParams<T> = T extends ((globs: string | string[], ...params: infer TParams extends unknown[]) => GlobMatcher) ? TParams : [];
//#endregion
//#region src/builder/api-builder.d.ts
declare class APIBuilder<TReturnType extends Output> {
private readonly root;
private readonly options;
constructor(root: string, options: Options);
withPromise(): Promise<TReturnType>;
withCallback(cb: ResultCallback<TReturnType>): void;
sync(): TReturnType;
}
//#endregion
//#region src/builder/index.d.ts
declare class Builder<TReturnType extends Output = PathsOutput, TGlobFunction = typeof picomatch> {
private readonly globCache;
private options;
private globFunction?;
constructor(options?: Partial<Options<TGlobFunction>>);
group(): Builder<GroupOutput, TGlobFunction>;
withPathSeparator(separator: "/" | "\\"): this;
withBasePath(): this;
withRelativePaths(): this;
withDirs(): this;
withMaxDepth(depth: number): this;
withMaxFiles(limit: number): this;
withFullPaths(): this;
withErrors(): this;
withSymlinks({
resolvePaths
}?: {
resolvePaths?: boolean | undefined;
}): this;
withAbortSignal(signal: AbortSignal): this;
normalize(): this;
filter(predicate: FilterPredicate): this;
onlyDirs(): this;
exclude(predicate: ExcludePredicate): this;
onlyCounts(): Builder<OnlyCountsOutput, TGlobFunction>;
crawl(root?: string): APIBuilder<TReturnType>;
withGlobFunction<TFunc>(fn: TFunc): Builder<TReturnType, TFunc>;
/**
* @deprecated Pass options using the constructor instead:
* ```ts
* new fdir(options).crawl("/path/to/root");
* ```
* This method will be removed in v7.0
*/
crawlWithOptions(root: string, options: Partial<Options<TGlobFunction>>): APIBuilder<TReturnType>;
glob(...patterns: string[]): Builder<TReturnType, TGlobFunction>;
globWithOptions(patterns: string[]): Builder<TReturnType, TGlobFunction>;
globWithOptions(patterns: string[], ...options: GlobParams<TGlobFunction>): Builder<TReturnType, TGlobFunction>;
}
//#endregion
//#region src/index.d.ts
type Fdir = typeof Builder;
//#endregion
export { Counts, ExcludePredicate, FSLike, Fdir, FilterPredicate, GlobFunction, GlobMatcher, GlobParams, Group, GroupOutput, OnlyCountsOutput, Options, Output, PathSeparator, PathsOutput, ResultCallback, WalkerState, Builder as fdir };
+570
View File
@@ -0,0 +1,570 @@
import { createRequire } from "module";
import { basename, dirname, normalize, relative, resolve, sep } from "path";
import * as nativeFs from "fs";
//#region rolldown:runtime
var __require = /* @__PURE__ */ createRequire(import.meta.url);
//#endregion
//#region src/utils.ts
function cleanPath(path) {
let normalized = normalize(path);
if (normalized.length > 1 && normalized[normalized.length - 1] === sep) normalized = normalized.substring(0, normalized.length - 1);
return normalized;
}
const SLASHES_REGEX = /[\\/]/g;
function convertSlashes(path, separator) {
return path.replace(SLASHES_REGEX, separator);
}
const WINDOWS_ROOT_DIR_REGEX = /^[a-z]:[\\/]$/i;
function isRootDirectory(path) {
return path === "/" || WINDOWS_ROOT_DIR_REGEX.test(path);
}
function normalizePath(path, options) {
const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options;
const pathNeedsCleaning = process.platform === "win32" && path.includes("/") || path.startsWith(".");
if (resolvePaths) path = resolve(path);
if (normalizePath$1 || pathNeedsCleaning) path = cleanPath(path);
if (path === ".") return "";
const needsSeperator = path[path.length - 1] !== pathSeparator;
return convertSlashes(needsSeperator ? path + pathSeparator : path, pathSeparator);
}
//#endregion
//#region src/api/functions/join-path.ts
function joinPathWithBasePath(filename, directoryPath) {
return directoryPath + filename;
}
function joinPathWithRelativePath(root, options) {
return function(filename, directoryPath) {
const sameRoot = directoryPath.startsWith(root);
if (sameRoot) return directoryPath.slice(root.length) + filename;
else return convertSlashes(relative(root, directoryPath), options.pathSeparator) + options.pathSeparator + filename;
};
}
function joinPath(filename) {
return filename;
}
function joinDirectoryPath(filename, directoryPath, separator) {
return directoryPath + filename + separator;
}
function build$7(root, options) {
const { relativePaths, includeBasePath } = options;
return relativePaths && root ? joinPathWithRelativePath(root, options) : includeBasePath ? joinPathWithBasePath : joinPath;
}
//#endregion
//#region src/api/functions/push-directory.ts
function pushDirectoryWithRelativePath(root) {
return function(directoryPath, paths) {
paths.push(directoryPath.substring(root.length) || ".");
};
}
function pushDirectoryFilterWithRelativePath(root) {
return function(directoryPath, paths, filters) {
const relativePath = directoryPath.substring(root.length) || ".";
if (filters.every((filter) => filter(relativePath, true))) paths.push(relativePath);
};
}
const pushDirectory = (directoryPath, paths) => {
paths.push(directoryPath || ".");
};
const pushDirectoryFilter = (directoryPath, paths, filters) => {
const path = directoryPath || ".";
if (filters.every((filter) => filter(path, true))) paths.push(path);
};
const empty$2 = () => {};
function build$6(root, options) {
const { includeDirs, filters, relativePaths } = options;
if (!includeDirs) return empty$2;
if (relativePaths) return filters && filters.length ? pushDirectoryFilterWithRelativePath(root) : pushDirectoryWithRelativePath(root);
return filters && filters.length ? pushDirectoryFilter : pushDirectory;
}
//#endregion
//#region src/api/functions/push-file.ts
const pushFileFilterAndCount = (filename, _paths, counts, filters) => {
if (filters.every((filter) => filter(filename, false))) counts.files++;
};
const pushFileFilter = (filename, paths, _counts, filters) => {
if (filters.every((filter) => filter(filename, false))) paths.push(filename);
};
const pushFileCount = (_filename, _paths, counts, _filters) => {
counts.files++;
};
const pushFile = (filename, paths) => {
paths.push(filename);
};
const empty$1 = () => {};
function build$5(options) {
const { excludeFiles, filters, onlyCounts } = options;
if (excludeFiles) return empty$1;
if (filters && filters.length) return onlyCounts ? pushFileFilterAndCount : pushFileFilter;
else if (onlyCounts) return pushFileCount;
else return pushFile;
}
//#endregion
//#region src/api/functions/get-array.ts
const getArray = (paths) => {
return paths;
};
const getArrayGroup = () => {
return [""].slice(0, 0);
};
function build$4(options) {
return options.group ? getArrayGroup : getArray;
}
//#endregion
//#region src/api/functions/group-files.ts
const groupFiles = (groups, directory, files) => {
groups.push({
directory,
files,
dir: directory
});
};
const empty = () => {};
function build$3(options) {
return options.group ? groupFiles : empty;
}
//#endregion
//#region src/api/functions/resolve-symlink.ts
const resolveSymlinksAsync = function(path, state, callback$1) {
const { queue, fs, options: { suppressErrors } } = state;
queue.enqueue();
fs.realpath(path, (error, resolvedPath) => {
if (error) return queue.dequeue(suppressErrors ? null : error, state);
fs.stat(resolvedPath, (error$1, stat) => {
if (error$1) return queue.dequeue(suppressErrors ? null : error$1, state);
if (stat.isDirectory() && isRecursive(path, resolvedPath, state)) return queue.dequeue(null, state);
callback$1(stat, resolvedPath);
queue.dequeue(null, state);
});
});
};
const resolveSymlinks = function(path, state, callback$1) {
const { queue, fs, options: { suppressErrors } } = state;
queue.enqueue();
try {
const resolvedPath = fs.realpathSync(path);
const stat = fs.statSync(resolvedPath);
if (stat.isDirectory() && isRecursive(path, resolvedPath, state)) return;
callback$1(stat, resolvedPath);
} catch (e) {
if (!suppressErrors) throw e;
}
};
function build$2(options, isSynchronous) {
if (!options.resolveSymlinks || options.excludeSymlinks) return null;
return isSynchronous ? resolveSymlinks : resolveSymlinksAsync;
}
function isRecursive(path, resolved, state) {
if (state.options.useRealPaths) return isRecursiveUsingRealPaths(resolved, state);
let parent = dirname(path);
let depth = 1;
while (parent !== state.root && depth < 2) {
const resolvedPath = state.symlinks.get(parent);
const isSameRoot = !!resolvedPath && (resolvedPath === resolved || resolvedPath.startsWith(resolved) || resolved.startsWith(resolvedPath));
if (isSameRoot) depth++;
else parent = dirname(parent);
}
state.symlinks.set(path, resolved);
return depth > 1;
}
function isRecursiveUsingRealPaths(resolved, state) {
return state.visited.includes(resolved + state.options.pathSeparator);
}
//#endregion
//#region src/api/functions/invoke-callback.ts
const onlyCountsSync = (state) => {
return state.counts;
};
const groupsSync = (state) => {
return state.groups;
};
const defaultSync = (state) => {
return state.paths;
};
const limitFilesSync = (state) => {
return state.paths.slice(0, state.options.maxFiles);
};
const onlyCountsAsync = (state, error, callback$1) => {
report(error, callback$1, state.counts, state.options.suppressErrors);
return null;
};
const defaultAsync = (state, error, callback$1) => {
report(error, callback$1, state.paths, state.options.suppressErrors);
return null;
};
const limitFilesAsync = (state, error, callback$1) => {
report(error, callback$1, state.paths.slice(0, state.options.maxFiles), state.options.suppressErrors);
return null;
};
const groupsAsync = (state, error, callback$1) => {
report(error, callback$1, state.groups, state.options.suppressErrors);
return null;
};
function report(error, callback$1, output, suppressErrors) {
if (error && !suppressErrors) callback$1(error, output);
else callback$1(null, output);
}
function build$1(options, isSynchronous) {
const { onlyCounts, group, maxFiles } = options;
if (onlyCounts) return isSynchronous ? onlyCountsSync : onlyCountsAsync;
else if (group) return isSynchronous ? groupsSync : groupsAsync;
else if (maxFiles) return isSynchronous ? limitFilesSync : limitFilesAsync;
else return isSynchronous ? defaultSync : defaultAsync;
}
//#endregion
//#region src/api/functions/walk-directory.ts
const readdirOpts = { withFileTypes: true };
const walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
state.queue.enqueue();
if (currentDepth < 0) return state.queue.dequeue(null, state);
const { fs } = state;
state.visited.push(crawlPath);
state.counts.directories++;
fs.readdir(crawlPath || ".", readdirOpts, (error, entries = []) => {
callback$1(entries, directoryPath, currentDepth);
state.queue.dequeue(state.options.suppressErrors ? null : error, state);
});
};
const walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
const { fs } = state;
if (currentDepth < 0) return;
state.visited.push(crawlPath);
state.counts.directories++;
let entries = [];
try {
entries = fs.readdirSync(crawlPath || ".", readdirOpts);
} catch (e) {
if (!state.options.suppressErrors) throw e;
}
callback$1(entries, directoryPath, currentDepth);
};
function build(isSynchronous) {
return isSynchronous ? walkSync : walkAsync;
}
//#endregion
//#region src/api/queue.ts
/**
* This is a custom stateless queue to track concurrent async fs calls.
* It increments a counter whenever a call is queued and decrements it
* as soon as it completes. When the counter hits 0, it calls onQueueEmpty.
*/
var Queue = class {
count = 0;
constructor(onQueueEmpty) {
this.onQueueEmpty = onQueueEmpty;
}
enqueue() {
this.count++;
return this.count;
}
dequeue(error, output) {
if (this.onQueueEmpty && (--this.count <= 0 || error)) {
this.onQueueEmpty(error, output);
if (error) {
output.controller.abort();
this.onQueueEmpty = void 0;
}
}
}
};
//#endregion
//#region src/api/counter.ts
var Counter = class {
_files = 0;
_directories = 0;
set files(num) {
this._files = num;
}
get files() {
return this._files;
}
set directories(num) {
this._directories = num;
}
get directories() {
return this._directories;
}
/**
* @deprecated use `directories` instead
*/
/* c8 ignore next 3 */
get dirs() {
return this._directories;
}
};
//#endregion
//#region src/api/aborter.ts
/**
* AbortController is not supported on Node 14 so we use this until we can drop
* support for Node 14.
*/
var Aborter = class {
aborted = false;
abort() {
this.aborted = true;
}
};
//#endregion
//#region src/api/walker.ts
var Walker = class {
root;
isSynchronous;
state;
joinPath;
pushDirectory;
pushFile;
getArray;
groupFiles;
resolveSymlink;
walkDirectory;
callbackInvoker;
constructor(root, options, callback$1) {
this.isSynchronous = !callback$1;
this.callbackInvoker = build$1(options, this.isSynchronous);
this.root = normalizePath(root, options);
this.state = {
root: isRootDirectory(this.root) ? this.root : this.root.slice(0, -1),
paths: [""].slice(0, 0),
groups: [],
counts: new Counter(),
options,
queue: new Queue((error, state) => this.callbackInvoker(state, error, callback$1)),
symlinks: /* @__PURE__ */ new Map(),
visited: [""].slice(0, 0),
controller: new Aborter(),
fs: options.fs || nativeFs
};
this.joinPath = build$7(this.root, options);
this.pushDirectory = build$6(this.root, options);
this.pushFile = build$5(options);
this.getArray = build$4(options);
this.groupFiles = build$3(options);
this.resolveSymlink = build$2(options, this.isSynchronous);
this.walkDirectory = build(this.isSynchronous);
}
start() {
this.pushDirectory(this.root, this.state.paths, this.state.options.filters);
this.walkDirectory(this.state, this.root, this.root, this.state.options.maxDepth, this.walk);
return this.isSynchronous ? this.callbackInvoker(this.state, null) : null;
}
walk = (entries, directoryPath, depth) => {
const { paths, options: { filters, resolveSymlinks: resolveSymlinks$1, excludeSymlinks, exclude, maxFiles, signal, useRealPaths, pathSeparator }, controller } = this.state;
if (controller.aborted || signal && signal.aborted || maxFiles && paths.length > maxFiles) return;
const files = this.getArray(this.state.paths);
for (let i = 0; i < entries.length; ++i) {
const entry = entries[i];
if (entry.isFile() || entry.isSymbolicLink() && !resolveSymlinks$1 && !excludeSymlinks) {
const filename = this.joinPath(entry.name, directoryPath);
this.pushFile(filename, files, this.state.counts, filters);
} else if (entry.isDirectory()) {
let path = joinDirectoryPath(entry.name, directoryPath, this.state.options.pathSeparator);
if (exclude && exclude(entry.name, path)) continue;
this.pushDirectory(path, paths, filters);
this.walkDirectory(this.state, path, path, depth - 1, this.walk);
} else if (this.resolveSymlink && entry.isSymbolicLink()) {
let path = joinPathWithBasePath(entry.name, directoryPath);
this.resolveSymlink(path, this.state, (stat, resolvedPath) => {
if (stat.isDirectory()) {
resolvedPath = normalizePath(resolvedPath, this.state.options);
if (exclude && exclude(entry.name, useRealPaths ? resolvedPath : path + pathSeparator)) return;
this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath : path + pathSeparator, depth - 1, this.walk);
} else {
resolvedPath = useRealPaths ? resolvedPath : path;
const filename = basename(resolvedPath);
const directoryPath$1 = normalizePath(dirname(resolvedPath), this.state.options);
resolvedPath = this.joinPath(filename, directoryPath$1);
this.pushFile(resolvedPath, files, this.state.counts, filters);
}
});
}
}
this.groupFiles(this.state.groups, directoryPath, files);
};
};
//#endregion
//#region src/api/async.ts
function promise(root, options) {
return new Promise((resolve$1, reject) => {
callback(root, options, (err, output) => {
if (err) return reject(err);
resolve$1(output);
});
});
}
function callback(root, options, callback$1) {
let walker = new Walker(root, options, callback$1);
walker.start();
}
//#endregion
//#region src/api/sync.ts
function sync(root, options) {
const walker = new Walker(root, options);
return walker.start();
}
//#endregion
//#region src/builder/api-builder.ts
var APIBuilder = class {
constructor(root, options) {
this.root = root;
this.options = options;
}
withPromise() {
return promise(this.root, this.options);
}
withCallback(cb) {
callback(this.root, this.options, cb);
}
sync() {
return sync(this.root, this.options);
}
};
//#endregion
//#region src/builder/index.ts
let pm = null;
/* c8 ignore next 6 */
try {
__require.resolve("picomatch");
pm = __require("picomatch");
} catch {}
var Builder = class {
globCache = {};
options = {
maxDepth: Infinity,
suppressErrors: true,
pathSeparator: sep,
filters: []
};
globFunction;
constructor(options) {
this.options = {
...this.options,
...options
};
this.globFunction = this.options.globFunction;
}
group() {
this.options.group = true;
return this;
}
withPathSeparator(separator) {
this.options.pathSeparator = separator;
return this;
}
withBasePath() {
this.options.includeBasePath = true;
return this;
}
withRelativePaths() {
this.options.relativePaths = true;
return this;
}
withDirs() {
this.options.includeDirs = true;
return this;
}
withMaxDepth(depth) {
this.options.maxDepth = depth;
return this;
}
withMaxFiles(limit) {
this.options.maxFiles = limit;
return this;
}
withFullPaths() {
this.options.resolvePaths = true;
this.options.includeBasePath = true;
return this;
}
withErrors() {
this.options.suppressErrors = false;
return this;
}
withSymlinks({ resolvePaths = true } = {}) {
this.options.resolveSymlinks = true;
this.options.useRealPaths = resolvePaths;
return this.withFullPaths();
}
withAbortSignal(signal) {
this.options.signal = signal;
return this;
}
normalize() {
this.options.normalizePath = true;
return this;
}
filter(predicate) {
this.options.filters.push(predicate);
return this;
}
onlyDirs() {
this.options.excludeFiles = true;
this.options.includeDirs = true;
return this;
}
exclude(predicate) {
this.options.exclude = predicate;
return this;
}
onlyCounts() {
this.options.onlyCounts = true;
return this;
}
crawl(root) {
return new APIBuilder(root || ".", this.options);
}
withGlobFunction(fn) {
this.globFunction = fn;
return this;
}
/**
* @deprecated Pass options using the constructor instead:
* ```ts
* new fdir(options).crawl("/path/to/root");
* ```
* This method will be removed in v7.0
*/
/* c8 ignore next 4 */
crawlWithOptions(root, options) {
this.options = {
...this.options,
...options
};
return new APIBuilder(root || ".", this.options);
}
glob(...patterns) {
if (this.globFunction) return this.globWithOptions(patterns);
return this.globWithOptions(patterns, ...[{ dot: true }]);
}
globWithOptions(patterns, ...options) {
const globFn = this.globFunction || pm;
/* c8 ignore next 5 */
if (!globFn) throw new Error("Please specify a glob function to use glob matching.");
var isMatch = this.globCache[patterns.join("\0")];
if (!isMatch) {
isMatch = globFn(patterns, ...options);
this.globCache[patterns.join("\0")] = isMatch;
}
this.options.filters.push((path) => isMatch(path));
return this;
}
};
//#endregion
export { Builder as fdir };
+103
View File
@@ -0,0 +1,103 @@
{
"name": "fdir",
"version": "6.5.0",
"description": "The fastest directory crawler & globbing alternative to glob, fast-glob, & tiny-glob. Crawls 1m files in < 1s",
"main": "./dist/index.cjs",
"types": "./dist/index.d.cts",
"type": "module",
"scripts": {
"prepublishOnly": "npm run test && npm run build",
"build": "tsdown",
"format": "prettier --write src __tests__ benchmarks",
"test": "vitest run __tests__/",
"test:coverage": "vitest run --coverage __tests__/",
"test:watch": "vitest __tests__/",
"bench": "ts-node benchmarks/benchmark.js",
"bench:glob": "ts-node benchmarks/glob-benchmark.ts",
"bench:fdir": "ts-node benchmarks/fdir-benchmark.ts",
"release": "./scripts/release.sh"
},
"engines": {
"node": ">=12.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/thecodrr/fdir.git"
},
"keywords": [
"util",
"os",
"sys",
"fs",
"walk",
"crawler",
"directory",
"files",
"io",
"tiny-glob",
"glob",
"fast-glob",
"speed",
"javascript",
"nodejs"
],
"author": "thecodrr <thecodrr@protonmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/thecodrr/fdir/issues"
},
"homepage": "https://github.com/thecodrr/fdir#readme",
"devDependencies": {
"@types/glob": "^8.1.0",
"@types/mock-fs": "^4.13.4",
"@types/node": "^20.9.4",
"@types/picomatch": "^4.0.0",
"@types/tap": "^15.0.11",
"@vitest/coverage-v8": "^0.34.6",
"all-files-in-tree": "^1.1.2",
"benny": "^3.7.1",
"csv-to-markdown-table": "^1.3.1",
"expect": "^29.7.0",
"fast-glob": "^3.3.2",
"fdir1": "npm:fdir@1.2.0",
"fdir2": "npm:fdir@2.1.0",
"fdir3": "npm:fdir@3.4.2",
"fdir4": "npm:fdir@4.1.0",
"fdir5": "npm:fdir@5.0.0",
"fs-readdir-recursive": "^1.1.0",
"get-all-files": "^4.1.0",
"glob": "^10.3.10",
"klaw-sync": "^6.0.0",
"mock-fs": "^5.2.0",
"picomatch": "^4.0.2",
"prettier": "^3.5.3",
"recur-readdir": "0.0.1",
"recursive-files": "^1.0.2",
"recursive-fs": "^2.1.0",
"recursive-readdir": "^2.2.3",
"rrdir": "^12.1.0",
"systeminformation": "^5.21.17",
"tiny-glob": "^0.2.9",
"ts-node": "^10.9.1",
"tsdown": "^0.12.5",
"typescript": "^5.3.2",
"vitest": "^0.34.6",
"walk-sync": "^3.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
},
"module": "./dist/index.mjs",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./package.json": "./package.json"
}
}
+20
View File
@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright 2017 Andrey Sitnik <andrey@sitnik.ru>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+39
View File
@@ -0,0 +1,39 @@
# Nano ID
<img src="https://ai.github.io/nanoid/logo.svg" align="right"
alt="Nano ID logo by Anton Lovchikov" width="180" height="94">
**English** | [Русский](./README.ru.md) | [简体中文](./README.zh-CN.md) | [Bahasa Indonesia](./README.id-ID.md)
A tiny, secure, URL-friendly, unique string ID generator for JavaScript.
> “An amazing level of senseless perfectionism,
> which is simply impossible not to respect.”
* **Small.** 130 bytes (minified and gzipped). No dependencies.
[Size Limit] controls the size.
* **Fast.** It is 2 times faster than UUID.
* **Safe.** It uses hardware random generator. Can be used in clusters.
* **Short IDs.** It uses a larger alphabet than UUID (`A-Za-z0-9_-`).
So ID size was reduced from 36 to 21 symbols.
* **Portable.** Nano ID was ported
to [20 programming languages](#other-programming-languages).
```js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"
```
Supports modern browsers, IE [with Babel], Node.js and React Native.
[online tool]: https://gitpod.io/#https://github.com/ai/nanoid/
[with Babel]: https://developer.epages.com/blog/coding/how-to-transpile-node-modules-with-babel-and-webpack-in-a-monorepo/
[Size Limit]: https://github.com/ai/size-limit
<a href="https://evilmartians.com/?utm_source=nanoid">
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
alt="Sponsored by Evil Martians" width="236" height="54">
</a>
## Docs
Read full docs **[here](https://github.com/ai/nanoid#readme)**.
+43
View File
@@ -0,0 +1,43 @@
let random = async bytes => crypto.getRandomValues(new Uint8Array(bytes))
let customAlphabet = (alphabet, defaultSize = 21) => {
let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
let step = -~((1.6 * mask * defaultSize) / alphabet.length)
return async (size = defaultSize) => {
if (size <= 0) return ''
let id = ''
while (true) {
let bytes = crypto.getRandomValues(new Uint8Array(step))
let i = step | 0
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length === size) return id
}
}
}
}
let nanoid = async (size = 21) => {
let id = ''
let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)))
while (size--) {
let byte = bytes[size] & 63
if (byte < 36) {
id += byte.toString(36)
} else if (byte < 62) {
id += (byte - 26).toString(36).toUpperCase()
} else if (byte < 63) {
id += '_'
} else {
id += '-'
}
}
return id
}
module.exports = { nanoid, customAlphabet, random }
+43
View File
@@ -0,0 +1,43 @@
let random = async bytes => crypto.getRandomValues(new Uint8Array(bytes))
let customAlphabet = (alphabet, defaultSize = 21) => {
let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
let step = -~((1.6 * mask * defaultSize) / alphabet.length)
return async (size = defaultSize) => {
if (size <= 0) return ''
let id = ''
while (true) {
let bytes = crypto.getRandomValues(new Uint8Array(step))
let i = step | 0
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length === size) return id
}
}
}
}
let nanoid = async (size = 21) => {
let id = ''
let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)))
while (size--) {
let byte = bytes[size] & 63
if (byte < 36) {
id += byte.toString(36)
} else if (byte < 62) {
id += (byte - 26).toString(36).toUpperCase()
} else if (byte < 63) {
id += '_'
} else {
id += '-'
}
}
return id
}
export { nanoid, customAlphabet, random }
+47
View File
@@ -0,0 +1,47 @@
let crypto = require('crypto')
let { urlAlphabet } = require('../url-alphabet/index.cjs')
let random = bytes =>
new Promise((resolve, reject) => {
crypto.randomFill(Buffer.allocUnsafe(bytes), (err, buf) => {
if (err) {
reject(err)
} else {
resolve(buf)
}
})
})
let customAlphabet = (alphabet, defaultSize = 21) => {
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
let tick = (id, size = defaultSize) =>
random(step).then(bytes => {
let i = step
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length >= size) return id
}
return tick(id, size)
})
return (size = defaultSize) => {
if (size <= 0) return Promise.resolve('')
return tick('', size)
}
}
let nanoid = (size = 21) =>
random((size |= 0)).then(bytes => {
let id = ''
while (size--) {
id += urlAlphabet[bytes[size] & 63]
}
return id
})
module.exports = { nanoid, customAlphabet, random }
+56
View File
@@ -0,0 +1,56 @@
/**
* Generate secure URL-friendly unique ID. The non-blocking version.
*
* By default, the ID will have 21 symbols to have a collision probability
* similar to UUID v4.
*
* ```js
* import { nanoid } from 'nanoid/async'
* nanoid().then(id => {
* model.id = id
* })
* ```
*
* @param size Size of the ID. The default size is 21.
* @returns A promise with a random string.
*/
export function nanoid(size?: number): Promise<string>
/**
* A low-level function.
* Generate secure unique ID with custom alphabet. The non-blocking version.
*
* Alphabet must contain 256 symbols or less. Otherwise, the generator
* will not be secure.
*
* @param alphabet Alphabet used to generate the ID.
* @param defaultSize Size of the ID. The default size is 21.
* @returns A function that returns a promise with a random string.
*
* ```js
* import { customAlphabet } from 'nanoid/async'
* const nanoid = customAlphabet('0123456789абвгдеё', 5)
* nanoid().then(id => {
* model.id = id //=> "8ё56а"
* })
* ```
*/
export function customAlphabet(
alphabet: string,
defaultSize?: number
): (size?: number) => Promise<string>
/**
* Generate an array of random bytes collected from hardware noise.
*
* ```js
* import { random } from 'nanoid/async'
* random(5).then(bytes => {
* bytes //=> [10, 67, 212, 67, 89]
* })
* ```
*
* @param bytes Size of the array.
* @returns A promise with a random bytes array.
*/
export function random(bytes: number): Promise<Uint8Array>
+47
View File
@@ -0,0 +1,47 @@
import crypto from 'crypto'
import { urlAlphabet } from '../url-alphabet/index.js'
let random = bytes =>
new Promise((resolve, reject) => {
crypto.randomFill(Buffer.allocUnsafe(bytes), (err, buf) => {
if (err) {
reject(err)
} else {
resolve(buf)
}
})
})
let customAlphabet = (alphabet, defaultSize = 21) => {
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
let tick = (id, size = defaultSize) =>
random(step).then(bytes => {
let i = step
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length >= size) return id
}
return tick(id, size)
})
return (size = defaultSize) => {
if (size <= 0) return Promise.resolve('')
return tick('', size)
}
}
let nanoid = (size = 21) =>
random((size |= 0)).then(bytes => {
let id = ''
while (size--) {
id += urlAlphabet[bytes[size] & 63]
}
return id
})
export { nanoid, customAlphabet, random }
+38
View File
@@ -0,0 +1,38 @@
import { getRandomBytesAsync } from 'expo-random'
import { urlAlphabet } from '../url-alphabet/index.js'
let random = getRandomBytesAsync
let customAlphabet = (alphabet, defaultSize = 21) => {
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
let tick = (id, size = defaultSize) =>
random(step).then(bytes => {
let i = step
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length >= size) return id
}
return tick(id, size)
})
return (size = defaultSize) => {
if (size <= 0) return Promise.resolve('')
return tick('', size)
}
}
let nanoid = (size = 21) =>
random((size |= 0)).then(bytes => {
let id = ''
while (size--) {
id += urlAlphabet[bytes[size] & 63]
}
return id
})
export { nanoid, customAlphabet, random }
+12
View File
@@ -0,0 +1,12 @@
{
"type": "module",
"main": "index.cjs",
"module": "index.js",
"react-native": {
"./index.js": "./index.native.js"
},
"browser": {
"./index.js": "./index.browser.js",
"./index.cjs": "./index.browser.cjs"
}
}
Generated Vendored Executable
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env node
let { nanoid, customAlphabet } = require('..')
function print(msg) {
process.stdout.write(msg + '\n')
}
function error(msg) {
process.stderr.write(msg + '\n')
process.exit(1)
}
if (process.argv.includes('--help') || process.argv.includes('-h')) {
print(`
Usage
$ nanoid [options]
Options
-s, --size Generated ID size
-a, --alphabet Alphabet to use
-h, --help Show this help
Examples
$ nanoid --s 15
S9sBF77U6sDB8Yg
$ nanoid --size 10 --alphabet abc
bcabababca`)
process.exit()
}
let alphabet, size
for (let i = 2; i < process.argv.length; i++) {
let arg = process.argv[i]
if (arg === '--size' || arg === '-s') {
size = Number(process.argv[i + 1])
i += 1
if (Number.isNaN(size) || size <= 0) {
error('Size must be positive integer')
}
} else if (arg === '--alphabet' || arg === '-a') {
alphabet = process.argv[i + 1]
i += 1
} else {
error('Unknown argument ' + arg)
}
}
if (alphabet) {
let customNanoid = customAlphabet(alphabet, size)
print(customNanoid())
} else {
print(nanoid(size))
}
+45
View File
@@ -0,0 +1,45 @@
let { urlAlphabet } = require('./url-alphabet/index.cjs')
let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))
let customRandom = (alphabet, defaultSize, getRandom) => {
let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
let step = -~((1.6 * mask * defaultSize) / alphabet.length)
return (size = defaultSize) => {
if (size <= 0) return ''
let id = ''
while (true) {
let bytes = getRandom(step)
let j = step | 0
while (j--) {
id += alphabet[bytes[j] & mask] || ''
if (id.length === size) return id
}
}
}
}
let customAlphabet = (alphabet, size = 21) =>
customRandom(alphabet, size, random)
let nanoid = (size = 21) =>
crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
byte &= 63
if (byte < 36) {
id += byte.toString(36)
} else if (byte < 62) {
id += (byte - 26).toString(36).toUpperCase()
} else if (byte > 62) {
id += '-'
} else {
id += '_'
}
return id
}, '')
module.exports = { nanoid, customAlphabet, customRandom, urlAlphabet, random }
+45
View File
@@ -0,0 +1,45 @@
import { urlAlphabet } from './url-alphabet/index.js'
let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))
let customRandom = (alphabet, defaultSize, getRandom) => {
let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
let step = -~((1.6 * mask * defaultSize) / alphabet.length)
return (size = defaultSize) => {
if (size <= 0) return ''
let id = ''
while (true) {
let bytes = getRandom(step)
let j = step | 0
while (j--) {
id += alphabet[bytes[j] & mask] || ''
if (id.length === size) return id
}
}
}
}
let customAlphabet = (alphabet, size = 21) =>
customRandom(alphabet, size, random)
let nanoid = (size = 21) =>
crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
byte &= 63
if (byte < 36) {
id += byte.toString(36)
} else if (byte < 62) {
id += (byte - 26).toString(36).toUpperCase()
} else if (byte > 62) {
id += '-'
} else {
id += '_'
}
return id
}, '')
export { nanoid, customAlphabet, customRandom, urlAlphabet, random }
+63
View File
@@ -0,0 +1,63 @@
let crypto = require('crypto')
let { urlAlphabet } = require('./url-alphabet/index.cjs')
const POOL_SIZE_MULTIPLIER = 128
let pool, poolOffset
let fillPool = bytes => {
if (bytes < 0 || bytes > 1024) throw new RangeError('Wrong ID size')
try {
if (!pool || pool.length < bytes) {
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)
crypto.randomFillSync(pool)
poolOffset = 0
} else if (poolOffset + bytes > pool.length) {
crypto.randomFillSync(pool)
poolOffset = 0
}
} catch (e) {
pool = undefined
throw e
}
poolOffset += bytes
}
let random = bytes => {
fillPool((bytes |= 0))
return pool.subarray(poolOffset - bytes, poolOffset)
}
let customRandom = (alphabet, defaultSize, getRandom) => {
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
return (size = defaultSize) => {
if (size <= 0) return ''
let id = ''
while (true) {
let bytes = getRandom(step)
let i = step
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length === size) return id
}
}
}
}
let customAlphabet = (alphabet, size = 21) =>
customRandom(alphabet, size, random)
let nanoid = (size = 21) => {
fillPool((size |= 0))
let id = ''
for (let i = poolOffset - size; i < poolOffset; i++) {
id += urlAlphabet[pool[i] & 63]
}
return id
}
module.exports = { nanoid, customAlphabet, customRandom, urlAlphabet, random }
+91
View File
@@ -0,0 +1,91 @@
/**
* Generate secure URL-friendly unique ID.
*
* By default, the ID will have 21 symbols to have a collision probability
* similar to UUID v4.
*
* ```js
* import { nanoid } from 'nanoid'
* model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
* ```
*
* @param size Size of the ID. The default size is 21.
* @returns A random string.
*/
export function nanoid(size?: number): string
/**
* Generate secure unique ID with custom alphabet.
*
* Alphabet must contain 256 symbols or less. Otherwise, the generator
* will not be secure.
*
* @param alphabet Alphabet used to generate the ID.
* @param defaultSize Size of the ID. The default size is 21.
* @returns A random string generator.
*
* ```js
* const { customAlphabet } = require('nanoid')
* const nanoid = customAlphabet('0123456789абвгдеё', 5)
* nanoid() //=> "8ё56а"
* ```
*/
export function customAlphabet(
alphabet: string,
defaultSize?: number
): (size?: number) => string
/**
* Generate unique ID with custom random generator and alphabet.
*
* Alphabet must contain 256 symbols or less. Otherwise, the generator
* will not be secure.
*
* ```js
* import { customRandom } from 'nanoid/format'
*
* const nanoid = customRandom('abcdef', 5, size => {
* const random = []
* for (let i = 0; i < size; i++) {
* random.push(randomByte())
* }
* return random
* })
*
* nanoid() //=> "fbaef"
* ```
*
* @param alphabet Alphabet used to generate a random string.
* @param size Size of the random string.
* @param random A random bytes generator.
* @returns A random string generator.
*/
export function customRandom(
alphabet: string,
size: number,
random: (bytes: number) => Uint8Array
): () => string
/**
* URL safe symbols.
*
* ```js
* import { urlAlphabet } from 'nanoid'
* const nanoid = customAlphabet(urlAlphabet, 10)
* nanoid() //=> "Uakgb_J5m9"
* ```
*/
export const urlAlphabet: string
/**
* Generate an array of random bytes collected from hardware noise.
*
* ```js
* import { customRandom, random } from 'nanoid'
* const nanoid = customRandom("abcdef", 5, random)
* ```
*
* @param bytes Size of the array.
* @returns An array of random bytes.
*/
export function random(bytes: number): Uint8Array
+91
View File
@@ -0,0 +1,91 @@
/**
* Generate secure URL-friendly unique ID.
*
* By default, the ID will have 21 symbols to have a collision probability
* similar to UUID v4.
*
* ```js
* import { nanoid } from 'nanoid'
* model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
* ```
*
* @param size Size of the ID. The default size is 21.
* @returns A random string.
*/
export function nanoid(size?: number): string
/**
* Generate secure unique ID with custom alphabet.
*
* Alphabet must contain 256 symbols or less. Otherwise, the generator
* will not be secure.
*
* @param alphabet Alphabet used to generate the ID.
* @param defaultSize Size of the ID. The default size is 21.
* @returns A random string generator.
*
* ```js
* const { customAlphabet } = require('nanoid')
* const nanoid = customAlphabet('0123456789абвгдеё', 5)
* nanoid() //=> "8ё56а"
* ```
*/
export function customAlphabet(
alphabet: string,
defaultSize?: number
): (size?: number) => string
/**
* Generate unique ID with custom random generator and alphabet.
*
* Alphabet must contain 256 symbols or less. Otherwise, the generator
* will not be secure.
*
* ```js
* import { customRandom } from 'nanoid/format'
*
* const nanoid = customRandom('abcdef', 5, size => {
* const random = []
* for (let i = 0; i < size; i++) {
* random.push(randomByte())
* }
* return random
* })
*
* nanoid() //=> "fbaef"
* ```
*
* @param alphabet Alphabet used to generate a random string.
* @param size Size of the random string.
* @param random A random bytes generator.
* @returns A random string generator.
*/
export function customRandom(
alphabet: string,
size: number,
random: (bytes: number) => Uint8Array
): () => string
/**
* URL safe symbols.
*
* ```js
* import { urlAlphabet } from 'nanoid'
* const nanoid = customAlphabet(urlAlphabet, 10)
* nanoid() //=> "Uakgb_J5m9"
* ```
*/
export const urlAlphabet: string
/**
* Generate an array of random bytes collected from hardware noise.
*
* ```js
* import { customRandom, random } from 'nanoid'
* const nanoid = customRandom("abcdef", 5, random)
* ```
*
* @param bytes Size of the array.
* @returns An array of random bytes.
*/
export function random(bytes: number): Uint8Array
+63
View File
@@ -0,0 +1,63 @@
import crypto from 'crypto'
import { urlAlphabet } from './url-alphabet/index.js'
const POOL_SIZE_MULTIPLIER = 128
let pool, poolOffset
let fillPool = bytes => {
if (bytes < 0 || bytes > 1024) throw new RangeError('Wrong ID size')
try {
if (!pool || pool.length < bytes) {
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)
crypto.randomFillSync(pool)
poolOffset = 0
} else if (poolOffset + bytes > pool.length) {
crypto.randomFillSync(pool)
poolOffset = 0
}
} catch (e) {
pool = undefined
throw e
}
poolOffset += bytes
}
let random = bytes => {
fillPool((bytes |= 0))
return pool.subarray(poolOffset - bytes, poolOffset)
}
let customRandom = (alphabet, defaultSize, getRandom) => {
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
return (size = defaultSize) => {
if (size <= 0) return ''
let id = ''
while (true) {
let bytes = getRandom(step)
let i = step
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length === size) return id
}
}
}
}
let customAlphabet = (alphabet, size = 21) =>
customRandom(alphabet, size, random)
let nanoid = (size = 21) => {
fillPool((size |= 0))
let id = ''
for (let i = poolOffset - size; i < poolOffset; i++) {
id += urlAlphabet[pool[i] & 63]
}
return id
}
export { nanoid, customAlphabet, customRandom, urlAlphabet, random }
+1
View File
@@ -0,0 +1 @@
export let nanoid=(t=21)=>crypto.getRandomValues(new Uint8Array(t)).reduce(((t,e)=>t+=(e&=63)<36?e.toString(36):e<62?(e-26).toString(36).toUpperCase():e<63?"_":"-"),"");
+24
View File
@@ -0,0 +1,24 @@
let urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
let customAlphabet = (alphabet, defaultSize = 21) => {
return (size = defaultSize) => {
let id = ''
let i = size | 0
while (i-- > 0) {
id += alphabet[(Math.random() * alphabet.length) | 0]
}
return id
}
}
let nanoid = (size = 21) => {
let id = ''
let i = size | 0
while (i-- > 0) {
id += urlAlphabet[(Math.random() * 64) | 0]
}
return id
}
module.exports = { nanoid, customAlphabet }
+33
View File
@@ -0,0 +1,33 @@
/**
* Generate URL-friendly unique ID. This method uses the non-secure
* predictable random generator with bigger collision probability.
*
* ```js
* import { nanoid } from 'nanoid/non-secure'
* model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
* ```
*
* @param size Size of the ID. The default size is 21.
* @returns A random string.
*/
export function nanoid(size?: number): string
/**
* Generate a unique ID based on a custom alphabet.
* This method uses the non-secure predictable random generator
* with bigger collision probability.
*
* @param alphabet Alphabet used to generate the ID.
* @param defaultSize Size of the ID. The default size is 21.
* @returns A random string generator.
*
* ```js
* import { customAlphabet } from 'nanoid/non-secure'
* const nanoid = customAlphabet('0123456789абвгдеё', 5)
* model.id = //=> "8ё56а"
* ```
*/
export function customAlphabet(
alphabet: string,
defaultSize?: number
): (size?: number) => string
+24
View File
@@ -0,0 +1,24 @@
let urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
let customAlphabet = (alphabet, defaultSize = 21) => {
return (size = defaultSize) => {
let id = ''
let i = size | 0
while (i-- > 0) {
id += alphabet[(Math.random() * alphabet.length) | 0]
}
return id
}
}
let nanoid = (size = 21) => {
let id = ''
let i = size | 0
while (i-- > 0) {
id += urlAlphabet[(Math.random() * 64) | 0]
}
return id
}
export { nanoid, customAlphabet }
+6
View File
@@ -0,0 +1,6 @@
{
"type": "module",
"main": "index.cjs",
"module": "index.js",
"react-native": "index.js"
}
+89
View File
@@ -0,0 +1,89 @@
{
"name": "nanoid",
"version": "3.3.19",
"description": "A tiny (116 bytes), secure URL-friendly unique string ID generator",
"keywords": [
"uuid",
"random",
"id",
"url"
],
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
},
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"author": "Andrey Sitnik <andrey@sitnik.ru>",
"license": "MIT",
"repository": "ai/nanoid",
"browser": {
"./index.js": "./index.browser.js",
"./async/index.js": "./async/index.browser.js",
"./async/index.cjs": "./async/index.browser.cjs",
"./index.cjs": "./index.browser.cjs"
},
"react-native": "index.js",
"bin": "./bin/nanoid.cjs",
"sideEffects": false,
"types": "./index.d.ts",
"type": "module",
"main": "index.cjs",
"module": "index.js",
"exports": {
".": {
"react-native": "./index.browser.js",
"browser": "./index.browser.js",
"require": {
"types": "./index.d.cts",
"default": "./index.cjs"
},
"import": {
"types": "./index.d.ts",
"default": "./index.js"
},
"default": "./index.js"
},
"./package.json": "./package.json",
"./async/package.json": "./async/package.json",
"./async": {
"browser": "./async/index.browser.js",
"require": {
"types": "./index.d.cts",
"default": "./async/index.cjs"
},
"import": {
"types": "./index.d.ts",
"default": "./async/index.js"
},
"default": "./async/index.js"
},
"./non-secure/package.json": "./non-secure/package.json",
"./non-secure": {
"require": {
"types": "./index.d.cts",
"default": "./non-secure/index.cjs"
},
"import": {
"types": "./index.d.ts",
"default": "./non-secure/index.js"
},
"default": "./non-secure/index.js"
},
"./url-alphabet/package.json": "./url-alphabet/package.json",
"./url-alphabet": {
"require": {
"types": "./index.d.cts",
"default": "./url-alphabet/index.cjs"
},
"import": {
"types": "./index.d.ts",
"default": "./url-alphabet/index.js"
},
"default": "./url-alphabet/index.js"
}
}
}
+4
View File
@@ -0,0 +1,4 @@
let urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
module.exports = { urlAlphabet }
+4
View File
@@ -0,0 +1,4 @@
let urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
export { urlAlphabet }
+6
View File
@@ -0,0 +1,6 @@
{
"type": "module",
"main": "index.cjs",
"module": "index.js",
"react-native": "index.js"
}
+15
View File
@@ -0,0 +1,15 @@
ISC License
Copyright (c) 2021-2024 Oleksii Raspopov, Kostiantyn Denysov, Anton Verinov
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+21
View File
@@ -0,0 +1,21 @@
# picocolors
The tiniest and the fastest library for terminal output formatting with ANSI colors.
```javascript
import pc from "picocolors"
console.log(
pc.green(`How are ${pc.italic(`you`)} doing?`)
)
```
- **No dependencies.**
- **14 times** smaller and **2 times** faster than chalk.
- Used by popular tools like PostCSS, SVGO, Stylelint, and Browserslist.
- Node.js v6+ & browsers support. Support for both CJS and ESM projects.
- TypeScript type declarations included.
- [`NO_COLOR`](https://no-color.org/) friendly.
## Docs
Read **[full docs](https://github.com/alexeyraspopov/picocolors#readme)** on GitHub.
Loaded 100 of 418 files, more files were not shown because too many files have changed in this diff. Show more