gtx-cli 2.5.18 → 2.5.20

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # gtx-cli
2
2
 
3
+ ## 2.5.20
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`997a5df`](https://github.com/generaltranslation/gt/commit/997a5df6ac355b49a77e768935f9017af689de21)]:
8
+ - generaltranslation@8.0.6
9
+
10
+ ## 2.5.19
11
+
12
+ ### Patch Changes
13
+
14
+ - [#853](https://github.com/generaltranslation/gt/pull/853) [`02abd0a`](https://github.com/generaltranslation/gt/commit/02abd0a970a09c514744982f06169f385dfdd972) Thanks [@fernando-aviles](https://github.com/fernando-aviles)! - Including hash of post-processed files in `gt-lock.json` to avoid unnecessary saves when calling `save-local`
15
+
3
16
  ## 2.5.18
4
17
 
5
18
  ### Patch Changes
@@ -6,6 +6,7 @@ import { getGitUnifiedDiff } from '../utils/gitDiff.js';
6
6
  import { gt } from '../utils/gt.js';
7
7
  import os from 'node:os';
8
8
  import { randomUUID } from 'node:crypto';
9
+ import { hashStringSync } from '../utils/hash.js';
9
10
  /**
10
11
  * Collects local user edits by diffing the latest downloaded server translation version
11
12
  * against the current local translation file, and submits the diffs upstream.
@@ -32,6 +33,19 @@ export async function collectAndSendUserEditDiffs(files, settings) {
32
33
  const downloadedVersion = downloadedVersions.entries?.[uploadedFile.branchId]?.[uploadedFile.fileId]?.[uploadedFile.versionId]?.[locale];
33
34
  if (!downloadedVersion)
34
35
  continue;
36
+ // Skip if local file matches the last postprocessed content hash
37
+ if (downloadedVersion.postProcessHash) {
38
+ try {
39
+ const localContent = await fs.promises.readFile(outputPath, 'utf8');
40
+ const localHash = hashStringSync(localContent);
41
+ if (localHash === downloadedVersion.postProcessHash) {
42
+ continue;
43
+ }
44
+ }
45
+ catch {
46
+ // If hash check fails, fall through to diff
47
+ }
48
+ }
35
49
  candidates.push({
36
50
  branchId: uploadedFile.branchId,
37
51
  fileName: uploadedFile.fileName,
@@ -115,8 +115,14 @@ export async function downloadFileBatch(fileTracker, files, options, forceDownlo
115
115
  }
116
116
  // Write the file to disk
117
117
  await fs.promises.writeFile(outputPath, data);
118
- // Track as downloaded
119
- recordDownloaded(outputPath);
118
+ // Track as downloaded with metadata for downstream postprocessing
119
+ recordDownloaded(outputPath, {
120
+ branchId,
121
+ fileId,
122
+ versionId,
123
+ locale,
124
+ inputPath,
125
+ });
120
126
  result.successful.push(requestedFile);
121
127
  if (branchId && fileId && versionId && locale) {
122
128
  ensureNestedObject(downloadedVersions.entries, [
@@ -9,6 +9,8 @@ import processOpenApi from '../../utils/processOpenApi.js';
9
9
  import { noFilesError, noVersionIdError } from '../../console/index.js';
10
10
  import localizeStaticImports from '../../utils/localizeStaticImports.js';
11
11
  import { logErrorAndExit } from '../../console/logging.js';
12
+ import { getDownloadedMeta } from '../../state/recentDownloads.js';
13
+ import { persistPostProcessHashes } from '../../utils/persistPostprocessHashes.js';
12
14
  // Downloads translations that were completed
13
15
  export async function handleTranslate(options, settings, fileVersionData, jobData, branchData) {
14
16
  if (fileVersionData) {
@@ -65,4 +67,6 @@ export async function postProcessTranslations(settings, includeFiles) {
65
67
  if (settings.options?.copyFiles) {
66
68
  await copyFile(settings);
67
69
  }
70
+ // Record postprocessed content hashes for newly downloaded files
71
+ persistPostProcessHashes(settings, includeFiles, getDownloadedMeta());
68
72
  }
@@ -1,6 +1,7 @@
1
1
  export type DownloadedVersionEntry = {
2
2
  fileName?: string;
3
3
  updatedAt?: string;
4
+ postProcessHash?: string;
4
5
  };
5
6
  export type DownloadedVersions = {
6
7
  version: number;
@@ -1,3 +1,12 @@
1
- export declare function recordDownloaded(filePath: string): void;
1
+ type DownloadMeta = {
2
+ branchId: string;
3
+ fileId: string;
4
+ versionId: string;
5
+ locale: string;
6
+ inputPath?: string;
7
+ };
8
+ export declare function recordDownloaded(filePath: string, meta?: DownloadMeta): void;
2
9
  export declare function getDownloaded(): Set<string>;
10
+ export declare function getDownloadedMeta(): Map<string, DownloadMeta>;
3
11
  export declare function clearDownloaded(): void;
12
+ export {};
@@ -1,10 +1,18 @@
1
1
  const recent = new Set();
2
- export function recordDownloaded(filePath) {
2
+ const recentMeta = new Map();
3
+ export function recordDownloaded(filePath, meta) {
3
4
  recent.add(filePath);
5
+ if (meta) {
6
+ recentMeta.set(filePath, meta);
7
+ }
4
8
  }
5
9
  export function getDownloaded() {
6
10
  return recent;
7
11
  }
12
+ export function getDownloadedMeta() {
13
+ return recentMeta;
14
+ }
8
15
  export function clearDownloaded() {
9
16
  recent.clear();
17
+ recentMeta.clear();
10
18
  }
@@ -0,0 +1,12 @@
1
+ import type { Settings } from '../types/index.js';
2
+ type DownloadMeta = {
3
+ branchId: string;
4
+ fileId: string;
5
+ versionId: string;
6
+ locale: string;
7
+ };
8
+ /**
9
+ * Persist postprocessed content hashes for recently downloaded files into gt-lock.json.
10
+ */
11
+ export declare function persistPostProcessHashes(settings: Settings, includeFiles: Set<string> | undefined, downloadedMeta: Map<string, DownloadMeta>): void;
12
+ export {};
@@ -0,0 +1,39 @@
1
+ import * as fs from 'node:fs';
2
+ import { ensureNestedObject, getDownloadedVersions, saveDownloadedVersions, } from '../fs/config/downloadedVersions.js';
3
+ import { hashStringSync } from './hash.js';
4
+ /**
5
+ * Persist postprocessed content hashes for recently downloaded files into gt-lock.json.
6
+ */
7
+ export function persistPostProcessHashes(settings, includeFiles, downloadedMeta) {
8
+ if (!includeFiles || includeFiles.size === 0 || downloadedMeta.size === 0) {
9
+ return;
10
+ }
11
+ const downloadedVersions = getDownloadedVersions(settings.configDirectory);
12
+ let lockUpdated = false;
13
+ for (const filePath of includeFiles) {
14
+ const meta = downloadedMeta.get(filePath);
15
+ if (!meta)
16
+ continue;
17
+ if (!fs.existsSync(filePath))
18
+ continue;
19
+ const content = fs.readFileSync(filePath, 'utf8');
20
+ const hash = hashStringSync(content);
21
+ ensureNestedObject(downloadedVersions.entries, [
22
+ meta.branchId,
23
+ meta.fileId,
24
+ meta.versionId,
25
+ meta.locale,
26
+ ]);
27
+ const existing = downloadedVersions.entries[meta.branchId][meta.fileId][meta.versionId][meta.locale] || {};
28
+ if (existing.postProcessHash !== hash) {
29
+ downloadedVersions.entries[meta.branchId][meta.fileId][meta.versionId][meta.locale] = {
30
+ ...existing,
31
+ postProcessHash: hash,
32
+ };
33
+ lockUpdated = true;
34
+ }
35
+ }
36
+ if (lockUpdated) {
37
+ saveDownloadedVersions(settings.configDirectory, downloadedVersions);
38
+ }
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtx-cli",
3
- "version": "2.5.18",
3
+ "version": "2.5.20",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [
@@ -104,7 +104,7 @@
104
104
  "unified": "^11.0.5",
105
105
  "unist-util-visit": "^5.0.0",
106
106
  "yaml": "^2.8.0",
107
- "generaltranslation": "8.0.5"
107
+ "generaltranslation": "8.0.6"
108
108
  },
109
109
  "devDependencies": {
110
110
  "@babel/types": "^7.28.4",