locize-cli 10.0.3 → 10.1.1
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 +110 -7
- package/createBranch.js +61 -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.1](https://github.com/locize/locize-cli/compare/v10.1.0...v10.1.1) - 2025-07-12
|
|
9
|
+
|
|
10
|
+
- create-branch: nicer feedback, if branch already exists
|
|
11
|
+
|
|
12
|
+
## [10.1.0](https://github.com/locize/locize-cli/compare/v10.0.3...v10.1.0) - 2025-07-10
|
|
13
|
+
|
|
14
|
+
- introduce branching features
|
|
15
|
+
|
|
8
16
|
## [10.0.3](https://github.com/locize/locize-cli/compare/v10.0.2...v10.0.3) - 2025-07-09
|
|
9
17
|
|
|
10
18
|
- introduce `--ignore-if-version-exists` option for `copy-version`
|
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', () => {
|
|
@@ -591,8 +600,8 @@ program
|
|
|
591
600
|
.on('--help', () => {
|
|
592
601
|
console.log(' Examples:');
|
|
593
602
|
console.log();
|
|
594
|
-
console.log(' $ locize copy-version latest
|
|
595
|
-
console.log(' $ locize copy-version latest --ver production
|
|
603
|
+
console.log(' $ locize copy-version latest');
|
|
604
|
+
console.log(' $ locize copy-version latest --ver production');
|
|
596
605
|
console.log(' $ locize copy-version latest --api-key <apiKey> --project-id <projectId> --ver <version>');
|
|
597
606
|
console.log();
|
|
598
607
|
});
|
|
@@ -635,7 +644,7 @@ program
|
|
|
635
644
|
.on('--help', () => {
|
|
636
645
|
console.log(' Examples:');
|
|
637
646
|
console.log();
|
|
638
|
-
console.log(' $ locize remove-version tmp-ver
|
|
647
|
+
console.log(' $ locize remove-version tmp-ver');
|
|
639
648
|
console.log(' $ locize remove-version tmp-ver --api-key <apiKey> --project-id <projectId>');
|
|
640
649
|
console.log();
|
|
641
650
|
});
|
|
@@ -685,8 +694,8 @@ program
|
|
|
685
694
|
.on('--help', () => {
|
|
686
695
|
console.log(' Examples:');
|
|
687
696
|
console.log();
|
|
688
|
-
console.log(' $ locize publish-version
|
|
689
|
-
console.log(' $ locize publish-version --ver production
|
|
697
|
+
console.log(' $ locize publish-version');
|
|
698
|
+
console.log(' $ locize publish-version --ver production');
|
|
690
699
|
console.log(' $ locize publish-version --api-key <apiKey> --project-id <projectId> --ver <version>');
|
|
691
700
|
console.log();
|
|
692
701
|
});
|
|
@@ -781,6 +790,100 @@ program
|
|
|
781
790
|
console.log();
|
|
782
791
|
});
|
|
783
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
|
+
});
|
|
784
887
|
|
|
785
888
|
program.parse(process.argv);
|
|
786
889
|
|
package/createBranch.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const colors = require('colors');
|
|
2
|
+
const request = require('./request');
|
|
3
|
+
const getBranches = require('./getBranches');
|
|
4
|
+
|
|
5
|
+
const handleError = (err, cb) => {
|
|
6
|
+
if (!cb && err) {
|
|
7
|
+
console.error(colors.red(err.stack));
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
if (cb) cb(err);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const createBranch = (opt, cb) => {
|
|
14
|
+
getBranches(opt, (err, branches) => {
|
|
15
|
+
if (err) return handleError(err, cb);
|
|
16
|
+
|
|
17
|
+
const b = branches.find((br) => br.name === opt.branch);
|
|
18
|
+
if (b) {
|
|
19
|
+
if (!cb) console.log(colors.green('creating branch "' + b.name + '" (' + b.id + ') not necessary, because already existing'));
|
|
20
|
+
if (cb) cb(null, b);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
request(opt.apiPath + '/branch/create/' + opt.projectId + '/' + opt.version, {
|
|
25
|
+
method: 'post',
|
|
26
|
+
headers: {
|
|
27
|
+
'Authorization': opt.apiKey
|
|
28
|
+
},
|
|
29
|
+
body: { name: opt.branch }
|
|
30
|
+
}, (err, res, obj) => {
|
|
31
|
+
if (err || (obj && (obj.errorMessage || obj.message))) {
|
|
32
|
+
if (!cb) console.log(colors.red('creating branch failed...'));
|
|
33
|
+
|
|
34
|
+
if (err) {
|
|
35
|
+
if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
|
|
36
|
+
if (cb) cb(err);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (obj && (obj.errorMessage || obj.message)) {
|
|
40
|
+
if (!cb) { console.error(colors.red((obj.errorMessage || obj.message))); process.exit(1); }
|
|
41
|
+
if (cb) cb(new Error((obj.errorMessage || obj.message)));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (res.status === 404) {
|
|
46
|
+
if (!cb) { console.error(colors.yellow(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
47
|
+
if (cb) cb(null, null);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (res.status >= 300) {
|
|
51
|
+
if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
52
|
+
if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (!cb) console.log(colors.green('creating branch "' + obj.name + '" (' + obj.id + ') successful'));
|
|
56
|
+
if (cb) cb(null, obj);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
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;
|