gt 2.10.8 → 2.11.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/CHANGELOG.md +12 -0
- package/dist/api/saveLocalEdits.js +1 -1
- package/dist/cli/base.js +1 -1
- package/dist/cli/commands/stage.d.ts +1 -0
- package/dist/cli/commands/stage.js +2 -1
- package/dist/cli/commands/translate.d.ts +1 -1
- package/dist/cli/commands/translate.js +19 -1
- package/dist/config/generateSettings.js +8 -1
- package/dist/formats/files/aggregateFiles.d.ts +4 -1
- package/dist/formats/files/aggregateFiles.js +28 -9
- package/dist/formats/files/collectFiles.d.ts +1 -0
- package/dist/formats/files/collectFiles.js +5 -3
- package/dist/fs/config/parseFilesConfig.d.ts +19 -5
- package/dist/fs/config/parseFilesConfig.js +66 -5
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/translation/stage.js +1 -1
- package/dist/translation/validate.js +2 -2
- package/dist/types/index.d.ts +12 -2
- package/dist/utils/resolvePublish.d.ts +18 -0
- package/dist/utils/resolvePublish.js +34 -0
- package/dist/workflows/steps/EnqueueStep.js +0 -1
- package/dist/workflows/steps/PublishStep.d.ts +10 -0
- package/dist/workflows/steps/PublishStep.js +38 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# gtx-cli
|
|
2
2
|
|
|
3
|
+
## 2.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1122](https://github.com/generaltranslation/gt/pull/1122) [`6d516a7`](https://github.com/generaltranslation/gt/commit/6d516a784f1192f7758689fcf4557e8a19de740a) Thanks [@fernando-aviles](https://github.com/fernando-aviles)! - Adding CDN publishing for all file types
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`6d516a7`](https://github.com/generaltranslation/gt/commit/6d516a784f1192f7758689fcf4557e8a19de740a)]:
|
|
12
|
+
- generaltranslation@8.1.18
|
|
13
|
+
- @generaltranslation/python-extractor@0.1.4
|
|
14
|
+
|
|
3
15
|
## 2.10.8
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -13,7 +13,7 @@ export async function saveLocalEdits(settings) {
|
|
|
13
13
|
if (!settings.files)
|
|
14
14
|
return;
|
|
15
15
|
// Collect current files from config
|
|
16
|
-
const files = await aggregateFiles(settings);
|
|
16
|
+
const { files } = await aggregateFiles(settings);
|
|
17
17
|
if (!files.length)
|
|
18
18
|
return;
|
|
19
19
|
// run branch query to get branch id
|
package/dist/cli/base.js
CHANGED
|
@@ -172,7 +172,7 @@ export class BaseCLI {
|
|
|
172
172
|
if (!settings.stageTranslations) {
|
|
173
173
|
const results = await handleStage(initOptions, settings, this.library, false);
|
|
174
174
|
if (results) {
|
|
175
|
-
await handleTranslate(initOptions, settings, results.fileVersionData, results.jobData, results.branchData);
|
|
175
|
+
await handleTranslate(initOptions, settings, results.fileVersionData, results.jobData, results.branchData, results.publishMap);
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
else {
|
|
@@ -13,7 +13,7 @@ export async function handleStage(options, settings, library, stage) {
|
|
|
13
13
|
// Validate credentials if not in dry run
|
|
14
14
|
if (!options.dryRun && !hasValidCredentials(settings))
|
|
15
15
|
return exitSync(1);
|
|
16
|
-
const { files: allFiles, reactComponents } = await collectFiles(options, settings, library);
|
|
16
|
+
const { files: allFiles, reactComponents, publishMap, } = await collectFiles(options, settings, library);
|
|
17
17
|
// Dry run
|
|
18
18
|
if (options.dryRun) {
|
|
19
19
|
logger.success(`Dry run: No files were sent to General Translation.`);
|
|
@@ -55,5 +55,6 @@ export async function handleStage(options, settings, library, stage) {
|
|
|
55
55
|
fileVersionData,
|
|
56
56
|
jobData,
|
|
57
57
|
branchData,
|
|
58
|
+
publishMap,
|
|
58
59
|
};
|
|
59
60
|
}
|
|
@@ -3,5 +3,5 @@ import { TranslateFlags } from '../../types/index.js';
|
|
|
3
3
|
import { Settings } from '../../types/index.js';
|
|
4
4
|
import { FileTranslationData } from '../../workflows/download.js';
|
|
5
5
|
import { BranchData } from '../../types/branch.js';
|
|
6
|
-
export declare function handleTranslate(options: TranslateFlags, settings: Settings, fileVersionData: FileTranslationData | undefined, jobData: EnqueueFilesResult | undefined, branchData: BranchData | undefined): Promise<void>;
|
|
6
|
+
export declare function handleTranslate(options: TranslateFlags, settings: Settings, fileVersionData: FileTranslationData | undefined, jobData: EnqueueFilesResult | undefined, branchData: BranchData | undefined, publishMap?: Map<string, boolean>): Promise<void>;
|
|
7
7
|
export declare function postProcessTranslations(settings: Settings, includeFiles?: Set<string>): Promise<void>;
|
|
@@ -9,8 +9,11 @@ import processOpenApi from '../../utils/processOpenApi.js';
|
|
|
9
9
|
import localizeStaticImports from '../../utils/localizeStaticImports.js';
|
|
10
10
|
import { getDownloadedMeta } from '../../state/recentDownloads.js';
|
|
11
11
|
import { persistPostProcessHashes } from '../../utils/persistPostprocessHashes.js';
|
|
12
|
+
import { PublishStep } from '../../workflows/steps/PublishStep.js';
|
|
13
|
+
import { gt } from '../../utils/gt.js';
|
|
14
|
+
import { hasPublishConfig } from '../../utils/resolvePublish.js';
|
|
12
15
|
// Downloads translations that were completed
|
|
13
|
-
export async function handleTranslate(options, settings, fileVersionData, jobData, branchData) {
|
|
16
|
+
export async function handleTranslate(options, settings, fileVersionData, jobData, branchData, publishMap) {
|
|
14
17
|
if (fileVersionData) {
|
|
15
18
|
const { resolvedPaths, placeholderPaths, transformPaths } = settings.files;
|
|
16
19
|
const fileMapping = createFileMapping(resolvedPaths, placeholderPaths, transformPaths, settings.locales, settings.defaultLocale);
|
|
@@ -26,6 +29,21 @@ export async function handleTranslate(options, settings, fileVersionData, jobDat
|
|
|
26
29
|
forceRetranslation: options.force,
|
|
27
30
|
forceDownload: options.forceDownload || options.force, // if force is true should also force download
|
|
28
31
|
});
|
|
32
|
+
// Publish/unpublish files after translations are downloaded
|
|
33
|
+
if (publishMap && hasPublishConfig(settings)) {
|
|
34
|
+
const allFileRefs = Object.entries(fileVersionData)
|
|
35
|
+
.filter(([fileId]) => publishMap.has(fileId))
|
|
36
|
+
.map(([fileId, data]) => ({
|
|
37
|
+
fileId,
|
|
38
|
+
versionId: data.versionId,
|
|
39
|
+
branchId: branchData?.currentBranch.id,
|
|
40
|
+
publish: publishMap.get(fileId),
|
|
41
|
+
fileName: data.fileName,
|
|
42
|
+
}));
|
|
43
|
+
const publishStep = new PublishStep(gt);
|
|
44
|
+
await publishStep.run(allFileRefs);
|
|
45
|
+
await publishStep.wait();
|
|
46
|
+
}
|
|
29
47
|
}
|
|
30
48
|
}
|
|
31
49
|
export async function postProcessTranslations(settings, includeFiles) {
|
|
@@ -125,7 +125,14 @@ export async function generateSettings(flags, cwd = process.cwd()) {
|
|
|
125
125
|
.map(([key]) => key);
|
|
126
126
|
mergedOptions.files = mergedOptions.files
|
|
127
127
|
? resolveFiles(mergedOptions.files, mergedOptions.defaultLocale, mergedOptions.locales, cwd, compositePatterns)
|
|
128
|
-
: {
|
|
128
|
+
: {
|
|
129
|
+
resolvedPaths: {},
|
|
130
|
+
placeholderPaths: {},
|
|
131
|
+
transformPaths: {},
|
|
132
|
+
publishPaths: new Set(),
|
|
133
|
+
unpublishPaths: new Set(),
|
|
134
|
+
gtJson: {},
|
|
135
|
+
};
|
|
129
136
|
mergedOptions.options = {
|
|
130
137
|
...(mergedOptions.options || {}),
|
|
131
138
|
mintlify: {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { Settings } from '../../types/index.js';
|
|
2
2
|
import type { FileToUpload } from '../../types/data.js';
|
|
3
3
|
export declare const SUPPORTED_DATA_FORMATS: string[];
|
|
4
|
-
export declare function aggregateFiles(settings: Settings): Promise<
|
|
4
|
+
export declare function aggregateFiles(settings: Settings): Promise<{
|
|
5
|
+
files: FileToUpload[];
|
|
6
|
+
publishMap: Map<string, boolean>;
|
|
7
|
+
}>;
|
|
@@ -11,6 +11,7 @@ import { determineLibrary } from '../../fs/determineFramework/index.js';
|
|
|
11
11
|
import { hashStringSync } from '../../utils/hash.js';
|
|
12
12
|
import { preprocessContent } from './preprocessContent.js';
|
|
13
13
|
import { parseKeyedMetadata, } from '../parseKeyedMetadata.js';
|
|
14
|
+
import { shouldPublishFile } from '../../utils/resolvePublish.js';
|
|
14
15
|
/**
|
|
15
16
|
* Checks if a file path is a metadata companion file (e.g. foo.metadata.json)
|
|
16
17
|
* AND its corresponding source file (e.g. foo.json) exists in the file list.
|
|
@@ -27,14 +28,25 @@ function isCompanionMetadataFile(filePath, allFilePaths) {
|
|
|
27
28
|
export const SUPPORTED_DATA_FORMATS = ['JSX', 'ICU', 'I18NEXT'];
|
|
28
29
|
export async function aggregateFiles(settings) {
|
|
29
30
|
// Aggregate all files to translate
|
|
30
|
-
const
|
|
31
|
+
const files = [];
|
|
32
|
+
const publishMap = new Map();
|
|
31
33
|
if (!settings.files ||
|
|
32
34
|
(Object.keys(settings.files.placeholderPaths).length === 1 &&
|
|
33
35
|
settings.files.placeholderPaths.gt)) {
|
|
34
|
-
return
|
|
36
|
+
return { files, publishMap };
|
|
35
37
|
}
|
|
36
38
|
const { resolvedPaths: filePaths } = settings.files;
|
|
37
39
|
const skipValidation = settings.options?.skipFileValidation;
|
|
40
|
+
// Build publish map upfront from resolved paths
|
|
41
|
+
for (const fileType of SUPPORTED_FILE_EXTENSIONS) {
|
|
42
|
+
if (filePaths[fileType]) {
|
|
43
|
+
for (const absolutePath of filePaths[fileType]) {
|
|
44
|
+
const relativePath = getRelative(absolutePath);
|
|
45
|
+
const fileId = hashStringSync(relativePath);
|
|
46
|
+
publishMap.set(fileId, shouldPublishFile(absolutePath, settings));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
38
50
|
// Process JSON files
|
|
39
51
|
if (filePaths.json) {
|
|
40
52
|
const { library, additionalModules } = determineLibrary();
|
|
@@ -122,7 +134,7 @@ export async function aggregateFiles(settings) {
|
|
|
122
134
|
}
|
|
123
135
|
return true;
|
|
124
136
|
});
|
|
125
|
-
|
|
137
|
+
files.push(...jsonFiles.filter((file) => file !== null));
|
|
126
138
|
}
|
|
127
139
|
// Process YAML files
|
|
128
140
|
if (filePaths.yaml) {
|
|
@@ -191,7 +203,7 @@ export async function aggregateFiles(settings) {
|
|
|
191
203
|
}
|
|
192
204
|
return true;
|
|
193
205
|
});
|
|
194
|
-
|
|
206
|
+
files.push(...yamlFiles.filter((file) => file !== null));
|
|
195
207
|
}
|
|
196
208
|
// Process Twilio Content JSON files
|
|
197
209
|
if (filePaths.twilioContentJson) {
|
|
@@ -231,7 +243,7 @@ export async function aggregateFiles(settings) {
|
|
|
231
243
|
}
|
|
232
244
|
return true;
|
|
233
245
|
});
|
|
234
|
-
|
|
246
|
+
files.push(...twilioContentJsonFiles.filter((file) => file !== null));
|
|
235
247
|
}
|
|
236
248
|
for (const fileType of SUPPORTED_FILE_EXTENSIONS) {
|
|
237
249
|
if (fileType === 'json' ||
|
|
@@ -239,7 +251,7 @@ export async function aggregateFiles(settings) {
|
|
|
239
251
|
fileType === 'twilioContentJson')
|
|
240
252
|
continue;
|
|
241
253
|
if (filePaths[fileType]) {
|
|
242
|
-
const
|
|
254
|
+
const parsed = filePaths[fileType]
|
|
243
255
|
.map((filePath) => {
|
|
244
256
|
const content = readFile(filePath);
|
|
245
257
|
const relativePath = getRelative(filePath);
|
|
@@ -268,11 +280,18 @@ export async function aggregateFiles(settings) {
|
|
|
268
280
|
}
|
|
269
281
|
return true;
|
|
270
282
|
});
|
|
271
|
-
|
|
283
|
+
files.push(...parsed.filter((file) => file !== null));
|
|
272
284
|
}
|
|
273
285
|
}
|
|
274
|
-
if (
|
|
286
|
+
if (files.length === 0 && !settings.publish) {
|
|
275
287
|
logger.error('No files to translate were found. Check your configuration and try again.');
|
|
276
288
|
}
|
|
277
|
-
|
|
289
|
+
// Remove stale entries for files that were skipped during validation
|
|
290
|
+
const validFileIds = new Set(files.map((f) => f.fileId));
|
|
291
|
+
for (const fileId of publishMap.keys()) {
|
|
292
|
+
if (!validFileIds.has(fileId)) {
|
|
293
|
+
publishMap.delete(fileId);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return { files, publishMap };
|
|
278
297
|
}
|
|
@@ -3,4 +3,5 @@ import type { FileToUpload } from 'generaltranslation/types';
|
|
|
3
3
|
export declare function collectFiles(options: TranslateFlags, settings: Settings, library: SupportedLibraries): Promise<{
|
|
4
4
|
files: FileToUpload[];
|
|
5
5
|
reactComponents: number;
|
|
6
|
+
publishMap: Map<string, boolean>;
|
|
6
7
|
}>;
|
|
@@ -5,9 +5,10 @@ import { aggregateInlineTranslations } from '../../translation/stage.js';
|
|
|
5
5
|
import { hashStringSync } from '../../utils/hash.js';
|
|
6
6
|
import { TEMPLATE_FILE_NAME, TEMPLATE_FILE_ID } from '../../utils/constants.js';
|
|
7
7
|
import { isInlineLibrary } from '../../types/libraries.js';
|
|
8
|
+
import { shouldPublishGt } from '../../utils/resolvePublish.js';
|
|
8
9
|
export async function collectFiles(options, settings, library) {
|
|
9
10
|
// Aggregate files
|
|
10
|
-
const
|
|
11
|
+
const { files, publishMap } = await aggregateFiles(settings);
|
|
11
12
|
// Parse for React components
|
|
12
13
|
let reactComponents = 0;
|
|
13
14
|
if (isInlineLibrary(library)) {
|
|
@@ -34,7 +35,7 @@ export async function collectFiles(options, settings, library) {
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
reactComponents = updates.length;
|
|
37
|
-
|
|
38
|
+
files.push({
|
|
38
39
|
fileName: TEMPLATE_FILE_NAME,
|
|
39
40
|
content: JSON.stringify(fileData),
|
|
40
41
|
fileFormat: 'GTJSON',
|
|
@@ -43,7 +44,8 @@ export async function collectFiles(options, settings, library) {
|
|
|
43
44
|
versionId: hashStringSync(JSON.stringify(Object.keys(fileData).sort())),
|
|
44
45
|
locale: settings.defaultLocale,
|
|
45
46
|
});
|
|
47
|
+
publishMap.set(TEMPLATE_FILE_ID, shouldPublishGt(settings));
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
|
-
return { files
|
|
50
|
+
return { files, reactComponents, publishMap };
|
|
49
51
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FilesOptions, ResolvedFiles, TransformFiles, TransformOption } from '../../types/index.js';
|
|
1
|
+
import { FilesOptions, IncludePattern, ResolvedFiles, TransformFiles, TransformOption } from '../../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Resolves the files from the files object
|
|
4
4
|
* Replaces [locale] with the actual locale in the files
|
|
@@ -9,9 +9,18 @@ import { FilesOptions, ResolvedFiles, TransformFiles, TransformOption } from '..
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function resolveLocaleFiles(files: ResolvedFiles, locale: string): ResolvedFiles;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
|
|
12
|
+
* Normalizes include patterns into plain path strings and tracks which
|
|
13
|
+
* patterns have explicit publish flags.
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeIncludePatterns(patterns: IncludePattern[]): {
|
|
16
|
+
paths: string[];
|
|
17
|
+
publishPatterns: string[];
|
|
18
|
+
unpublishPatterns: string[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Resolves the files from the files object.
|
|
22
|
+
* Performs glob pattern expansion on the files.
|
|
23
|
+
* Replaces [locale] with the actual locale in the files.
|
|
15
24
|
*
|
|
16
25
|
* @param files - The files object
|
|
17
26
|
* @returns The resolved files
|
|
@@ -20,7 +29,12 @@ export declare function resolveFiles(files: FilesOptions, locale: string, locale
|
|
|
20
29
|
resolvedPaths: ResolvedFiles;
|
|
21
30
|
placeholderPaths: ResolvedFiles;
|
|
22
31
|
transformPaths: TransformFiles;
|
|
23
|
-
|
|
32
|
+
publishPaths: Set<string>;
|
|
33
|
+
unpublishPaths: Set<string>;
|
|
34
|
+
gtJson: {
|
|
35
|
+
publish?: boolean;
|
|
36
|
+
includeSourceCodeContext?: boolean;
|
|
37
|
+
};
|
|
24
38
|
};
|
|
25
39
|
export declare function expandGlobPatterns(cwd: string, includePatterns: string[], excludePatterns: string[], locale: string, locales: string[], transformPatterns?: TransformOption | string | TransformOption[], compositePatterns?: string[]): {
|
|
26
40
|
resolvedPaths: string[];
|
|
@@ -22,9 +22,33 @@ export function resolveLocaleFiles(files, locale) {
|
|
|
22
22
|
return result;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
25
|
+
* Normalizes include patterns into plain path strings and tracks which
|
|
26
|
+
* patterns have explicit publish flags.
|
|
27
|
+
*/
|
|
28
|
+
export function normalizeIncludePatterns(patterns) {
|
|
29
|
+
const paths = [];
|
|
30
|
+
const publishPatterns = [];
|
|
31
|
+
const unpublishPatterns = [];
|
|
32
|
+
for (const pattern of patterns) {
|
|
33
|
+
if (typeof pattern === 'string') {
|
|
34
|
+
paths.push(pattern);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
paths.push(pattern.pattern);
|
|
38
|
+
if (pattern.publish === true) {
|
|
39
|
+
publishPatterns.push(pattern.pattern);
|
|
40
|
+
}
|
|
41
|
+
else if (pattern.publish === false) {
|
|
42
|
+
unpublishPatterns.push(pattern.pattern);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { paths, publishPatterns, unpublishPatterns };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolves the files from the files object.
|
|
50
|
+
* Performs glob pattern expansion on the files.
|
|
51
|
+
* Replaces [locale] with the actual locale in the files.
|
|
28
52
|
*
|
|
29
53
|
* @param files - The files object
|
|
30
54
|
* @returns The resolved files
|
|
@@ -34,6 +58,8 @@ export function resolveFiles(files, locale, locales, cwd, compositePatterns) {
|
|
|
34
58
|
const result = {};
|
|
35
59
|
const placeholderResult = {};
|
|
36
60
|
const transformPaths = {};
|
|
61
|
+
const publishPaths = new Set();
|
|
62
|
+
const unpublishPaths = new Set();
|
|
37
63
|
// Process GT files
|
|
38
64
|
if (files.gt?.output) {
|
|
39
65
|
placeholderResult.gt = path.resolve(cwd, files.gt.output);
|
|
@@ -49,16 +75,24 @@ export function resolveFiles(files, locale, locales, cwd, compositePatterns) {
|
|
|
49
75
|
}
|
|
50
76
|
// ==== PLACEHOLDERS ==== //
|
|
51
77
|
if (files[fileType]?.include) {
|
|
52
|
-
const
|
|
78
|
+
const { paths, publishPatterns, unpublishPatterns } = normalizeIncludePatterns(files[fileType].include);
|
|
79
|
+
const filePaths = expandGlobPatterns(cwd, paths, files[fileType]?.exclude || [], locale, locales, transformPaths[fileType] || undefined, compositePatterns);
|
|
53
80
|
result[fileType] = filePaths.resolvedPaths;
|
|
54
81
|
placeholderResult[fileType] = filePaths.placeholderPaths;
|
|
82
|
+
// Classify resolved paths into publish/unpublish sets
|
|
83
|
+
classifyPublishPaths(filePaths.resolvedPaths, publishPatterns, unpublishPatterns, cwd, locale, publishPaths, unpublishPaths);
|
|
55
84
|
}
|
|
56
85
|
}
|
|
57
86
|
return {
|
|
58
87
|
resolvedPaths: result,
|
|
59
88
|
placeholderPaths: placeholderResult,
|
|
60
89
|
transformPaths: transformPaths,
|
|
61
|
-
|
|
90
|
+
publishPaths,
|
|
91
|
+
unpublishPaths,
|
|
92
|
+
gtJson: {
|
|
93
|
+
publish: files.gt?.publish,
|
|
94
|
+
includeSourceCodeContext: files.gt?.includeSourceCodeContext,
|
|
95
|
+
},
|
|
62
96
|
};
|
|
63
97
|
}
|
|
64
98
|
// Helper function to expand glob patterns
|
|
@@ -149,3 +183,30 @@ function buildPlaceholderPathFromPattern(patternPath, absolutePath, localeTag) {
|
|
|
149
183
|
function toPosixPath(value) {
|
|
150
184
|
return value.split(path.sep).join(path.posix.sep);
|
|
151
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Classifies resolved file paths into publish/unpublish sets by matching
|
|
188
|
+
* them against the given glob patterns. Uses POSIX paths for micromatch
|
|
189
|
+
* compatibility but stores platform-native paths in the output sets.
|
|
190
|
+
*/
|
|
191
|
+
function classifyPublishPaths(resolvedPaths, publishPatterns, unpublishPatterns, cwd, locale, publishPaths, unpublishPaths) {
|
|
192
|
+
if (publishPatterns.length === 0 && unpublishPatterns.length === 0)
|
|
193
|
+
return;
|
|
194
|
+
const posixPaths = resolvedPaths.map(toPosixPath);
|
|
195
|
+
const toAbsoluteGlob = (p) => toPosixPath(path.resolve(cwd, p.replace(/\[locale\]/g, locale)));
|
|
196
|
+
for (const pattern of publishPatterns) {
|
|
197
|
+
const matched = new Set(micromatch(posixPaths, toAbsoluteGlob(pattern)));
|
|
198
|
+
for (let i = 0; i < posixPaths.length; i++) {
|
|
199
|
+
if (matched.has(posixPaths[i])) {
|
|
200
|
+
publishPaths.add(resolvedPaths[i]);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (const pattern of unpublishPatterns) {
|
|
205
|
+
const matched = new Set(micromatch(posixPaths, toAbsoluteGlob(pattern)));
|
|
206
|
+
for (let i = 0; i < posixPaths.length; i++) {
|
|
207
|
+
if (matched.has(posixPaths[i])) {
|
|
208
|
+
unpublishPaths.add(resolvedPaths[i]);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "2.
|
|
1
|
+
export declare const PACKAGE_VERSION = "2.11.0";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const PACKAGE_VERSION = '2.
|
|
2
|
+
export const PACKAGE_VERSION = '2.11.0';
|
|
@@ -15,7 +15,7 @@ export async function aggregateInlineTranslations(options, settings, library) {
|
|
|
15
15
|
]);
|
|
16
16
|
}
|
|
17
17
|
// ---- CREATING UPDATES ---- //
|
|
18
|
-
const { updates, errors, warnings } = await createUpdates(options, settings.src, options.dictionary, library, false, settings.parsingOptions, settings.files?.includeSourceCodeContext ?? false);
|
|
18
|
+
const { updates, errors, warnings } = await createUpdates(options, settings.src, options.dictionary, library, false, settings.parsingOptions, settings.files?.gtJson.includeSourceCodeContext ?? false);
|
|
19
19
|
if (warnings.length > 0) {
|
|
20
20
|
logger.warn(chalk.yellow(`CLI tool encountered ${warnings.length} warnings while scanning for translatable content.\n` +
|
|
21
21
|
warnings
|
|
@@ -10,7 +10,7 @@ import { Libraries } from '../types/libraries.js';
|
|
|
10
10
|
*/
|
|
11
11
|
async function runValidation(settings, pkg, files) {
|
|
12
12
|
if (files && files.length > 0) {
|
|
13
|
-
return createInlineUpdates(pkg, true, files, settings.parsingOptions, settings.files?.includeSourceCodeContext ?? false);
|
|
13
|
+
return createInlineUpdates(pkg, true, files, settings.parsingOptions, settings.files?.gtJson.includeSourceCodeContext ?? false);
|
|
14
14
|
}
|
|
15
15
|
// Full project validation
|
|
16
16
|
// Use local variable to avoid mutating caller's settings object
|
|
@@ -23,7 +23,7 @@ async function runValidation(settings, pkg, files) {
|
|
|
23
23
|
'./dictionary.ts',
|
|
24
24
|
'./src/dictionary.ts',
|
|
25
25
|
]);
|
|
26
|
-
return createUpdates(settings, settings.src, dictionary, pkg, true, settings.parsingOptions, settings.files?.includeSourceCodeContext ?? false);
|
|
26
|
+
return createUpdates(settings, settings.src, dictionary, pkg, true, settings.parsingOptions, settings.files?.gtJson.includeSourceCodeContext ?? false);
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* Parse file path from error/warning string in withLocation format: "filepath (line:col): message"
|
package/dist/types/index.d.ts
CHANGED
|
@@ -133,15 +133,20 @@ export type TransformOption = {
|
|
|
133
133
|
export type TransformFiles = {
|
|
134
134
|
[K in SupportedFileExtension]?: TransformOption | string | TransformOption[];
|
|
135
135
|
};
|
|
136
|
+
export type IncludePattern = string | {
|
|
137
|
+
pattern: string;
|
|
138
|
+
publish?: boolean;
|
|
139
|
+
};
|
|
136
140
|
export type FilesOptions = {
|
|
137
141
|
[K in SupportedFileExtension]?: {
|
|
138
|
-
include:
|
|
142
|
+
include: IncludePattern[];
|
|
139
143
|
exclude?: string[];
|
|
140
144
|
transform?: string | TransformOption | TransformOption[];
|
|
141
145
|
};
|
|
142
146
|
} & {
|
|
143
147
|
gt?: {
|
|
144
148
|
output: string;
|
|
149
|
+
publish?: boolean;
|
|
145
150
|
includeSourceCodeContext?: boolean;
|
|
146
151
|
};
|
|
147
152
|
};
|
|
@@ -159,7 +164,12 @@ export type Settings = {
|
|
|
159
164
|
resolvedPaths: ResolvedFiles;
|
|
160
165
|
placeholderPaths: ResolvedFiles;
|
|
161
166
|
transformPaths: TransformFiles;
|
|
162
|
-
|
|
167
|
+
publishPaths: Set<string>;
|
|
168
|
+
unpublishPaths: Set<string>;
|
|
169
|
+
gtJson: {
|
|
170
|
+
publish?: boolean;
|
|
171
|
+
includeSourceCodeContext?: boolean;
|
|
172
|
+
};
|
|
163
173
|
};
|
|
164
174
|
stageTranslations: boolean;
|
|
165
175
|
publish: boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Settings } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Determines whether a file should be published based on the publish resolution logic:
|
|
4
|
+
* - If the file is explicitly opted OUT (unpublishPaths), never publish
|
|
5
|
+
* - If the file is explicitly opted IN (publishPaths), always publish
|
|
6
|
+
* - Otherwise, fall back to the global publish setting
|
|
7
|
+
*/
|
|
8
|
+
export declare function shouldPublishFile(resolvedPath: string, settings: Settings): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Returns true if the user has any explicit publish configuration —
|
|
11
|
+
* global flag, gt-specific flag, or per-file publish/unpublish patterns.
|
|
12
|
+
*/
|
|
13
|
+
export declare function hasPublishConfig(settings: Settings): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Determines whether gtjson content should be published.
|
|
16
|
+
* Uses the gt-specific publish flag if set, otherwise falls back to global.
|
|
17
|
+
*/
|
|
18
|
+
export declare function shouldPublishGt(settings: Settings): boolean;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines whether a file should be published based on the publish resolution logic:
|
|
3
|
+
* - If the file is explicitly opted OUT (unpublishPaths), never publish
|
|
4
|
+
* - If the file is explicitly opted IN (publishPaths), always publish
|
|
5
|
+
* - Otherwise, fall back to the global publish setting
|
|
6
|
+
*/
|
|
7
|
+
export function shouldPublishFile(resolvedPath, settings) {
|
|
8
|
+
if (settings.files.unpublishPaths?.has(resolvedPath))
|
|
9
|
+
return false;
|
|
10
|
+
if (settings.files.publishPaths?.has(resolvedPath))
|
|
11
|
+
return true;
|
|
12
|
+
return settings.publish ?? false;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns true if the user has any explicit publish configuration —
|
|
16
|
+
* global flag, gt-specific flag, or per-file publish/unpublish patterns.
|
|
17
|
+
*/
|
|
18
|
+
export function hasPublishConfig(settings) {
|
|
19
|
+
return (settings.publish ||
|
|
20
|
+
settings.files.gtJson.publish !== undefined ||
|
|
21
|
+
(settings.files.publishPaths?.size ?? 0) > 0 ||
|
|
22
|
+
(settings.files.unpublishPaths?.size ?? 0) > 0);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Determines whether gtjson content should be published.
|
|
26
|
+
* Uses the gt-specific publish flag if set, otherwise falls back to global.
|
|
27
|
+
*/
|
|
28
|
+
export function shouldPublishGt(settings) {
|
|
29
|
+
if (settings.files.gtJson.publish === false)
|
|
30
|
+
return false;
|
|
31
|
+
if (settings.files.gtJson.publish === true)
|
|
32
|
+
return true;
|
|
33
|
+
return settings.publish;
|
|
34
|
+
}
|
|
@@ -18,7 +18,6 @@ export class EnqueueStep extends WorkflowStep {
|
|
|
18
18
|
this.result = await this.gt.enqueueFiles(files, {
|
|
19
19
|
sourceLocale: this.settings.defaultLocale,
|
|
20
20
|
targetLocales: this.settings.locales,
|
|
21
|
-
publish: this.settings.publish,
|
|
22
21
|
requireApproval: this.settings.stageTranslations,
|
|
23
22
|
modelProvider: this.settings.modelProvider,
|
|
24
23
|
force: this.force,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { WorkflowStep } from './WorkflowStep.js';
|
|
2
|
+
import { GT } from 'generaltranslation';
|
|
3
|
+
import type { PublishFileEntry } from 'generaltranslation/types';
|
|
4
|
+
export declare class PublishStep extends WorkflowStep<PublishFileEntry[], void> {
|
|
5
|
+
private gt;
|
|
6
|
+
private spinner;
|
|
7
|
+
constructor(gt: GT);
|
|
8
|
+
run(files: PublishFileEntry[]): Promise<void>;
|
|
9
|
+
wait(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { WorkflowStep } from './WorkflowStep.js';
|
|
2
|
+
import { logger } from '../../console/logger.js';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
export class PublishStep extends WorkflowStep {
|
|
5
|
+
gt;
|
|
6
|
+
spinner = logger.createSpinner('dots');
|
|
7
|
+
constructor(gt) {
|
|
8
|
+
super();
|
|
9
|
+
this.gt = gt;
|
|
10
|
+
}
|
|
11
|
+
async run(files) {
|
|
12
|
+
if (files.length === 0)
|
|
13
|
+
return;
|
|
14
|
+
this.spinner.start('Updating CDN...');
|
|
15
|
+
try {
|
|
16
|
+
const result = await this.gt.publishFiles(files);
|
|
17
|
+
const failed = result.results.filter((r) => !r.success);
|
|
18
|
+
if (failed.length > 0) {
|
|
19
|
+
this.spinner.stop(chalk.yellow('CDN updated with errors'));
|
|
20
|
+
for (const f of failed) {
|
|
21
|
+
const file = files.find((p) => p.fileId === f.fileId);
|
|
22
|
+
const name = file?.fileName ?? f.fileId;
|
|
23
|
+
logger.warn(`Failed to update ${name}: ${f.error ?? 'unknown error'}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
this.spinner.stop(chalk.green('CDN updated'));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
this.spinner.stop(chalk.red('Failed to update CDN'));
|
|
32
|
+
logger.warn(`Publish error: ${err instanceof Error ? err.message : String(err)}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async wait() {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gt",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": "dist/main.js",
|
|
6
6
|
"files": [
|
|
@@ -110,8 +110,8 @@
|
|
|
110
110
|
"unified": "^11.0.5",
|
|
111
111
|
"unist-util-visit": "^5.0.0",
|
|
112
112
|
"yaml": "^2.8.0",
|
|
113
|
-
"@generaltranslation/python-extractor": "0.1.
|
|
114
|
-
"generaltranslation": "8.1.
|
|
113
|
+
"@generaltranslation/python-extractor": "0.1.4",
|
|
114
|
+
"generaltranslation": "8.1.18",
|
|
115
115
|
"gt-remark": "1.0.5"
|
|
116
116
|
},
|
|
117
117
|
"devDependencies": {
|