database reading
This commit is contained in:
1 parent
68c24dcec5
commit
fc8455e353
418 files changed
+674402
-1553
No files matched your search
-19
@@ -1,19 +0,0 @@
|
||||
# Зависимости
|
||||
node_modules
|
||||
|
||||
# Сборка
|
||||
dist
|
||||
dist-ssr
|
||||
|
||||
# Логи
|
||||
*.log
|
||||
|
||||
# Окружение
|
||||
.env
|
||||
.env.*
|
||||
|
||||
# Редактор / ОС
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
Vendored
+45
@@ -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≠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);
|
||||
Vendored
+1
@@ -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}
|
||||
Vendored
+41
@@ -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
@@ -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>
|
||||
+1
@@ -0,0 +1 @@
|
||||
../esbuild/bin/esbuild
|
||||
+1
@@ -0,0 +1 @@
|
||||
../nanoid/bin/nanoid.cjs
|
||||
+1
@@ -0,0 +1 @@
|
||||
../rollup/dist/bin/rollup
|
||||
+1
@@ -0,0 +1 @@
|
||||
../@sqlite.org/sqlite-wasm/bin/index.js
|
||||
+1
@@ -0,0 +1 @@
|
||||
../typescript/bin/tsc
|
||||
+1
@@ -0,0 +1 @@
|
||||
../typescript/bin/tsserver
|
||||
+1
@@ -0,0 +1 @@
|
||||
../vite/bin/vite.js
|
||||
+374
@@ -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
File diff suppressed because it is too large.
Load diff
+7
@@ -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
@@ -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
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
+3
@@ -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.
|
||||
BIN
Binary file not shown.
+20
@@ -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
@@ -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
@@ -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
@@ -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ⅇ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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1 @@
|
||||
export * from "./zstd.ts";
|
||||
+475
@@ -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
@@ -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
@@ -0,0 +1 @@
|
||||
export * from "./zstd.ts";
|
||||
+124
@@ -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
@@ -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
@@ -0,0 +1,3 @@
|
||||
# `@napi-rs/lzma-linux-x64-gnu`
|
||||
|
||||
This is the **x86_64-unknown-linux-gnu** binary for `@napi-rs/lzma`
|
||||
BIN
Binary file not shown.
+39
@@ -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
@@ -0,0 +1,3 @@
|
||||
# `@rollup/rollup-linux-x64-gnu`
|
||||
|
||||
This is the **x86_64-unknown-linux-gnu** binary for `rollup`
|
||||
+25
@@ -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"
|
||||
}
|
||||
BIN
Binary file not shown.
+243
@@ -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
@@ -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
File diff suppressed because it is too large.
Load diff
+7
@@ -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
@@ -0,0 +1,3 @@
|
||||
import { default as sqlite3InitModule } from './sqlite-wasm/jswasm/sqlite3-node.mjs';
|
||||
|
||||
export default sqlite3InitModule;
|
||||
+72
@@ -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"
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+14037
File diff suppressed because it is too large.
Load diff
+12043
File diff suppressed because it is too large.
Load diff
Generated
Vendored
+691
@@ -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();
|
||||
}
|
||||
Generated
Vendored
+35
@@ -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());
|
||||
Generated
Vendored
+193
@@ -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,
|
||||
});
|
||||
Generated
Vendored
+187
@@ -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;
|
||||
+46
@@ -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());
|
||||
+14070
File diff suppressed because it is too large.
Load diff
+14039
File diff suppressed because it is too large.
Load diff
BIN
Binary file not shown.
+21
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
BIN
Binary file not shown.
+300
@@ -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
@@ -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
File diff suppressed because it is too large.
Load diff
+74
@@ -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"
|
||||
}
|
||||
}
|
||||
+7
@@ -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
@@ -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 © 2024 Abdullah Atta under MIT. [Read full text here.](https://github.com/thecodrr/fdir/raw/master/LICENSE)
|
||||
+588
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"
|
||||
}
|
||||
}
|
||||
+55
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"type": "module",
|
||||
"main": "index.cjs",
|
||||
"module": "index.js",
|
||||
"react-native": "index.js"
|
||||
}
|
||||
+89
@@ -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
@@ -0,0 +1,4 @@
|
||||
let urlAlphabet =
|
||||
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
|
||||
|
||||
module.exports = { urlAlphabet }
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
let urlAlphabet =
|
||||
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
|
||||
|
||||
export { urlAlphabet }
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"type": "module",
|
||||
"main": "index.cjs",
|
||||
"module": "index.js",
|
||||
"react-native": "index.js"
|
||||
}
|
||||
+15
@@ -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
@@ -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
Reference in new issue
Block a user