@glash/cli 0.2.33 → 0.2.34
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/bin/glash.mjs +1 -0
- package/commands/deploy.mjs +44 -10
- package/package.json +1 -1
package/bin/glash.mjs
CHANGED
|
@@ -102,6 +102,7 @@ ${color.bold('FLAGS')}
|
|
|
102
102
|
--asset-threshold <size> Auto-offload threshold (default: 100mb)
|
|
103
103
|
--source-upload <mode> Source upload: auto, direct, chunked
|
|
104
104
|
--source-threshold <size> Auto-chunk source threshold (default: 90mb)
|
|
105
|
+
--source-concurrency <n> Parallel chunk uploads for large source bundles (default: 4)
|
|
105
106
|
--framework <name> Override framework detection (glashjs, next, vite, etc.)
|
|
106
107
|
--help, -h Show this help
|
|
107
108
|
--version, -v Show CLI version
|
package/commands/deploy.mjs
CHANGED
|
@@ -218,6 +218,7 @@ export async function deploy({ flags }) {
|
|
|
218
218
|
gitBranch: gitBranch || '',
|
|
219
219
|
target,
|
|
220
220
|
framework: projectProfile.framework,
|
|
221
|
+
flags,
|
|
221
222
|
};
|
|
222
223
|
|
|
223
224
|
if (shouldUseChunkedSourceUpload(zipStat.size, flags)) {
|
|
@@ -519,10 +520,19 @@ async function uploadSourceBundleStaged(projectId, zipPath, zipStat, meta, indic
|
|
|
519
520
|
|
|
520
521
|
const partSize = sourceUploadPartSize(prepared.partSize);
|
|
521
522
|
const blob = await openAsBlob(zipPath, { type: 'application/zip' });
|
|
523
|
+
const chunks = [];
|
|
524
|
+
for (let offset = 0, partNumber = 1; offset < sizeBytes; offset += partSize, partNumber += 1) {
|
|
525
|
+
chunks.push({
|
|
526
|
+
partNumber,
|
|
527
|
+
offset,
|
|
528
|
+
end: Math.min(offset + partSize, sizeBytes),
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
|
|
522
532
|
const parts = [];
|
|
523
|
-
let
|
|
524
|
-
|
|
525
|
-
|
|
533
|
+
let uploadedBytes = 0;
|
|
534
|
+
const concurrency = sourceUploadConcurrency(meta.flags);
|
|
535
|
+
await mapWithConcurrency(chunks, concurrency, async ({ partNumber, offset, end }) => {
|
|
526
536
|
const partUrl = withQueryParam(prepared.uploadPartUrl, 'partNumber', String(partNumber));
|
|
527
537
|
const res = await fetchWithRetries(partUrl, {
|
|
528
538
|
method: 'PUT',
|
|
@@ -540,10 +550,11 @@ async function uploadSourceBundleStaged(projectId, zipPath, zipStat, meta, indic
|
|
|
540
550
|
throw new Error(`Chunked source upload part ${partNumber} did not return a multipart ETag`);
|
|
541
551
|
}
|
|
542
552
|
parts.push({ partNumber: Number(part.partNumber), etag: String(part.etag) });
|
|
543
|
-
|
|
553
|
+
uploadedBytes += (end - offset);
|
|
554
|
+
const percent = 28 + Math.round((uploadedBytes / sizeBytes) * 14);
|
|
544
555
|
indicator?.setProgress?.(percent, 'uploading');
|
|
545
|
-
|
|
546
|
-
|
|
556
|
+
});
|
|
557
|
+
parts.sort((a, b) => a.partNumber - b.partNumber);
|
|
547
558
|
|
|
548
559
|
const completed = await fetchWithRetries(prepared.completeUrl, {
|
|
549
560
|
method: 'POST',
|
|
@@ -575,6 +586,19 @@ async function uploadSourceBundleStaged(projectId, zipPath, zipStat, meta, indic
|
|
|
575
586
|
return { deployment, partsUploaded: parts.length, sha256 };
|
|
576
587
|
}
|
|
577
588
|
|
|
589
|
+
async function mapWithConcurrency(items, concurrency, worker) {
|
|
590
|
+
const limit = Math.max(1, Math.min(Number(concurrency) || 1, items.length || 1));
|
|
591
|
+
let next = 0;
|
|
592
|
+
const runners = Array.from({ length: limit }, async () => {
|
|
593
|
+
while (next < items.length) {
|
|
594
|
+
const item = items[next];
|
|
595
|
+
next += 1;
|
|
596
|
+
await worker(item);
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
await Promise.all(runners);
|
|
600
|
+
}
|
|
601
|
+
|
|
578
602
|
function sourceUploadFailure(error) {
|
|
579
603
|
const message = error?.message || String(error);
|
|
580
604
|
if (error?.status === 404 && /source-upload|Cannot POST/i.test(message)) {
|
|
@@ -629,7 +653,7 @@ function uploadTimeoutMsFor(bytes) {
|
|
|
629
653
|
function publicAssetPartSize(value) {
|
|
630
654
|
const parsed = Number(value);
|
|
631
655
|
if (Number.isFinite(parsed) && parsed >= 5 * 1024 * 1024) return Math.round(parsed);
|
|
632
|
-
return
|
|
656
|
+
return 80 * 1024 * 1024;
|
|
633
657
|
}
|
|
634
658
|
|
|
635
659
|
function assetOffloadFailure(error, assetSummary) {
|
|
@@ -678,7 +702,14 @@ function sourceUploadThresholdBytes(flags) {
|
|
|
678
702
|
function sourceUploadPartSize(value) {
|
|
679
703
|
const parsed = Number(value);
|
|
680
704
|
if (Number.isFinite(parsed) && parsed >= 5 * 1024 * 1024) return Math.round(parsed);
|
|
681
|
-
return
|
|
705
|
+
return 80 * 1024 * 1024;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
function sourceUploadConcurrency(flags = {}) {
|
|
709
|
+
const raw = flags['source-concurrency'] ?? process.env.GLASH_SOURCE_UPLOAD_CONCURRENCY ?? '4';
|
|
710
|
+
const parsed = Number(raw);
|
|
711
|
+
if (!Number.isFinite(parsed) || parsed < 1) return 4;
|
|
712
|
+
return Math.max(1, Math.min(8, Math.floor(parsed)));
|
|
682
713
|
}
|
|
683
714
|
|
|
684
715
|
async function detectProjectProfile(cwd, flags = {}) {
|
|
@@ -686,9 +717,12 @@ async function detectProjectProfile(cwd, flags = {}) {
|
|
|
686
717
|
if (forced) return { framework: forced, label: forced };
|
|
687
718
|
const pkg = await readPackageJson(cwd);
|
|
688
719
|
const deps = { ...(pkg?.dependencies ?? {}), ...(pkg?.devDependencies ?? {}) };
|
|
720
|
+
const scripts = pkg?.scripts ?? {};
|
|
721
|
+
const hasNextConfig = await existsAny(cwd, ['next.config.js', 'next.config.mjs', 'next.config.cjs', 'next.config.ts']);
|
|
689
722
|
const hasGlashConfig = await existsAny(cwd, ['glash.config.mjs', 'glash.config.js', 'glash.config.cjs']);
|
|
690
|
-
|
|
691
|
-
if (deps.next) return { framework: 'next', label: 'Next.js' };
|
|
723
|
+
const scriptText = Object.values(scripts).join('\n');
|
|
724
|
+
if (deps.next || hasNextConfig || /\bnext\s+(build|dev|start)\b/i.test(scriptText)) return { framework: 'next', label: 'Next.js' };
|
|
725
|
+
if (deps.glashjs || hasGlashConfig || /\bglash\s+(build|serve|dev)\b/i.test(scriptText)) return { framework: 'glashjs', label: 'glashjs' };
|
|
692
726
|
if (deps.nuxt || deps.nuxt3) return { framework: 'nuxt', label: 'Nuxt' };
|
|
693
727
|
if (deps.vite) return { framework: 'vite', label: 'Vite' };
|
|
694
728
|
if (deps['@remix-run/dev'] || deps.remix) return { framework: 'remix', label: 'Remix' };
|
package/package.json
CHANGED