latticesql 3.4.2 → 3.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +85 -2
- package/dist/index.cjs +84 -1
- package/dist/index.js +84 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -54523,6 +54523,25 @@ var css = `
|
|
|
54523
54523
|
animation: feedSpin 0.7s linear infinite; vertical-align: middle;
|
|
54524
54524
|
}
|
|
54525
54525
|
@keyframes feedSpin { to { transform: rotate(360deg); } }
|
|
54526
|
+
/* Batch-upload progress bar \u2014 pinned to the top of the feed while a
|
|
54527
|
+
multi-file drop drains through the bounded-concurrency queue. */
|
|
54528
|
+
.ingest-progress {
|
|
54529
|
+
position: sticky; top: 0; z-index: 3;
|
|
54530
|
+
display: flex; flex-direction: column; gap: 6px;
|
|
54531
|
+
padding: 8px 10px; border-radius: 8px;
|
|
54532
|
+
background: var(--surface); border: 1px solid rgba(190, 242, 100, 0.22);
|
|
54533
|
+
box-shadow: var(--shadow-1), var(--glow-accent-soft);
|
|
54534
|
+
}
|
|
54535
|
+
.ingest-progress-label { font-size: 12px; font-weight: 500; color: var(--text); }
|
|
54536
|
+
.ingest-progress-track {
|
|
54537
|
+
height: 6px; border-radius: 999px; overflow: hidden; background: var(--border-strong);
|
|
54538
|
+
}
|
|
54539
|
+
.ingest-progress-fill {
|
|
54540
|
+
height: 100%; width: 0%; border-radius: 999px;
|
|
54541
|
+
background: linear-gradient(90deg, var(--accent-deep), var(--accent));
|
|
54542
|
+
box-shadow: 0 0 8px rgba(190, 242, 100, 0.5);
|
|
54543
|
+
transition: width 0.3s ease;
|
|
54544
|
+
}
|
|
54526
54545
|
.assistant-rail {
|
|
54527
54546
|
position: relative;
|
|
54528
54547
|
background:
|
|
@@ -61859,6 +61878,63 @@ var appJs = `
|
|
|
61859
61878
|
// Browsers can't expose the local path, so we POST the bytes; the
|
|
61860
61879
|
// server extracts + summarizes, then discards them (path stays null).
|
|
61861
61880
|
// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
61881
|
+
// Cap how many uploads are in flight at once. A browser allows only ~6
|
|
61882
|
+
// HTTP/1.1 connections per host, so a bulk drop of N files would fire N
|
|
61883
|
+
// upload POSTs in parallel and saturate that budget \u2014 every other data
|
|
61884
|
+
// request (entities, rows, navigation) then queues for minutes behind the
|
|
61885
|
+
// multi-minute ingests and the GUI looks frozen. Holding uploads to a few
|
|
61886
|
+
// at a time leaves connections free for the rest of the app (and eases the
|
|
61887
|
+
// AI rate limit each ingest hits server-side). The realtime/feed streams are
|
|
61888
|
+
// already off this budget \u2014 they share one WebSocket \u2014 so this is the last
|
|
61889
|
+
// place a big batch could starve the connection pool.
|
|
61890
|
+
var INGEST_MAX_CONCURRENCY = 3;
|
|
61891
|
+
// Run a batch of upload thunks with at most \`limit\` in flight, calling
|
|
61892
|
+
// onProgress(done, total) as each settles. One failure never stalls the
|
|
61893
|
+
// batch \u2014 uploadFile surfaces its own error and resolves.
|
|
61894
|
+
function runIngestBatch(thunks, limit, onProgress) {
|
|
61895
|
+
return new Promise(function (resolve) {
|
|
61896
|
+
var total = thunks.length, idx = 0, done = 0;
|
|
61897
|
+
function startNext() {
|
|
61898
|
+
if (idx >= total) return;
|
|
61899
|
+
var thunk = thunks[idx++];
|
|
61900
|
+
Promise.resolve().then(thunk).catch(function () { /* already surfaced */ }).then(function () {
|
|
61901
|
+
done++;
|
|
61902
|
+
if (onProgress) onProgress(done, total);
|
|
61903
|
+
if (done === total) resolve(); else startNext();
|
|
61904
|
+
});
|
|
61905
|
+
}
|
|
61906
|
+
for (var i = 0; i < Math.min(limit, total); i++) startNext();
|
|
61907
|
+
});
|
|
61908
|
+
}
|
|
61909
|
+
// A batch-upload progress bar pinned to the top of the rail feed
|
|
61910
|
+
// ("Analyzing N of M\u2026"). The per-file "Analyzing <name>\u2026" cards still
|
|
61911
|
+
// appear, but only INGEST_MAX_CONCURRENCY at a time; this gives the
|
|
61912
|
+
// whole-batch view that the individual cards can't. Returns
|
|
61913
|
+
// { update(done, total), done() }.
|
|
61914
|
+
function ingestProgress(total) {
|
|
61915
|
+
var feedEl = document.getElementById('rail-feed');
|
|
61916
|
+
if (!feedEl) return { update: function () {}, done: function () {} };
|
|
61917
|
+
railEmptyGone();
|
|
61918
|
+
var wrap = document.createElement('div');
|
|
61919
|
+
wrap.className = 'ingest-progress';
|
|
61920
|
+
wrap.innerHTML =
|
|
61921
|
+
'<div class="ingest-progress-label">Analyzing 0 of ' + total + '\u2026</div>' +
|
|
61922
|
+
'<div class="ingest-progress-track"><div class="ingest-progress-fill"></div></div>';
|
|
61923
|
+
feedEl.insertBefore(wrap, feedEl.firstChild);
|
|
61924
|
+
var label = wrap.querySelector('.ingest-progress-label');
|
|
61925
|
+
var fill = wrap.querySelector('.ingest-progress-fill');
|
|
61926
|
+
return {
|
|
61927
|
+
update: function (n, t) {
|
|
61928
|
+
if (label) label.textContent = 'Analyzing ' + n + ' of ' + t + '\u2026';
|
|
61929
|
+
if (fill) fill.style.width = Math.round((n / t) * 100) + '%';
|
|
61930
|
+
},
|
|
61931
|
+
done: function () {
|
|
61932
|
+
if (fill) fill.style.width = '100%';
|
|
61933
|
+
if (label) label.textContent = 'Analyzed ' + total + ' file' + (total === 1 ? '' : 's');
|
|
61934
|
+
setTimeout(function () { if (wrap.parentNode) wrap.parentNode.removeChild(wrap); }, 2500);
|
|
61935
|
+
},
|
|
61936
|
+
};
|
|
61937
|
+
}
|
|
61862
61938
|
// Append a transient "Analyzing <file>\u2026" row to the feed so the user sees
|
|
61863
61939
|
// the ingest is processing in the background; returns a disposer. The real
|
|
61864
61940
|
// create/link feed events stream in over SSE as the server materializes them.
|
|
@@ -61918,7 +61994,14 @@ var appJs = `
|
|
|
61918
61994
|
});
|
|
61919
61995
|
return;
|
|
61920
61996
|
}
|
|
61921
|
-
|
|
61997
|
+
// Multi-file: drain through the bounded-concurrency queue (so a big drop
|
|
61998
|
+
// can't saturate the connection budget) with a batch progress bar.
|
|
61999
|
+
var bar = ingestProgress(files.length);
|
|
62000
|
+
var thunks = [];
|
|
62001
|
+
for (var i = 0; i < files.length; i++) {
|
|
62002
|
+
(function (f) { thunks.push(function () { return uploadFile(f); }); })(files[i]);
|
|
62003
|
+
}
|
|
62004
|
+
runIngestBatch(thunks, INGEST_MAX_CONCURRENCY, bar.update).then(bar.done);
|
|
61922
62005
|
}
|
|
61923
62006
|
// Mobile: tapping the handle expands/collapses the bottom drawer.
|
|
61924
62007
|
function initRailDrawer() {
|
|
@@ -69424,7 +69507,7 @@ function printHelp() {
|
|
|
69424
69507
|
);
|
|
69425
69508
|
}
|
|
69426
69509
|
function getVersion() {
|
|
69427
|
-
if (true) return "3.4.
|
|
69510
|
+
if (true) return "3.4.3";
|
|
69428
69511
|
try {
|
|
69429
69512
|
const pkgPath = new URL("../package.json", import.meta.url).pathname;
|
|
69430
69513
|
const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
|
package/dist/index.cjs
CHANGED
|
@@ -56399,6 +56399,25 @@ var css = `
|
|
|
56399
56399
|
animation: feedSpin 0.7s linear infinite; vertical-align: middle;
|
|
56400
56400
|
}
|
|
56401
56401
|
@keyframes feedSpin { to { transform: rotate(360deg); } }
|
|
56402
|
+
/* Batch-upload progress bar \u2014 pinned to the top of the feed while a
|
|
56403
|
+
multi-file drop drains through the bounded-concurrency queue. */
|
|
56404
|
+
.ingest-progress {
|
|
56405
|
+
position: sticky; top: 0; z-index: 3;
|
|
56406
|
+
display: flex; flex-direction: column; gap: 6px;
|
|
56407
|
+
padding: 8px 10px; border-radius: 8px;
|
|
56408
|
+
background: var(--surface); border: 1px solid rgba(190, 242, 100, 0.22);
|
|
56409
|
+
box-shadow: var(--shadow-1), var(--glow-accent-soft);
|
|
56410
|
+
}
|
|
56411
|
+
.ingest-progress-label { font-size: 12px; font-weight: 500; color: var(--text); }
|
|
56412
|
+
.ingest-progress-track {
|
|
56413
|
+
height: 6px; border-radius: 999px; overflow: hidden; background: var(--border-strong);
|
|
56414
|
+
}
|
|
56415
|
+
.ingest-progress-fill {
|
|
56416
|
+
height: 100%; width: 0%; border-radius: 999px;
|
|
56417
|
+
background: linear-gradient(90deg, var(--accent-deep), var(--accent));
|
|
56418
|
+
box-shadow: 0 0 8px rgba(190, 242, 100, 0.5);
|
|
56419
|
+
transition: width 0.3s ease;
|
|
56420
|
+
}
|
|
56402
56421
|
.assistant-rail {
|
|
56403
56422
|
position: relative;
|
|
56404
56423
|
background:
|
|
@@ -63735,6 +63754,63 @@ var appJs = `
|
|
|
63735
63754
|
// Browsers can't expose the local path, so we POST the bytes; the
|
|
63736
63755
|
// server extracts + summarizes, then discards them (path stays null).
|
|
63737
63756
|
// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
63757
|
+
// Cap how many uploads are in flight at once. A browser allows only ~6
|
|
63758
|
+
// HTTP/1.1 connections per host, so a bulk drop of N files would fire N
|
|
63759
|
+
// upload POSTs in parallel and saturate that budget \u2014 every other data
|
|
63760
|
+
// request (entities, rows, navigation) then queues for minutes behind the
|
|
63761
|
+
// multi-minute ingests and the GUI looks frozen. Holding uploads to a few
|
|
63762
|
+
// at a time leaves connections free for the rest of the app (and eases the
|
|
63763
|
+
// AI rate limit each ingest hits server-side). The realtime/feed streams are
|
|
63764
|
+
// already off this budget \u2014 they share one WebSocket \u2014 so this is the last
|
|
63765
|
+
// place a big batch could starve the connection pool.
|
|
63766
|
+
var INGEST_MAX_CONCURRENCY = 3;
|
|
63767
|
+
// Run a batch of upload thunks with at most \`limit\` in flight, calling
|
|
63768
|
+
// onProgress(done, total) as each settles. One failure never stalls the
|
|
63769
|
+
// batch \u2014 uploadFile surfaces its own error and resolves.
|
|
63770
|
+
function runIngestBatch(thunks, limit, onProgress) {
|
|
63771
|
+
return new Promise(function (resolve) {
|
|
63772
|
+
var total = thunks.length, idx = 0, done = 0;
|
|
63773
|
+
function startNext() {
|
|
63774
|
+
if (idx >= total) return;
|
|
63775
|
+
var thunk = thunks[idx++];
|
|
63776
|
+
Promise.resolve().then(thunk).catch(function () { /* already surfaced */ }).then(function () {
|
|
63777
|
+
done++;
|
|
63778
|
+
if (onProgress) onProgress(done, total);
|
|
63779
|
+
if (done === total) resolve(); else startNext();
|
|
63780
|
+
});
|
|
63781
|
+
}
|
|
63782
|
+
for (var i = 0; i < Math.min(limit, total); i++) startNext();
|
|
63783
|
+
});
|
|
63784
|
+
}
|
|
63785
|
+
// A batch-upload progress bar pinned to the top of the rail feed
|
|
63786
|
+
// ("Analyzing N of M\u2026"). The per-file "Analyzing <name>\u2026" cards still
|
|
63787
|
+
// appear, but only INGEST_MAX_CONCURRENCY at a time; this gives the
|
|
63788
|
+
// whole-batch view that the individual cards can't. Returns
|
|
63789
|
+
// { update(done, total), done() }.
|
|
63790
|
+
function ingestProgress(total) {
|
|
63791
|
+
var feedEl = document.getElementById('rail-feed');
|
|
63792
|
+
if (!feedEl) return { update: function () {}, done: function () {} };
|
|
63793
|
+
railEmptyGone();
|
|
63794
|
+
var wrap = document.createElement('div');
|
|
63795
|
+
wrap.className = 'ingest-progress';
|
|
63796
|
+
wrap.innerHTML =
|
|
63797
|
+
'<div class="ingest-progress-label">Analyzing 0 of ' + total + '\u2026</div>' +
|
|
63798
|
+
'<div class="ingest-progress-track"><div class="ingest-progress-fill"></div></div>';
|
|
63799
|
+
feedEl.insertBefore(wrap, feedEl.firstChild);
|
|
63800
|
+
var label = wrap.querySelector('.ingest-progress-label');
|
|
63801
|
+
var fill = wrap.querySelector('.ingest-progress-fill');
|
|
63802
|
+
return {
|
|
63803
|
+
update: function (n, t) {
|
|
63804
|
+
if (label) label.textContent = 'Analyzing ' + n + ' of ' + t + '\u2026';
|
|
63805
|
+
if (fill) fill.style.width = Math.round((n / t) * 100) + '%';
|
|
63806
|
+
},
|
|
63807
|
+
done: function () {
|
|
63808
|
+
if (fill) fill.style.width = '100%';
|
|
63809
|
+
if (label) label.textContent = 'Analyzed ' + total + ' file' + (total === 1 ? '' : 's');
|
|
63810
|
+
setTimeout(function () { if (wrap.parentNode) wrap.parentNode.removeChild(wrap); }, 2500);
|
|
63811
|
+
},
|
|
63812
|
+
};
|
|
63813
|
+
}
|
|
63738
63814
|
// Append a transient "Analyzing <file>\u2026" row to the feed so the user sees
|
|
63739
63815
|
// the ingest is processing in the background; returns a disposer. The real
|
|
63740
63816
|
// create/link feed events stream in over SSE as the server materializes them.
|
|
@@ -63794,7 +63870,14 @@ var appJs = `
|
|
|
63794
63870
|
});
|
|
63795
63871
|
return;
|
|
63796
63872
|
}
|
|
63797
|
-
|
|
63873
|
+
// Multi-file: drain through the bounded-concurrency queue (so a big drop
|
|
63874
|
+
// can't saturate the connection budget) with a batch progress bar.
|
|
63875
|
+
var bar = ingestProgress(files.length);
|
|
63876
|
+
var thunks = [];
|
|
63877
|
+
for (var i = 0; i < files.length; i++) {
|
|
63878
|
+
(function (f) { thunks.push(function () { return uploadFile(f); }); })(files[i]);
|
|
63879
|
+
}
|
|
63880
|
+
runIngestBatch(thunks, INGEST_MAX_CONCURRENCY, bar.update).then(bar.done);
|
|
63798
63881
|
}
|
|
63799
63882
|
// Mobile: tapping the handle expands/collapses the bottom drawer.
|
|
63800
63883
|
function initRailDrawer() {
|
package/dist/index.js
CHANGED
|
@@ -56224,6 +56224,25 @@ var css = `
|
|
|
56224
56224
|
animation: feedSpin 0.7s linear infinite; vertical-align: middle;
|
|
56225
56225
|
}
|
|
56226
56226
|
@keyframes feedSpin { to { transform: rotate(360deg); } }
|
|
56227
|
+
/* Batch-upload progress bar \u2014 pinned to the top of the feed while a
|
|
56228
|
+
multi-file drop drains through the bounded-concurrency queue. */
|
|
56229
|
+
.ingest-progress {
|
|
56230
|
+
position: sticky; top: 0; z-index: 3;
|
|
56231
|
+
display: flex; flex-direction: column; gap: 6px;
|
|
56232
|
+
padding: 8px 10px; border-radius: 8px;
|
|
56233
|
+
background: var(--surface); border: 1px solid rgba(190, 242, 100, 0.22);
|
|
56234
|
+
box-shadow: var(--shadow-1), var(--glow-accent-soft);
|
|
56235
|
+
}
|
|
56236
|
+
.ingest-progress-label { font-size: 12px; font-weight: 500; color: var(--text); }
|
|
56237
|
+
.ingest-progress-track {
|
|
56238
|
+
height: 6px; border-radius: 999px; overflow: hidden; background: var(--border-strong);
|
|
56239
|
+
}
|
|
56240
|
+
.ingest-progress-fill {
|
|
56241
|
+
height: 100%; width: 0%; border-radius: 999px;
|
|
56242
|
+
background: linear-gradient(90deg, var(--accent-deep), var(--accent));
|
|
56243
|
+
box-shadow: 0 0 8px rgba(190, 242, 100, 0.5);
|
|
56244
|
+
transition: width 0.3s ease;
|
|
56245
|
+
}
|
|
56227
56246
|
.assistant-rail {
|
|
56228
56247
|
position: relative;
|
|
56229
56248
|
background:
|
|
@@ -63560,6 +63579,63 @@ var appJs = `
|
|
|
63560
63579
|
// Browsers can't expose the local path, so we POST the bytes; the
|
|
63561
63580
|
// server extracts + summarizes, then discards them (path stays null).
|
|
63562
63581
|
// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
63582
|
+
// Cap how many uploads are in flight at once. A browser allows only ~6
|
|
63583
|
+
// HTTP/1.1 connections per host, so a bulk drop of N files would fire N
|
|
63584
|
+
// upload POSTs in parallel and saturate that budget \u2014 every other data
|
|
63585
|
+
// request (entities, rows, navigation) then queues for minutes behind the
|
|
63586
|
+
// multi-minute ingests and the GUI looks frozen. Holding uploads to a few
|
|
63587
|
+
// at a time leaves connections free for the rest of the app (and eases the
|
|
63588
|
+
// AI rate limit each ingest hits server-side). The realtime/feed streams are
|
|
63589
|
+
// already off this budget \u2014 they share one WebSocket \u2014 so this is the last
|
|
63590
|
+
// place a big batch could starve the connection pool.
|
|
63591
|
+
var INGEST_MAX_CONCURRENCY = 3;
|
|
63592
|
+
// Run a batch of upload thunks with at most \`limit\` in flight, calling
|
|
63593
|
+
// onProgress(done, total) as each settles. One failure never stalls the
|
|
63594
|
+
// batch \u2014 uploadFile surfaces its own error and resolves.
|
|
63595
|
+
function runIngestBatch(thunks, limit, onProgress) {
|
|
63596
|
+
return new Promise(function (resolve) {
|
|
63597
|
+
var total = thunks.length, idx = 0, done = 0;
|
|
63598
|
+
function startNext() {
|
|
63599
|
+
if (idx >= total) return;
|
|
63600
|
+
var thunk = thunks[idx++];
|
|
63601
|
+
Promise.resolve().then(thunk).catch(function () { /* already surfaced */ }).then(function () {
|
|
63602
|
+
done++;
|
|
63603
|
+
if (onProgress) onProgress(done, total);
|
|
63604
|
+
if (done === total) resolve(); else startNext();
|
|
63605
|
+
});
|
|
63606
|
+
}
|
|
63607
|
+
for (var i = 0; i < Math.min(limit, total); i++) startNext();
|
|
63608
|
+
});
|
|
63609
|
+
}
|
|
63610
|
+
// A batch-upload progress bar pinned to the top of the rail feed
|
|
63611
|
+
// ("Analyzing N of M\u2026"). The per-file "Analyzing <name>\u2026" cards still
|
|
63612
|
+
// appear, but only INGEST_MAX_CONCURRENCY at a time; this gives the
|
|
63613
|
+
// whole-batch view that the individual cards can't. Returns
|
|
63614
|
+
// { update(done, total), done() }.
|
|
63615
|
+
function ingestProgress(total) {
|
|
63616
|
+
var feedEl = document.getElementById('rail-feed');
|
|
63617
|
+
if (!feedEl) return { update: function () {}, done: function () {} };
|
|
63618
|
+
railEmptyGone();
|
|
63619
|
+
var wrap = document.createElement('div');
|
|
63620
|
+
wrap.className = 'ingest-progress';
|
|
63621
|
+
wrap.innerHTML =
|
|
63622
|
+
'<div class="ingest-progress-label">Analyzing 0 of ' + total + '\u2026</div>' +
|
|
63623
|
+
'<div class="ingest-progress-track"><div class="ingest-progress-fill"></div></div>';
|
|
63624
|
+
feedEl.insertBefore(wrap, feedEl.firstChild);
|
|
63625
|
+
var label = wrap.querySelector('.ingest-progress-label');
|
|
63626
|
+
var fill = wrap.querySelector('.ingest-progress-fill');
|
|
63627
|
+
return {
|
|
63628
|
+
update: function (n, t) {
|
|
63629
|
+
if (label) label.textContent = 'Analyzing ' + n + ' of ' + t + '\u2026';
|
|
63630
|
+
if (fill) fill.style.width = Math.round((n / t) * 100) + '%';
|
|
63631
|
+
},
|
|
63632
|
+
done: function () {
|
|
63633
|
+
if (fill) fill.style.width = '100%';
|
|
63634
|
+
if (label) label.textContent = 'Analyzed ' + total + ' file' + (total === 1 ? '' : 's');
|
|
63635
|
+
setTimeout(function () { if (wrap.parentNode) wrap.parentNode.removeChild(wrap); }, 2500);
|
|
63636
|
+
},
|
|
63637
|
+
};
|
|
63638
|
+
}
|
|
63563
63639
|
// Append a transient "Analyzing <file>\u2026" row to the feed so the user sees
|
|
63564
63640
|
// the ingest is processing in the background; returns a disposer. The real
|
|
63565
63641
|
// create/link feed events stream in over SSE as the server materializes them.
|
|
@@ -63619,7 +63695,14 @@ var appJs = `
|
|
|
63619
63695
|
});
|
|
63620
63696
|
return;
|
|
63621
63697
|
}
|
|
63622
|
-
|
|
63698
|
+
// Multi-file: drain through the bounded-concurrency queue (so a big drop
|
|
63699
|
+
// can't saturate the connection budget) with a batch progress bar.
|
|
63700
|
+
var bar = ingestProgress(files.length);
|
|
63701
|
+
var thunks = [];
|
|
63702
|
+
for (var i = 0; i < files.length; i++) {
|
|
63703
|
+
(function (f) { thunks.push(function () { return uploadFile(f); }); })(files[i]);
|
|
63704
|
+
}
|
|
63705
|
+
runIngestBatch(thunks, INGEST_MAX_CONCURRENCY, bar.update).then(bar.done);
|
|
63623
63706
|
}
|
|
63624
63707
|
// Mobile: tapping the handle expands/collapses the bottom drawer.
|
|
63625
63708
|
function initRailDrawer() {
|
package/package.json
CHANGED