locize-cli 10.0.2 → 10.1.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 +8 -0
- package/README.md +21 -0
- package/bin/locize +115 -8
- package/copyVersion.js +6 -1
- package/createBranch.js +41 -0
- package/download.js +43 -19
- package/getBranches.js +40 -0
- package/getJob.js +1 -1
- package/getProjectStats.js +1 -1
- package/isValidUuid.js +2 -0
- package/mergeBranch.js +98 -0
- package/package.json +1 -1
- package/sync.js +59 -35
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
Project versioning adheres to [Semantic Versioning](http://semver.org/).
|
|
6
6
|
Change log format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
7
7
|
|
|
8
|
+
## [10.1.0](https://github.com/locize/locize-cli/compare/v10.0.3...v10.1.0) - 2025-07-10
|
|
9
|
+
|
|
10
|
+
- introduce branching features
|
|
11
|
+
|
|
12
|
+
## [10.0.3](https://github.com/locize/locize-cli/compare/v10.0.2...v10.0.3) - 2025-07-09
|
|
13
|
+
|
|
14
|
+
- introduce `--ignore-if-version-exists` option for `copy-version`
|
|
15
|
+
|
|
8
16
|
## [10.0.2](https://github.com/locize/locize-cli/compare/v10.0.1...v10.0.2) - 2025-07-02
|
|
9
17
|
|
|
10
18
|
- respect opt.namespace when parsing local namespaces
|
package/README.md
CHANGED
|
@@ -325,6 +325,27 @@ locize format path/to/dictionary --format android
|
|
|
325
325
|
```
|
|
326
326
|
|
|
327
327
|
|
|
328
|
+
## Working with branches
|
|
329
|
+
### Create a new branch
|
|
330
|
+
|
|
331
|
+
```sh
|
|
332
|
+
locize create-branch featureXYZ --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba --ver latest
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Sync or Download that branch
|
|
336
|
+
|
|
337
|
+
```sh
|
|
338
|
+
locize sync --branch featureXYZ --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba
|
|
339
|
+
|
|
340
|
+
locize download --branch featureXYZ --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Merge that branch
|
|
344
|
+
|
|
345
|
+
```sh
|
|
346
|
+
locize merge-branch featureXYZ --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba --delete true
|
|
347
|
+
```
|
|
348
|
+
|
|
328
349
|
|
|
329
350
|
## Other information
|
|
330
351
|
|
package/bin/locize
CHANGED
|
@@ -26,6 +26,8 @@ const removeVersion = require('../removeVersion.js');
|
|
|
26
26
|
const publishVersion = require('../publishVersion');
|
|
27
27
|
const deleteNamespace = require('../deleteNamespace');
|
|
28
28
|
const formatFn = require('../format');
|
|
29
|
+
const createBranch = require('../createBranch');
|
|
30
|
+
const mergeBranch = require('../mergeBranch');
|
|
29
31
|
|
|
30
32
|
var config = {};
|
|
31
33
|
try {
|
|
@@ -239,6 +241,7 @@ program
|
|
|
239
241
|
.option('-m, --path-mask <mask>', 'This will define the folder and file structure; do not add a file extension (default: {{language}}/{{namespace}})', `{{language}}${path.sep}{{namespace}}`)
|
|
240
242
|
.option('-c, --clean <true|false>', 'Removes all local files by removing the whole folder (default: false)', 'false')
|
|
241
243
|
.option('-up, --unpublished <true|false>', 'Downloads the current (unpublished) translations. This will generate private download costs (default: false)', 'false')
|
|
244
|
+
.option('-b, --branch <branch>', 'The branch name (or id) that should be targeted')
|
|
242
245
|
.option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
|
|
243
246
|
.action((options) => {
|
|
244
247
|
try {
|
|
@@ -275,6 +278,8 @@ program
|
|
|
275
278
|
|
|
276
279
|
const pathMask = options.pathMask;
|
|
277
280
|
|
|
281
|
+
const branch = options.branch;
|
|
282
|
+
|
|
278
283
|
download({
|
|
279
284
|
apiKey: apiKey,
|
|
280
285
|
projectId: projectId,
|
|
@@ -289,7 +294,8 @@ program
|
|
|
289
294
|
clean: clean,
|
|
290
295
|
languageFolderPrefix: languageFolderPrefix,
|
|
291
296
|
pathMask: pathMask,
|
|
292
|
-
unpublished: unpublished
|
|
297
|
+
unpublished: unpublished,
|
|
298
|
+
branch: branch
|
|
293
299
|
});
|
|
294
300
|
})
|
|
295
301
|
.on('--help', () => {
|
|
@@ -380,6 +386,7 @@ program
|
|
|
380
386
|
.option('-n, --namespace <ns>', 'The namespace that should be targeted (you can also pass a comma separated list)')
|
|
381
387
|
.option('-g, --get-path <url>', `Specify the get-path url that should be used (default: ${getPathUrl})`)
|
|
382
388
|
.option('-up, --unpublished <true|false>', 'Downloads the current (unpublished) translations. This will generate private download costs (default: false)', 'false')
|
|
389
|
+
.option('-b, --branch <branch>', 'The branch name (or id) that should be targeted')
|
|
383
390
|
.option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
|
|
384
391
|
.action((options) => {
|
|
385
392
|
try {
|
|
@@ -428,6 +435,7 @@ program
|
|
|
428
435
|
const unpublished = options.unpublished === 'true';
|
|
429
436
|
const autoCreatePath = options.autoCreatePath === 'true';
|
|
430
437
|
const backupDeletedPath = options.backupDeletedPath;
|
|
438
|
+
const branch = options.branch;
|
|
431
439
|
|
|
432
440
|
sync({
|
|
433
441
|
apiPath: url.parse(getPath).protocol + '//' + url.parse(getPath).host,
|
|
@@ -453,7 +461,8 @@ program
|
|
|
453
461
|
pathMask: pathMask,
|
|
454
462
|
unpublished: unpublished,
|
|
455
463
|
autoCreatePath: autoCreatePath,
|
|
456
|
-
backupDeletedPath: backupDeletedPath
|
|
464
|
+
backupDeletedPath: backupDeletedPath,
|
|
465
|
+
branch: branch
|
|
457
466
|
});
|
|
458
467
|
})
|
|
459
468
|
.on('--help', () => {
|
|
@@ -552,6 +561,7 @@ program
|
|
|
552
561
|
.option('-k, --api-key <apiKey>', 'The api-key that should be used')
|
|
553
562
|
.option('-v, --ver <version>', 'The target version to be used to copy to (default: latest)')
|
|
554
563
|
.option('-i, --project-id <projectId>', 'The project-id that should be used')
|
|
564
|
+
.option('-iv, --ignore-if-version-exists <true|false>', 'The project-id that should be used (default: false)', 'false')
|
|
555
565
|
.option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
|
|
556
566
|
.action((fromVersion, options) => {
|
|
557
567
|
try {
|
|
@@ -576,19 +586,22 @@ program
|
|
|
576
586
|
|
|
577
587
|
const getPath = options.getPath || config.getPath || getPathUrl;
|
|
578
588
|
|
|
589
|
+
const ignoreIfVersionExists = options.ignoreIfVersionExists === 'true';
|
|
590
|
+
|
|
579
591
|
copyVersion({
|
|
580
592
|
apiKey: apiKey,
|
|
581
593
|
projectId: projectId,
|
|
582
594
|
apiPath: url.parse(getPath).protocol + '//' + url.parse(getPath).host,
|
|
583
595
|
fromVersion: fromVersion,
|
|
584
|
-
toVersion: version
|
|
596
|
+
toVersion: version,
|
|
597
|
+
ignoreIfVersionExists: ignoreIfVersionExists
|
|
585
598
|
});
|
|
586
599
|
})
|
|
587
600
|
.on('--help', () => {
|
|
588
601
|
console.log(' Examples:');
|
|
589
602
|
console.log();
|
|
590
|
-
console.log(' $ locize copy-version latest
|
|
591
|
-
console.log(' $ locize copy-version latest --ver production
|
|
603
|
+
console.log(' $ locize copy-version latest');
|
|
604
|
+
console.log(' $ locize copy-version latest --ver production');
|
|
592
605
|
console.log(' $ locize copy-version latest --api-key <apiKey> --project-id <projectId> --ver <version>');
|
|
593
606
|
console.log();
|
|
594
607
|
});
|
|
@@ -631,7 +644,7 @@ program
|
|
|
631
644
|
.on('--help', () => {
|
|
632
645
|
console.log(' Examples:');
|
|
633
646
|
console.log();
|
|
634
|
-
console.log(' $ locize remove-version tmp-ver
|
|
647
|
+
console.log(' $ locize remove-version tmp-ver');
|
|
635
648
|
console.log(' $ locize remove-version tmp-ver --api-key <apiKey> --project-id <projectId>');
|
|
636
649
|
console.log();
|
|
637
650
|
});
|
|
@@ -681,8 +694,8 @@ program
|
|
|
681
694
|
.on('--help', () => {
|
|
682
695
|
console.log(' Examples:');
|
|
683
696
|
console.log();
|
|
684
|
-
console.log(' $ locize publish-version
|
|
685
|
-
console.log(' $ locize publish-version --ver production
|
|
697
|
+
console.log(' $ locize publish-version');
|
|
698
|
+
console.log(' $ locize publish-version --ver production');
|
|
686
699
|
console.log(' $ locize publish-version --api-key <apiKey> --project-id <projectId> --ver <version>');
|
|
687
700
|
console.log();
|
|
688
701
|
});
|
|
@@ -777,6 +790,100 @@ program
|
|
|
777
790
|
console.log();
|
|
778
791
|
});
|
|
779
792
|
|
|
793
|
+
program
|
|
794
|
+
.command('create-branch <branch>')
|
|
795
|
+
.alias('cb')
|
|
796
|
+
.description('create branch')
|
|
797
|
+
.option('-k, --api-key <apiKey>', 'The api-key that should be used')
|
|
798
|
+
.option('-v, --ver <version>', 'The target version to be used to copy to (default: latest)')
|
|
799
|
+
.option('-i, --project-id <projectId>', 'The project-id that should be used')
|
|
800
|
+
.option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
|
|
801
|
+
.action((branch, options) => {
|
|
802
|
+
try {
|
|
803
|
+
config = ini.parse(fs.readFileSync(options.configPath, 'utf-8')) || config;
|
|
804
|
+
} catch (e) {}
|
|
805
|
+
|
|
806
|
+
const apiKey = options.apiKey || config.apiKey || process.env.LOCIZE_API_KEY || process.env.LOCIZE_KEY;
|
|
807
|
+
if (!apiKey) {
|
|
808
|
+
console.error(' error: missing required argument `apiKey`');
|
|
809
|
+
process.exit(1);
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
const projectId = options.projectId || config.projectId || process.env.LOCIZE_PROJECTID || process.env.LOCIZE_PID;
|
|
814
|
+
if (!projectId) {
|
|
815
|
+
console.error(' error: missing required argument `projectId`');
|
|
816
|
+
process.exit(1);
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
const version = options.ver || config.ver || config.version || process.env.LOCIZE_VERSION || process.env.LOCIZE_VER || 'latest';
|
|
821
|
+
|
|
822
|
+
const getPath = options.getPath || config.getPath || options.addPath || config.addPath || getPathUrl;
|
|
823
|
+
|
|
824
|
+
createBranch({
|
|
825
|
+
apiKey: apiKey,
|
|
826
|
+
projectId: projectId,
|
|
827
|
+
apiPath: url.parse(getPath).protocol + '//' + url.parse(getPath).host,
|
|
828
|
+
version: version,
|
|
829
|
+
branch: branch
|
|
830
|
+
});
|
|
831
|
+
})
|
|
832
|
+
.on('--help', () => {
|
|
833
|
+
console.log(' Examples:');
|
|
834
|
+
console.log();
|
|
835
|
+
console.log(' $ locize creaete-branch featureX');
|
|
836
|
+
console.log(' $ locize creaete-branch featureX --ver production');
|
|
837
|
+
console.log(' $ locize creaete-branch featureX --api-key <apiKey> --project-id <projectId> --ver <version>');
|
|
838
|
+
console.log();
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
program
|
|
842
|
+
.command('merge-branch <branch>')
|
|
843
|
+
.alias('mb')
|
|
844
|
+
.description('merge branch')
|
|
845
|
+
.option('-k, --api-key <apiKey>', 'The api-key that should be used')
|
|
846
|
+
.option('-i, --project-id <projectId>', 'The project-id that should be used')
|
|
847
|
+
.option('-d, --delete <true|false>', 'This will delete the branch after merging. (default: false)', 'false')
|
|
848
|
+
.option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
|
|
849
|
+
.action((branch, options) => {
|
|
850
|
+
try {
|
|
851
|
+
config = ini.parse(fs.readFileSync(options.configPath, 'utf-8')) || config;
|
|
852
|
+
} catch (e) {}
|
|
853
|
+
|
|
854
|
+
const apiKey = options.apiKey || config.apiKey || process.env.LOCIZE_API_KEY || process.env.LOCIZE_KEY;
|
|
855
|
+
if (!apiKey) {
|
|
856
|
+
console.error(' error: missing required argument `apiKey`');
|
|
857
|
+
process.exit(1);
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
const projectId = options.projectId || config.projectId || process.env.LOCIZE_PROJECTID || process.env.LOCIZE_PID;
|
|
862
|
+
if (!projectId) {
|
|
863
|
+
console.error(' error: missing required argument `projectId`');
|
|
864
|
+
process.exit(1);
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
const getPath = options.getPath || config.getPath || options.addPath || config.addPath || getPathUrl;
|
|
869
|
+
|
|
870
|
+
mergeBranch({
|
|
871
|
+
apiKey: apiKey,
|
|
872
|
+
projectId: projectId,
|
|
873
|
+
apiPath: url.parse(getPath).protocol + '//' + url.parse(getPath).host,
|
|
874
|
+
delete: options.delete === 'true',
|
|
875
|
+
branch: branch
|
|
876
|
+
});
|
|
877
|
+
})
|
|
878
|
+
.on('--help', () => {
|
|
879
|
+
console.log(' Examples:');
|
|
880
|
+
console.log();
|
|
881
|
+
console.log(' $ locize merge-branch featureX');
|
|
882
|
+
console.log(' $ locize merge-branch <projectId-of-branch>');
|
|
883
|
+
console.log(' $ locize merge-branch featureX --delete true');
|
|
884
|
+
console.log(' $ locize merge-branch featureX --api-key <apiKey> --project-id <projectId> --delete true');
|
|
885
|
+
console.log();
|
|
886
|
+
});
|
|
780
887
|
|
|
781
888
|
program.parse(process.argv);
|
|
782
889
|
|
package/copyVersion.js
CHANGED
|
@@ -3,7 +3,12 @@ const request = require('./request');
|
|
|
3
3
|
const getJob = require('./getJob');
|
|
4
4
|
|
|
5
5
|
const copyVersion = (opt, cb) => {
|
|
6
|
-
|
|
6
|
+
const queryParams = new URLSearchParams();
|
|
7
|
+
if (opt.ignoreIfVersionExists) {
|
|
8
|
+
queryParams.append('ignoreIfVersionExists', 'true');
|
|
9
|
+
}
|
|
10
|
+
const queryString = queryParams.size > 0 ? '?' + queryParams.toString() : '';
|
|
11
|
+
request(opt.apiPath + '/copy/' + opt.projectId + '/version/' + opt.fromVersion + '/' + opt.toVersion + queryString, {
|
|
7
12
|
method: 'post',
|
|
8
13
|
headers: {
|
|
9
14
|
'Authorization': opt.apiKey
|
package/createBranch.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const colors = require('colors');
|
|
2
|
+
const request = require('./request');
|
|
3
|
+
|
|
4
|
+
const createBranch = (opt, cb) => {
|
|
5
|
+
request(opt.apiPath + '/branch/create/' + opt.projectId + '/' + opt.version, {
|
|
6
|
+
method: 'post',
|
|
7
|
+
headers: {
|
|
8
|
+
'Authorization': opt.apiKey
|
|
9
|
+
},
|
|
10
|
+
body: { name: opt.branch }
|
|
11
|
+
}, (err, res, obj) => {
|
|
12
|
+
if (err || (obj && (obj.errorMessage || obj.message))) {
|
|
13
|
+
if (!cb) console.log(colors.red('creating branch failed...'));
|
|
14
|
+
|
|
15
|
+
if (err) {
|
|
16
|
+
if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
|
|
17
|
+
if (cb) cb(err);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (obj && (obj.errorMessage || obj.message)) {
|
|
21
|
+
if (!cb) { console.error(colors.red((obj.errorMessage || obj.message))); process.exit(1); }
|
|
22
|
+
if (cb) cb(new Error((obj.errorMessage || obj.message)));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (res.status === 404) {
|
|
27
|
+
if (!cb) { console.error(colors.yellow(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
28
|
+
if (cb) cb(null, null);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (res.status >= 300) {
|
|
32
|
+
if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
33
|
+
if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!cb) console.log(colors.green('creating branch "' + obj.name + '" (' + obj.id + ') successful'));
|
|
37
|
+
if (cb) cb(null, obj);
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
module.exports = createBranch;
|
package/download.js
CHANGED
|
@@ -13,6 +13,8 @@ const formats = require('./formats');
|
|
|
13
13
|
const getProjectStats = require('./getProjectStats');
|
|
14
14
|
const reversedFileExtensionsMap = formats.reversedFileExtensionsMap;
|
|
15
15
|
const locize2xcstrings = require('locize-xcstrings/cjs/locize2xcstrings');
|
|
16
|
+
const getBranches = require('./getBranches');
|
|
17
|
+
const isValidUuid = require('./isValidUuid');
|
|
16
18
|
|
|
17
19
|
function getInfosInUrl(download) {
|
|
18
20
|
const splitted = download.key.split('/');
|
|
@@ -370,25 +372,7 @@ const filterDownloads = (opt, downloads) => {
|
|
|
370
372
|
return filterDownloadsLanguages(opt, downloads);
|
|
371
373
|
};
|
|
372
374
|
|
|
373
|
-
const
|
|
374
|
-
opt.format = opt.format || 'json';
|
|
375
|
-
if (!reversedFileExtensionsMap[opt.format]) {
|
|
376
|
-
return handleError(new Error(`${opt.format} is not a valid format!`), cb);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if (opt.skipEmpty === undefined) opt.skipEmpty = true;
|
|
380
|
-
opt.apiPath = opt.apiPath || 'https://api.locize.app';
|
|
381
|
-
opt.version = opt.version || 'latest';
|
|
382
|
-
opt.languageFolderPrefix = opt.languageFolderPrefix || '';
|
|
383
|
-
opt.path = opt.path || opt.target;
|
|
384
|
-
opt.pathMaskInterpolationPrefix = opt.pathMaskInterpolationPrefix || '{{';
|
|
385
|
-
opt.pathMaskInterpolationSuffix = opt.pathMaskInterpolationSuffix || '}}';
|
|
386
|
-
opt.pathMask = opt.pathMask || `${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}${path.sep}${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`;
|
|
387
|
-
opt.pathMask = opt.pathMask.replace(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`, `${opt.languageFolderPrefix}${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`);
|
|
388
|
-
if (opt.unpublished && !opt.apiKey) {
|
|
389
|
-
return handleError(new Error('Please provide also an api-key!'), cb);
|
|
390
|
-
}
|
|
391
|
-
|
|
375
|
+
const continueToDownload = (opt, cb) => {
|
|
392
376
|
var url = opt.apiPath + '/download/' + opt.projectId;
|
|
393
377
|
|
|
394
378
|
if (opt.namespace && opt.namespace.indexOf(',') > 0 && opt.namespace.indexOf(' ') < 0) {
|
|
@@ -468,4 +452,44 @@ const download = (opt, cb) => {
|
|
|
468
452
|
});
|
|
469
453
|
};
|
|
470
454
|
|
|
455
|
+
const download = (opt, cb) => {
|
|
456
|
+
opt.format = opt.format || 'json';
|
|
457
|
+
if (!reversedFileExtensionsMap[opt.format]) {
|
|
458
|
+
return handleError(new Error(`${opt.format} is not a valid format!`), cb);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (opt.skipEmpty === undefined) opt.skipEmpty = true;
|
|
462
|
+
opt.apiPath = opt.apiPath || 'https://api.locize.app';
|
|
463
|
+
opt.version = opt.version || 'latest';
|
|
464
|
+
opt.languageFolderPrefix = opt.languageFolderPrefix || '';
|
|
465
|
+
opt.path = opt.path || opt.target;
|
|
466
|
+
opt.pathMaskInterpolationPrefix = opt.pathMaskInterpolationPrefix || '{{';
|
|
467
|
+
opt.pathMaskInterpolationSuffix = opt.pathMaskInterpolationSuffix || '}}';
|
|
468
|
+
opt.pathMask = opt.pathMask || `${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}${path.sep}${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`;
|
|
469
|
+
opt.pathMask = opt.pathMask.replace(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`, `${opt.languageFolderPrefix}${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`);
|
|
470
|
+
if (opt.unpublished && !opt.apiKey) {
|
|
471
|
+
return handleError(new Error('Please provide also an api-key!'), cb);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (opt.branch) {
|
|
475
|
+
getBranches(opt, (err, branches) => {
|
|
476
|
+
if (err) return handleError(err, cb);
|
|
477
|
+
|
|
478
|
+
let b;
|
|
479
|
+
if (isValidUuid(opt.branch)) b = branches.find((br) => br.id === opt.branch);
|
|
480
|
+
if (!b) b = branches.find((br) => br.name === opt.branch);
|
|
481
|
+
if (!b) {
|
|
482
|
+
return handleError(new Error(`Branch ${opt.branch} not found!`), cb);
|
|
483
|
+
}
|
|
484
|
+
opt.projectId = b.id;
|
|
485
|
+
opt.version = b.version;
|
|
486
|
+
|
|
487
|
+
continueToDownload(opt, cb);
|
|
488
|
+
});
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
continueToDownload(opt, cb);
|
|
493
|
+
};
|
|
494
|
+
|
|
471
495
|
module.exports = download;
|
package/getBranches.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const colors = require('colors');
|
|
2
|
+
const request = require('./request');
|
|
3
|
+
|
|
4
|
+
const getBranches = (opt, cb) => {
|
|
5
|
+
request(opt.apiPath + '/branches/' + opt.projectId, {
|
|
6
|
+
method: 'get',
|
|
7
|
+
headers: {
|
|
8
|
+
'Authorization': opt.apiKey
|
|
9
|
+
}
|
|
10
|
+
}, (err, res, obj) => {
|
|
11
|
+
if (err || (obj && (obj.errorMessage || obj.message))) {
|
|
12
|
+
if (!cb) console.log(colors.red('getting branches failed...'));
|
|
13
|
+
|
|
14
|
+
if (err) {
|
|
15
|
+
if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
|
|
16
|
+
if (cb) cb(err);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (obj && (obj.errorMessage || obj.message)) {
|
|
20
|
+
if (!cb) { console.error(colors.red((obj.errorMessage || obj.message))); process.exit(1); }
|
|
21
|
+
if (cb) cb(new Error((obj.errorMessage || obj.message)));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (res.status === 404) {
|
|
26
|
+
if (!cb) { console.error(colors.yellow(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
27
|
+
if (cb) cb(null, null);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (res.status >= 300) {
|
|
31
|
+
if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
32
|
+
if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!cb) console.log(colors.green('getting branches successful'));
|
|
36
|
+
if (cb) cb(null, obj);
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
module.exports = getBranches;
|
package/getJob.js
CHANGED
|
@@ -32,7 +32,7 @@ const getJob = (opt, jobId, cb) => {
|
|
|
32
32
|
if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
35
|
-
if (!cb) console.log(colors.green('getting job
|
|
35
|
+
if (!cb) console.log(colors.green('getting job successful'));
|
|
36
36
|
if (cb) cb(null, obj);
|
|
37
37
|
});
|
|
38
38
|
};
|
package/getProjectStats.js
CHANGED
|
@@ -32,7 +32,7 @@ const getProjectStats = (opt, cb) => {
|
|
|
32
32
|
if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
35
|
-
if (!cb) console.log(colors.green('getting project stats
|
|
35
|
+
if (!cb) console.log(colors.green('getting project stats successful'));
|
|
36
36
|
if (cb) cb(null, obj);
|
|
37
37
|
});
|
|
38
38
|
};
|
package/isValidUuid.js
ADDED
package/mergeBranch.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const colors = require('colors');
|
|
2
|
+
const request = require('./request');
|
|
3
|
+
const getBranches = require('./getBranches');
|
|
4
|
+
const isValidUuid = require('./isValidUuid');
|
|
5
|
+
const getJob = require('./getJob');
|
|
6
|
+
|
|
7
|
+
const mergeBranch = (opt, cb) => {
|
|
8
|
+
const queryParams = new URLSearchParams();
|
|
9
|
+
if (opt.delete) {
|
|
10
|
+
queryParams.append('delete', 'true');
|
|
11
|
+
}
|
|
12
|
+
const queryString = queryParams.size > 0 ? '?' + queryParams.toString() : '';
|
|
13
|
+
request(opt.apiPath + '/branch/merge/' + opt.branch + queryString, {
|
|
14
|
+
method: 'post',
|
|
15
|
+
headers: {
|
|
16
|
+
'Authorization': opt.apiKey
|
|
17
|
+
}
|
|
18
|
+
}, (err, res, obj) => {
|
|
19
|
+
if (err || (obj && (obj.errorMessage || obj.message))) {
|
|
20
|
+
if (!cb) console.log(colors.red('merging branch failed...'));
|
|
21
|
+
|
|
22
|
+
if (err) {
|
|
23
|
+
if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
|
|
24
|
+
if (cb) cb(err);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (obj && (obj.errorMessage || obj.message)) {
|
|
28
|
+
if (!cb) { console.error(colors.red((obj.errorMessage || obj.message))); process.exit(1); }
|
|
29
|
+
if (cb) cb(new Error((obj.errorMessage || obj.message)));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (res.status === 404) {
|
|
34
|
+
if (!cb) { console.error(colors.yellow(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
35
|
+
if (cb) cb(null, null);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (res.status >= 300) {
|
|
39
|
+
if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
40
|
+
if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!obj || !obj.jobId) {
|
|
45
|
+
if (!cb) { console.error(colors.red('No jobId! Something went wrong!')); process.exit(1); }
|
|
46
|
+
if (cb) cb(new Error('No jobId! Something went wrong!'));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
(function waitForJob() {
|
|
51
|
+
getJob(opt, obj.jobId, (err, job) => {
|
|
52
|
+
if (err) {
|
|
53
|
+
if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
|
|
54
|
+
if (cb) cb(err);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (job && !job.timeouted) {
|
|
59
|
+
setTimeout(waitForJob, 2000);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (job && job.timeouted) {
|
|
64
|
+
if (!cb) { console.error(colors.red('Job timeouted!')); process.exit(1); }
|
|
65
|
+
if (cb) cb(new Error('Job timeouted!'));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!cb) console.log(colors.green('merging branch successful'));
|
|
70
|
+
if (cb) cb(null);
|
|
71
|
+
});
|
|
72
|
+
})();
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const handleError = (err, cb) => {
|
|
77
|
+
if (!cb && err) {
|
|
78
|
+
console.error(colors.red(err.stack));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
if (cb) cb(err);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
module.exports = (opt, cb) => {
|
|
85
|
+
getBranches(opt, (err, branches) => {
|
|
86
|
+
if (err) return handleError(err, cb);
|
|
87
|
+
|
|
88
|
+
let b;
|
|
89
|
+
if (isValidUuid(opt.branch)) b = branches.find((br) => br.id === opt.branch);
|
|
90
|
+
if (!b) b = branches.find((br) => br.name === opt.branch);
|
|
91
|
+
if (!b) {
|
|
92
|
+
return handleError(new Error(`Branch ${opt.branch} not found!`), cb);
|
|
93
|
+
}
|
|
94
|
+
opt.branch = b.id;
|
|
95
|
+
|
|
96
|
+
mergeBranch(opt, cb);
|
|
97
|
+
});
|
|
98
|
+
};
|
package/package.json
CHANGED
package/sync.js
CHANGED
|
@@ -18,6 +18,8 @@ const deleteNamespace = require('./deleteNamespace');
|
|
|
18
18
|
const getProjectStats = require('./getProjectStats');
|
|
19
19
|
const reversedFileExtensionsMap = formats.reversedFileExtensionsMap;
|
|
20
20
|
const locize2xcstrings = require('locize-xcstrings/cjs/locize2xcstrings');
|
|
21
|
+
const getBranches = require('./getBranches');
|
|
22
|
+
const isValidUuid = require('./isValidUuid');
|
|
21
23
|
|
|
22
24
|
const getDirectories = (srcpath) => {
|
|
23
25
|
return fs.readdirSync(srcpath).filter((file) => {
|
|
@@ -659,6 +661,49 @@ const handleSync = (opt, remoteLanguages, localNamespaces, cb) => {
|
|
|
659
661
|
});
|
|
660
662
|
};
|
|
661
663
|
|
|
664
|
+
const continueToSync = (opt, cb) => {
|
|
665
|
+
console.log(colors.grey('checking remote (locize)...'));
|
|
666
|
+
getRemoteLanguages(opt, (err, remoteLanguages) => {
|
|
667
|
+
if (err) return handleError(err, cb);
|
|
668
|
+
|
|
669
|
+
if (opt.referenceLanguageOnly && opt.language && opt.referenceLanguage !== opt.language) {
|
|
670
|
+
opt.referenceLanguage = opt.language;
|
|
671
|
+
}
|
|
672
|
+
if (opt.referenceLanguageOnly && !opt.language && opt.languages && opt.languages.length > 0 && opt.languages.indexOf(opt.referenceLanguage) < 0) {
|
|
673
|
+
opt.referenceLanguage = opt.languages[0];
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
if (opt.referenceLanguageOnly) {
|
|
677
|
+
console.log(colors.grey(`checking local${opt.path !== process.cwd() ? ` (${opt.path})` : ''} only reference language...`));
|
|
678
|
+
parseLocalReference(opt, (err, localNamespaces) => {
|
|
679
|
+
if (err) return handleError(err, cb);
|
|
680
|
+
|
|
681
|
+
if (!opt.dry && opt.cleanLocalFiles) {
|
|
682
|
+
localNamespaces.forEach((ln) => fs.unlinkSync(ln.path));
|
|
683
|
+
localNamespaces = [];
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
console.log(colors.grey('calculate diffs...'));
|
|
687
|
+
handleSync(opt, remoteLanguages, localNamespaces, cb);
|
|
688
|
+
});
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
console.log(colors.grey(`checking local${opt.path !== process.cwd() ? ` (${opt.path})` : ''}...`));
|
|
693
|
+
parseLocalLanguages(opt, remoteLanguages, (err, localNamespaces) => {
|
|
694
|
+
if (err) return handleError(err, cb);
|
|
695
|
+
|
|
696
|
+
if (!opt.dry && opt.cleanLocalFiles) {
|
|
697
|
+
localNamespaces.forEach((ln) => fs.unlinkSync(ln.path));
|
|
698
|
+
localNamespaces = [];
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
console.log(colors.grey('calculate diffs...'));
|
|
702
|
+
handleSync(opt, remoteLanguages, localNamespaces, cb);
|
|
703
|
+
});
|
|
704
|
+
});
|
|
705
|
+
};
|
|
706
|
+
|
|
662
707
|
const sync = (opt, cb) => {
|
|
663
708
|
opt.format = opt.format || 'json';
|
|
664
709
|
if (!reversedFileExtensionsMap[opt.format]) {
|
|
@@ -695,46 +740,25 @@ const sync = (opt, cb) => {
|
|
|
695
740
|
return handleError(new Error('Please provide also an api-key!'), cb);
|
|
696
741
|
}
|
|
697
742
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
if (err) return handleError(err, cb);
|
|
701
|
-
|
|
702
|
-
if (opt.referenceLanguageOnly && opt.language && opt.referenceLanguage !== opt.language) {
|
|
703
|
-
opt.referenceLanguage = opt.language;
|
|
704
|
-
}
|
|
705
|
-
if (opt.referenceLanguageOnly && !opt.language && opt.languages && opt.languages.length > 0 && opt.languages.indexOf(opt.referenceLanguage) < 0) {
|
|
706
|
-
opt.referenceLanguage = opt.languages[0];
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
if (opt.referenceLanguageOnly) {
|
|
710
|
-
console.log(colors.grey(`checking local${opt.path !== process.cwd() ? ` (${opt.path})` : ''} only reference language...`));
|
|
711
|
-
parseLocalReference(opt, (err, localNamespaces) => {
|
|
712
|
-
if (err) return handleError(err, cb);
|
|
713
|
-
|
|
714
|
-
if (!opt.dry && opt.cleanLocalFiles) {
|
|
715
|
-
localNamespaces.forEach((ln) => fs.unlinkSync(ln.path));
|
|
716
|
-
localNamespaces = [];
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
console.log(colors.grey('calculate diffs...'));
|
|
720
|
-
handleSync(opt, remoteLanguages, localNamespaces, cb);
|
|
721
|
-
});
|
|
722
|
-
return;
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
console.log(colors.grey(`checking local${opt.path !== process.cwd() ? ` (${opt.path})` : ''}...`));
|
|
726
|
-
parseLocalLanguages(opt, remoteLanguages, (err, localNamespaces) => {
|
|
743
|
+
if (opt.branch) {
|
|
744
|
+
getBranches(opt, (err, branches) => {
|
|
727
745
|
if (err) return handleError(err, cb);
|
|
728
746
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
747
|
+
let b;
|
|
748
|
+
if (isValidUuid(opt.branch)) b = branches.find((br) => br.id === opt.branch);
|
|
749
|
+
if (!b) b = branches.find((br) => br.name === opt.branch);
|
|
750
|
+
if (!b) {
|
|
751
|
+
return handleError(new Error(`Branch ${opt.branch} not found!`), cb);
|
|
732
752
|
}
|
|
753
|
+
opt.projectId = b.id;
|
|
754
|
+
opt.version = b.version;
|
|
733
755
|
|
|
734
|
-
|
|
735
|
-
handleSync(opt, remoteLanguages, localNamespaces, cb);
|
|
756
|
+
continueToSync(opt, cb);
|
|
736
757
|
});
|
|
737
|
-
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
continueToSync(opt, cb);
|
|
738
762
|
};
|
|
739
763
|
|
|
740
764
|
module.exports = sync;
|