gipity 1.0.379 → 1.0.380
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/progress.js +18 -1
- package/dist/sync.js +23 -4
- package/dist/template-vars.js +4 -1
- package/package.json +1 -1
package/dist/progress.js
CHANGED
|
@@ -19,11 +19,26 @@ class TerminalProgress {
|
|
|
19
19
|
/** True while an in-place transfer line is on screen and not yet committed. */
|
|
20
20
|
liveOpen = false;
|
|
21
21
|
lastRenderAt = 0;
|
|
22
|
+
/** The label of the current transfer session; a change starts a fresh one. */
|
|
23
|
+
barLabel = null;
|
|
24
|
+
/** True once the current session hit 100% - late/overshoot ticks are dropped. */
|
|
25
|
+
barSettled = false;
|
|
22
26
|
phase(message) {
|
|
23
27
|
this.commitLive();
|
|
24
28
|
process.stdout.write(` ${muted(message)}\n`);
|
|
25
29
|
}
|
|
26
30
|
transfer(label, doneBytes, totalBytes) {
|
|
31
|
+
// A new label begins a fresh transfer session (e.g. downloads → uploads on
|
|
32
|
+
// the same reporter). Within a session, once we've drawn the 100% frame we
|
|
33
|
+
// drop any further ticks - download byte totals are estimated, so the wire
|
|
34
|
+
// can deliver a hair more or fewer bytes than expected and we don't want a
|
|
35
|
+
// late chunk reopening a second "100%" line.
|
|
36
|
+
if (label !== this.barLabel) {
|
|
37
|
+
this.barLabel = label;
|
|
38
|
+
this.barSettled = false;
|
|
39
|
+
}
|
|
40
|
+
if (this.barSettled)
|
|
41
|
+
return;
|
|
27
42
|
const finished = totalBytes > 0 && doneBytes >= totalBytes;
|
|
28
43
|
// Throttle mid-flight redraws; always paint the first and final frames.
|
|
29
44
|
const now = Date.now();
|
|
@@ -32,8 +47,10 @@ class TerminalProgress {
|
|
|
32
47
|
this.lastRenderAt = now;
|
|
33
48
|
this.liveOpen = true;
|
|
34
49
|
process.stdout.write('\r' + this.frame(label, doneBytes, totalBytes) + CLEAR_TO_EOL);
|
|
35
|
-
if (finished)
|
|
50
|
+
if (finished) {
|
|
36
51
|
this.commitLive();
|
|
52
|
+
this.barSettled = true;
|
|
53
|
+
}
|
|
37
54
|
}
|
|
38
55
|
finish() {
|
|
39
56
|
this.commitLive();
|
package/dist/sync.js
CHANGED
|
@@ -195,14 +195,14 @@ async function fetchRemote(projectGuid) {
|
|
|
195
195
|
}
|
|
196
196
|
return out;
|
|
197
197
|
}
|
|
198
|
-
async function downloadAll(projectGuid) {
|
|
198
|
+
async function downloadAll(projectGuid, onBytes) {
|
|
199
199
|
const stream = await downloadStream(`/projects/${projectGuid}/files/tree?content=tar`);
|
|
200
200
|
const extract = tar.extract();
|
|
201
201
|
const files = new Map();
|
|
202
202
|
return new Promise((resolve, reject) => {
|
|
203
203
|
extract.on('entry', (header, entryStream, next) => {
|
|
204
204
|
const chunks = [];
|
|
205
|
-
entryStream.on('data', (c) => chunks.push(c));
|
|
205
|
+
entryStream.on('data', (c) => { chunks.push(c); onBytes?.(c.length); });
|
|
206
206
|
entryStream.on('end', () => { files.set(header.name, Buffer.concat(chunks)); next(); });
|
|
207
207
|
entryStream.resume();
|
|
208
208
|
});
|
|
@@ -519,9 +519,23 @@ async function syncInner(projectGuid, root, ignore, opts, interactive) {
|
|
|
519
519
|
const downloadedBytes = new Map();
|
|
520
520
|
const needsBulkDownload = plannedToApply.some(a => a.kind === 'download' || a.kind === 'conflict');
|
|
521
521
|
if (needsBulkDownload) {
|
|
522
|
-
|
|
522
|
+
// The tree endpoint streams the *whole* remote tree as one tar (the caller
|
|
523
|
+
// then picks out only the paths it planned to apply), so the bytes that
|
|
524
|
+
// actually move = the sum of every remote file's size. That's the honest
|
|
525
|
+
// denominator for the bar - it tracks real wire progress, not just the
|
|
526
|
+
// handful of changed files.
|
|
527
|
+
const downloadLabel = 'Downloading updates from Gipity';
|
|
528
|
+
const totalDownloadBytes = [...remote.values()].reduce((sum, r) => sum + r.size, 0);
|
|
529
|
+
let recvBytes = 0;
|
|
530
|
+
p?.transfer(downloadLabel, 0, totalDownloadBytes);
|
|
531
|
+
const onBytes = p
|
|
532
|
+
? (delta) => {
|
|
533
|
+
recvBytes = Math.min(recvBytes + delta, totalDownloadBytes);
|
|
534
|
+
p.transfer(downloadLabel, recvBytes, totalDownloadBytes);
|
|
535
|
+
}
|
|
536
|
+
: undefined;
|
|
523
537
|
try {
|
|
524
|
-
const all = await downloadAll(config.projectGuid);
|
|
538
|
+
const all = await downloadAll(config.projectGuid, onBytes);
|
|
525
539
|
for (const a of plannedToApply) {
|
|
526
540
|
if (a.kind === 'download' || a.kind === 'conflict') {
|
|
527
541
|
const buf = all.get(a.path);
|
|
@@ -533,6 +547,11 @@ async function syncInner(projectGuid, root, ignore, opts, interactive) {
|
|
|
533
547
|
catch (err) {
|
|
534
548
|
errors.push(`Download batch failed: ${err.message}`);
|
|
535
549
|
}
|
|
550
|
+
finally {
|
|
551
|
+
// Settle the bar even if the extracted-byte tally fell short of the
|
|
552
|
+
// estimate (the live line stays open until something hits 100% or finish()).
|
|
553
|
+
p?.finish();
|
|
554
|
+
}
|
|
536
555
|
}
|
|
537
556
|
// ── Writes pass: uploads, downloads, conflicts (rename + download + upload copy) ──
|
|
538
557
|
// We serialize conflicts; uploads run with bounded concurrency.
|
package/dist/template-vars.js
CHANGED
|
@@ -68,7 +68,10 @@ export function buildTemplateVars(v) {
|
|
|
68
68
|
'{{DESCRIPTION_META}}': v.description ? `\n <meta name="description" content="${safeDesc}">` : '',
|
|
69
69
|
'{{OG_DESCRIPTION}}': v.description ? `\n <meta property="og:description" content="${safeDesc}">` : '',
|
|
70
70
|
'{{JSON_LD_BLOCK}}': `<script type="application/ld+json">\n${jsonLd}\n </script>`,
|
|
71
|
-
|
|
71
|
+
// `crossorigin="anonymous"` so SDK errors surface with a real message/stack
|
|
72
|
+
// (CORS mode) instead of a sanitized message-less "Script error". The CDN
|
|
73
|
+
// returns Access-Control-Allow-Origin:*, so it works on any app domain.
|
|
74
|
+
'{{ANALYTICS_SCRIPT}}': `<script defer crossorigin="anonymous" src="https://media.gipity.ai/client/v1/gipity.js" data-app="${v.projectGuid}"></script>`,
|
|
72
75
|
};
|
|
73
76
|
}
|
|
74
77
|
/** Pure string substitution — exported so the test can exercise it without
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gipity",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.380",
|
|
4
4
|
"description": "The full-stack platform tuned for AI agents. Database, storage, auth, functions, deploy, and drop-in kits - all agent-tuned. Pair with Claude Code or use standalone.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"gipity": "dist/updater/shim.js",
|