@ivotoby/postgram-cli 1.6.0 → 1.8.0

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/client.js CHANGED
@@ -134,6 +134,24 @@ export function createPgmClient(options) {
134
134
  body: input
135
135
  });
136
136
  },
137
+ diffSync(input) {
138
+ return request(options, '/api/sync/diff', {
139
+ method: 'POST',
140
+ body: input
141
+ });
142
+ },
143
+ uploadSyncFiles(input) {
144
+ return request(options, '/api/sync/upload', {
145
+ method: 'POST',
146
+ body: input
147
+ });
148
+ },
149
+ finalizeSync(input) {
150
+ return request(options, '/api/sync/finalize', {
151
+ method: 'POST',
152
+ body: input
153
+ });
154
+ },
137
155
  getSyncStatus(repo) {
138
156
  return request(options, `/api/sync/status/${encodeURIComponent(repo)}`);
139
157
  },
package/dist/pgm.js CHANGED
@@ -540,7 +540,7 @@ program
540
540
  try {
541
541
  const resolvedDir = path.resolve(dir);
542
542
  const repoName = options.repo ?? path.basename(resolvedDir);
543
- const files = [];
543
+ const manifest = [];
544
544
  const SKIP_DIRS = new Set(['.git', 'node_modules', '.obsidian', '.trash']);
545
545
  async function walk(dirPath, prefix) {
546
546
  const entries = await readdir(dirPath, { withFileTypes: true });
@@ -557,43 +557,23 @@ program
557
557
  const relativePath = prefix
558
558
  ? `${prefix}/${entry.name}`
559
559
  : entry.name;
560
- files.push({ path: relativePath, sha, content });
560
+ manifest.push({ path: relativePath, sha, fullPath });
561
561
  }
562
562
  }
563
563
  }
564
564
  await walk(resolvedDir, '');
565
565
  const config = await resolvePgmConfig();
566
566
  const client = createPgmClient(config);
567
+ const manifestForServer = manifest.map(({ path: p, sha }) => ({ path: p, sha }));
568
+ const diff = await client.diffSync({ repo: repoName, files: manifestForServer });
567
569
  if (options.dryRun) {
568
- const status = await client.getSyncStatus(repoName);
569
- const existingByPath = new Map(status.files.map((f) => [f.path, f]));
570
- const incomingPaths = new Set(files.map((f) => f.path));
571
- let newCount = 0;
572
- let changedCount = 0;
573
- let unchangedCount = 0;
574
- for (const file of files) {
575
- const existing = existingByPath.get(file.path);
576
- if (!existing) {
577
- newCount += 1;
578
- }
579
- else if (existing.sha !== file.sha) {
580
- changedCount += 1;
581
- }
582
- else {
583
- unchangedCount += 1;
584
- }
585
- }
586
- let deletedCount = 0;
587
- for (const [existingPath, entry] of existingByPath) {
588
- if (!incomingPaths.has(existingPath) && entry.syncStatus !== 'stale') {
589
- deletedCount += 1;
590
- }
591
- }
570
+ const newCount = diff.toUpload.filter((f) => f.reason === 'new').length;
571
+ const changedCount = diff.toUpload.filter((f) => f.reason === 'changed').length;
592
572
  const result = {
593
573
  created: newCount,
594
574
  updated: changedCount,
595
- unchanged: unchangedCount,
596
- deleted: deletedCount
575
+ unchanged: diff.unchanged,
576
+ deleted: diff.toDelete.length
597
577
  };
598
578
  if (json) {
599
579
  printJson(result);
@@ -605,7 +585,49 @@ program
605
585
  }
606
586
  return;
607
587
  }
608
- const result = await client.syncRepo({ repo: repoName, files });
588
+ const pathToFile = new Map(manifest.map((f) => [f.path, f]));
589
+ const BATCH_BYTES = 4 * 1024 * 1024;
590
+ const BATCH_FILES = 50;
591
+ let totalCreated = 0;
592
+ let totalUpdated = 0;
593
+ let batch = [];
594
+ let batchBytes = 0;
595
+ async function flushBatch() {
596
+ if (batch.length === 0)
597
+ return;
598
+ const result = await client.uploadSyncFiles({
599
+ repo: repoName,
600
+ files: batch
601
+ });
602
+ totalCreated += result.created;
603
+ totalUpdated += result.updated;
604
+ batch = [];
605
+ batchBytes = 0;
606
+ }
607
+ for (const toUpload of diff.toUpload) {
608
+ const entry = pathToFile.get(toUpload.path);
609
+ if (!entry) {
610
+ throw new AppError(ErrorCode.INTERNAL, `Server asked to upload ${toUpload.path} but it was not in the local manifest`);
611
+ }
612
+ const content = await fsReadFile(entry.fullPath, 'utf8');
613
+ const size = Buffer.byteLength(content, 'utf8');
614
+ if (batch.length > 0 && (batch.length >= BATCH_FILES || batchBytes + size > BATCH_BYTES)) {
615
+ await flushBatch();
616
+ }
617
+ batch.push({ path: toUpload.path, sha: toUpload.sha, content });
618
+ batchBytes += size;
619
+ }
620
+ await flushBatch();
621
+ const finalize = await client.finalizeSync({
622
+ repo: repoName,
623
+ files: manifestForServer
624
+ });
625
+ const result = {
626
+ created: totalCreated,
627
+ updated: totalUpdated,
628
+ unchanged: diff.unchanged,
629
+ deleted: finalize.deleted
630
+ };
609
631
  if (json) {
610
632
  printJson(result);
611
633
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ivotoby/postgram-cli",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "description": "Postgram CLI — store, search, and manage entities from the command line",
5
5
  "type": "module",
6
6
  "bin": {