Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

accent-cli

Package Overview
Dependencies
Maintainers
2
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

accent-cli - npm Package Compare versions

Comparing version 0.14.2 to 0.15.0

lib/types/version-config.d.ts

2

.oclif.manifest.json

@@ -1,1 +0,1 @@

{"version":"0.14.2","commands":{"export":{"id":"export","description":"Export files from Accent and write them to your local filesystem","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent export","$ accent export --order-by=key --version=build.myapp.com:0.12.345"],"flags":{"order-by":{"name":"order-by","type":"option","description":"Order of the keys","options":["index","key"],"default":"index"},"version":{"name":"version","type":"option","description":"Fetch a specific version","default":""},"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[]},"format":{"id":"format","description":"Format local files from server. Exit code is 1 if there are errors.","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent format"],"flags":{"order-by":{"name":"order-by","type":"option","description":"Order of the keys","options":["index","key","-index","-key"],"default":"index"},"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[]},"jipt":{"id":"jipt","description":"Export jipt files from Accent and write them to your local filesystem","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent jipt"],"flags":{"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[{"name":"pseudoLanguageName","description":"The pseudo language for in-place-translation-editing","required":true}]},"lint":{"id":"lint","description":"Lint local files and display errors if any. Exit code is 1 if there are errors.","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent lint"],"flags":{"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[]},"stats":{"id":"stats","description":"Fetch stats from the API and display it beautifully","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent stats"],"flags":{"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[]},"sync":{"id":"sync","description":"Sync files in Accent and write them to your local filesystem","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent sync","$ accent sync --dry-run --sync-type=force","$ accent sync --add-translations --merge-type=smart --order-key=key --version=v0.23"],"flags":{"add-translations":{"name":"add-translations","type":"boolean","description":"Add translations in Accent to help translators if you already have translated strings locally","allowNo":false},"dry-run":{"name":"dry-run","type":"boolean","description":"Do not write the file from the export _after_ the operation","allowNo":false},"merge-type":{"name":"merge-type","type":"option","description":"Algorithm to use on existing strings when adding translation","options":["smart","passive","force"],"default":"passive"},"order-by":{"name":"order-by","type":"option","description":"Will be used in the export call as the order of the keys","options":["index","key"],"default":"index"},"sync-type":{"name":"sync-type","type":"option","description":"Algorithm to use on existing strings when syncing the main language","options":["smart","passive"],"default":"smart"},"version":{"name":"version","type":"option","description":"Sync a specific version, the tag needs to exists in Accent first","default":""},"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[]}}}
{"version":"0.15.0","commands":{"export":{"id":"export","description":"Export files from Accent and write them to your local filesystem","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent export","$ accent export --order-by=key --version=build.myapp.com:0.12.345"],"flags":{"order-by":{"name":"order-by","type":"option","description":"Order of the keys","options":["index","key"],"default":"index"},"version":{"name":"version","type":"option","description":"Fetch a specific version","default":""},"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[]},"format":{"id":"format","description":"Format local files from server. Exit code is 1 if there are errors.","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent format"],"flags":{"order-by":{"name":"order-by","type":"option","description":"Order of the keys","options":["index","key","-index","-key"],"default":"index"},"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[]},"jipt":{"id":"jipt","description":"Export jipt files from Accent and write them to your local filesystem","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent jipt"],"flags":{"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[{"name":"pseudoLanguageName","description":"The pseudo language for in-place-translation-editing","required":true}]},"lint":{"id":"lint","description":"Lint local files and display errors if any. Exit code is 1 if there are errors.","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent lint"],"flags":{"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[]},"stats":{"id":"stats","description":"Fetch stats from the API and display them beautifully","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent stats"],"flags":{"version":{"name":"version","type":"option","description":"View stats for a specific version"},"check-reviewed":{"name":"check-reviewed","type":"boolean","description":"Exit 1 when reviewed percentage is not 100%","allowNo":false},"check-translated":{"name":"check-translated","type":"boolean","description":"Exit 1 when translated percentage is not 100%","allowNo":false},"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[]},"sync":{"id":"sync","description":"Sync files in Accent and write them to your local filesystem","pluginName":"accent-cli","pluginType":"core","aliases":[],"examples":["$ accent sync","$ accent sync --dry-run --sync-type=force","$ accent sync --add-translations --merge-type=smart --order-key=key --version=v0.23"],"flags":{"add-translations":{"name":"add-translations","type":"boolean","description":"Add translations in Accent to help translators if you already have translated strings locally","allowNo":false},"dry-run":{"name":"dry-run","type":"boolean","description":"Do not write the file from the export _after_ the operation","allowNo":false},"merge-type":{"name":"merge-type","type":"option","description":"Algorithm to use on existing strings when adding translation","options":["smart","passive","force"],"default":"passive"},"order-by":{"name":"order-by","type":"option","description":"Will be used in the export call as the order of the keys","options":["index","key"],"default":"index"},"sync-type":{"name":"sync-type","type":"option","description":"Algorithm to use on existing strings when syncing the main language","options":["smart","passive"],"default":"smart"},"version":{"name":"version","type":"option","description":"Sync a specific version, the tag needs to exists in Accent first","default":""},"config":{"name":"config","type":"option","description":"Path to the config file","default":"accent.json"}},"args":[]}}}

@@ -0,1 +1,2 @@

import { flags } from '@oclif/command';
import Command from '../base';

@@ -6,5 +7,8 @@ export default class Stats extends Command {

static flags: {
config: import("@oclif/command/lib/flags").IOptionFlag<string>;
version: flags.IOptionFlag<string | undefined>;
'check-reviewed': import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
'check-translated': import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
config: flags.IOptionFlag<string>;
};
run(): Promise<void>;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// Vendor
const chalk = require("chalk");
// Command
const command_1 = require("@oclif/command");
const base_1 = require("../base");
const errors_1 = require("@oclif/errors");
// Services
const project_stats_1 = require("../services/formatters/project-stats");
const project_fetcher_1 = require("../services/project-fetcher");
class Stats extends base_1.default {
/* eslint-disable @typescript-eslint/require-await */
async run() {
const formatter = new project_stats_1.default(this.project, this.projectConfig.config);
const { flags } = this.parse(Stats);
if (this.projectConfig.config.version?.tag && !flags.version) {
flags.version = this.projectConfig.config.version.tag;
}
if (flags.version) {
const config = this.projectConfig.config;
const fetcher = new project_fetcher_1.default();
const response = await fetcher.fetch(config, { versionId: flags.version });
this.project = response.project;
}
const formatter = new project_stats_1.default(this.project, this.projectConfig.config, flags.version);
formatter.log();
if (flags['check-reviewed']) {
const conflictsCount = this.project.revisions.reduce((memo, revision) => memo + revision.conflictsCount, 0);
if (conflictsCount !== 0) {
const versionFormat = flags.version ? ` ${flags.version}` : '';
throw new errors_1.CLIError(chalk.red(`Project${versionFormat} has ${conflictsCount} strings to be reviewed`), { exit: 1 });
}
}
if (flags['check-translated']) {
const translatedCount = this.project.revisions.reduce((memo, revision) => memo + revision.translatedCount, 0);
const translationsCount = this.project.revisions.reduce((memo, revision) => memo + revision.translationsCount, 0);
if (translationsCount - translatedCount !== 0) {
const versionFormat = flags.version ? ` ${flags.version}` : '';
throw new errors_1.CLIError(chalk.red(`Project${versionFormat} has ${translatedCount} strings to be translated`), { exit: 1 });
}
}
}
}
exports.default = Stats;
Stats.description = 'Fetch stats from the API and display it beautifully';
Stats.description = 'Fetch stats from the API and display them beautifully';
Stats.examples = [`$ accent stats`];
Stats.flags = { config: base_1.configFlag };
Stats.flags = {
version: command_1.flags.string({
default: undefined,
description: 'View stats for a specific version',
}),
'check-reviewed': command_1.flags.boolean({
description: 'Exit 1 when reviewed percentage is not 100%',
}),
'check-translated': command_1.flags.boolean({
description: 'Exit 1 when translated percentage is not 100%',
}),
config: base_1.configFlag,
};

@@ -24,2 +24,5 @@ "use strict";

const documents = this.projectConfig.files();
if (this.projectConfig.config.version?.tag && !flags.version) {
flags.version = this.config.version;
}
// From all the documentConfigs, do the sync or peek operations and log the results.

@@ -26,0 +29,0 @@ const syncFormatter = new project_sync_1.default();

@@ -9,2 +9,4 @@ import Document from './document';

private sourceFolderPath;
private getCurrentBranchName;
private extractVersionFromBranch;
}

@@ -5,2 +5,3 @@ "use strict";

const errors_1 = require("@oclif/errors");
const child_process_1 = require("child_process");
const fs = require("fs-extra");

@@ -27,2 +28,6 @@ const path = require("path");

}
if (this.config.version?.branchVersionPrefix &&
this.getCurrentBranchName().startsWith(this.config.version?.branchVersionPrefix)) {
this.config.version.tag = this.extractVersionFromBranch(this.getCurrentBranchName(), this.config.version?.branchVersionPrefix);
}
const sameFolderPathWarning = new Set();

@@ -48,3 +53,16 @@ this.config.files.forEach((documentConfig) => {

}
getCurrentBranchName() {
try {
return (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD')
.toString('utf8')
.replace(/[\n\r\s]+$/, '');
}
catch {
return '';
}
}
extractVersionFromBranch(branchName, gitBranchVersionMatch) {
return branchName.replace(gitBranchVersionMatch, '');
}
}
exports.default = ConfigFetcher;

@@ -7,4 +7,6 @@ import { Config } from '../../types/config';

private readonly config;
constructor(project: Project, config: Config);
private readonly version;
constructor(project: Project, config: Config, version?: string);
percentageReviewedString(number: number, translationsCount: number): string;
log(): void;
}

@@ -8,23 +8,27 @@ "use strict";

const base_1 = require("./base");
const TITLE_LENGTH_PADDING = 4;
class ProjectStatsFormatter extends base_1.default {
constructor(project, config) {
constructor(project, config, version) {
super();
this.project = project;
this.config = config;
this.version = version;
}
log() {
const translationsCount = this.project.revisions.reduce((memo, revision) => memo + revision.translationsCount, 0);
const conflictsCount = this.project.revisions.reduce((memo, revision) => memo + revision.conflictsCount, 0);
const reviewedCount = this.project.revisions.reduce((memo, revision) => memo + revision.reviewedCount, 0);
const percentageReviewed = translationsCount > 0 ? reviewedCount / translationsCount : 0;
const percentageReviewedString = `${percentageReviewed}% reviewed`;
percentageReviewedString(number, translationsCount) {
const prettyFloat = (number) => {
if (number.endsWith('.00')) {
return parseInt(number, 10).toString();
}
else {
return number;
}
};
const percentageReviewedString = `${prettyFloat(number.toFixed(2))}% reviewed`;
let percentageReviewedFormat = chalk.green(percentageReviewedString);
if (percentageReviewed === 100) {
if (number === 100) {
percentageReviewedFormat = chalk.green(percentageReviewedString);
}
else if (percentageReviewed > 100 / 2) {
else if (number > 100 / 2) {
percentageReviewedFormat = chalk.yellow(percentageReviewedString);
}
else if (percentageReviewed <= 0 && translationsCount === 0) {
else if (number <= 0 && translationsCount === 0) {
percentageReviewedFormat = chalk.dim('No strings');

@@ -35,10 +39,13 @@ }

}
console.log(this.project.logo
? this.project.logo
: chalk.bgGreenBright.black.bold(' ^ '), chalk.white.bold(this.project.name), chalk.dim(' • '), percentageReviewedFormat);
const titleLength = (this.project.logo ? this.project.logo.length + 1 : 0) +
this.project.name.length +
percentageReviewedString.length +
TITLE_LENGTH_PADDING;
console.log(chalk.gray.dim('⎯'.repeat(titleLength)));
return percentageReviewedFormat;
}
log() {
const translationsCount = this.project.revisions.reduce((memo, revision) => memo + revision.translationsCount, 0);
const translatedCount = this.project.revisions.reduce((memo, revision) => memo + revision.translatedCount, 0);
const conflictsCount = this.project.revisions.reduce((memo, revision) => memo + revision.conflictsCount, 0);
const reviewedCount = this.project.revisions.reduce((memo, revision) => memo + revision.reviewedCount, 0);
const percentageReviewed = translationsCount > 0 ? (reviewedCount / translationsCount) * 100 : 0;
const percentageReviewedFormat = this.percentageReviewedString(percentageReviewed, translationsCount);
console.log(this.project.logo ? this.project.logo : chalk.bgGreen.black.bold(' ^ '), chalk.whiteBright.bold(this.project.name), chalk.dim(' • '), percentageReviewedFormat);
console.log(chalk.gray.dim('⎯'));
console.log(chalk.magenta('Last synced'));

@@ -59,14 +66,4 @@ if (this.project.lastSyncedAt) {

if (this.project.masterRevision.id !== revision.id) {
const percentageReviewed = revision.reviewedCount / revision.translationsCount;
const percentageReviewedString = `${percentageReviewed}% reviewed`;
let percentageReviewedFormat = chalk.green(percentageReviewedString);
if (percentageReviewed === 100) {
percentageReviewedFormat = chalk.green(percentageReviewedString);
}
else if (percentageReviewed > 100 / 2) {
percentageReviewedFormat = chalk.yellow(percentageReviewedString);
}
else {
percentageReviewedFormat = chalk.red(percentageReviewedString);
}
const percentageReviewed = (revision.reviewedCount / revision.translationsCount) * 100;
const percentageReviewedFormat = this.percentageReviewedString(percentageReviewed, translationsCount);
console.log(`${chalk.white.bold((0, revision_slug_fetcher_1.fetchNameFromRevision)(revision))} – ${(0, revision_slug_fetcher_1.fetchFromRevision)(revision)}`, chalk.dim('•'), percentageReviewedFormat);

@@ -88,10 +85,15 @@ }

this.project.versions.entries.forEach((version) => {
console.log(chalk.bgBlack.white(` ${version.tag} `));
if (version.tag === this.version) {
console.log(chalk.bgBlack.whiteBright(` ${version.tag} `));
}
else {
console.log(chalk.white(`${version.tag}`));
}
});
console.log('');
}
console.log(chalk.magenta('Strings'));
console.log(chalk.white('# Strings:'), chalk.white(`${translationsCount}`));
console.log(chalk.magenta(`Strings (${translationsCount})`));
console.log(chalk.green('✓ Reviewed:'), chalk.green(`${reviewedCount}`));
console.log(chalk.red('× In review:'), chalk.red(`${conflictsCount}`));
console.log(chalk.white('✎ Translated:'), chalk.white(`${translatedCount}`));
console.log('');

@@ -98,0 +100,0 @@ const owners = this.project.collaborators.filter(({ role }) => role === 'OWNER');

import { Config } from '../types/config';
import { ProjectViewer } from '../types/project';
export default class ProjectFetcher {
fetch(config: Config): Promise<ProjectViewer>;
fetch(config: Config, params?: object): Promise<ProjectViewer>;
private graphql;
}

@@ -8,4 +8,4 @@ "use strict";

class ProjectFetcher {
async fetch(config) {
const response = await this.graphql(config);
async fetch(config, params) {
const response = await this.graphql(config, params || {});
try {

@@ -22,4 +22,4 @@ const data = (await response.json());

}
async graphql(config) {
const query = `query ProjectDetails($project_id: ID!) {
async graphql(config, params) {
const query = `query ProjectDetails($project_id: ID! $versionId: ID) {
viewer {

@@ -80,5 +80,6 @@ user {

revisions {
revisions(versionId: $versionId) {
id
isMaster
translatedCount
translationsCount

@@ -99,3 +100,4 @@ conflictsCount

// eslint-disable-next-line camelcase
const variables = config.project ? { project_id: config.project } : {};
const configParams = config.project ? { project_id: config.project } : {};
const variables = { ...configParams, ...params };
return await (0, node_fetch_1.default)(`${config.apiUrl}/graphql`, {

@@ -102,0 +104,0 @@ body: JSON.stringify({ query, variables }),

import { DocumentConfig } from './document-config';
import { VersionConfig } from './version-config';
export interface Config {
apiUrl: string;
apiKey: string;
project: string | null | undefined;
project?: string | null;
version?: VersionConfig;
files: DocumentConfig[];
}

@@ -12,2 +12,3 @@ export interface Language {

isMaster: boolean;
translatedCount: number;
translationsCount: number;

@@ -14,0 +15,0 @@ conflictsCount: number;

{
"name": "accent-cli",
"version": "0.14.2",
"version": "0.15.0",
"author": "Simon Prévost",

@@ -5,0 +5,0 @@ "description": "Accent CLI",

@@ -23,3 +23,3 @@ Accent CLI

$ accent (-v|--version|version)
accent-cli/0.14.2 darwin-arm64 node-v16.15.1
accent-cli/0.15.0 darwin-arm64 node-v16.19.1
$ accent --help [COMMAND]

@@ -42,2 +42,5 @@ USAGE

"apiKey": "2nziVSaa8yUJxLkwoZA",
"version": {
"branchVersionPrefix": "release/"
}
"files": [

@@ -70,2 +73,6 @@ {

Version object configuration
- `branchVersionPrefix`: The Git branch prefix use to extract the file version
Each operation section `sync` and `addTranslations` can contain the following object:

@@ -136,2 +143,14 @@

## Version
Version can be extracted from the current Git branch name.
```
"version": {
"branchVersionPrefix": "release/"
}
```
Naming a branch `release/v1.0.0` will cause the `sync` and `stats` CLI commands to be invoked as if `--version=1.0.0` had been specified.
# Commands

@@ -165,3 +184,3 @@ <!-- commands -->

_See code: [src/commands/export.ts](https://github.com/mirego/accent/blob/v0.14.2/src/commands/export.ts)_
_See code: [src/commands/export.ts](https://github.com/mirego/accent/blob/v0.15.0/src/commands/export.ts)_

@@ -184,3 +203,3 @@ ## `accent format`

_See code: [src/commands/format.ts](https://github.com/mirego/accent/blob/v0.14.2/src/commands/format.ts)_
_See code: [src/commands/format.ts](https://github.com/mirego/accent/blob/v0.15.0/src/commands/format.ts)_

@@ -222,3 +241,3 @@ ## `accent help [COMMAND]`

_See code: [src/commands/jipt.ts](https://github.com/mirego/accent/blob/v0.14.2/src/commands/jipt.ts)_
_See code: [src/commands/jipt.ts](https://github.com/mirego/accent/blob/v0.15.0/src/commands/jipt.ts)_

@@ -240,7 +259,7 @@ ## `accent lint`

_See code: [src/commands/lint.ts](https://github.com/mirego/accent/blob/v0.14.2/src/commands/lint.ts)_
_See code: [src/commands/lint.ts](https://github.com/mirego/accent/blob/v0.15.0/src/commands/lint.ts)_
## `accent stats`
Fetch stats from the API and display it beautifully
Fetch stats from the API and display them beautifully

@@ -252,3 +271,6 @@ ```

OPTIONS
--config=config [default: accent.json] Path to the config file
--check-reviewed Exit 1 when reviewed percentage is not 100%
--check-translated Exit 1 when translated percentage is not 100%
--config=config [default: accent.json] Path to the config file
--version=version View stats for a specific version

@@ -259,3 +281,3 @@ EXAMPLE

_See code: [src/commands/stats.ts](https://github.com/mirego/accent/blob/v0.14.2/src/commands/stats.ts)_
_See code: [src/commands/stats.ts](https://github.com/mirego/accent/blob/v0.15.0/src/commands/stats.ts)_

@@ -292,3 +314,3 @@ ## `accent sync`

_See code: [src/commands/sync.ts](https://github.com/mirego/accent/blob/v0.14.2/src/commands/sync.ts)_
_See code: [src/commands/sync.ts](https://github.com/mirego/accent/blob/v0.15.0/src/commands/sync.ts)_
<!-- commandsstop -->

@@ -337,3 +359,2 @@

`accent-cli` is © 2019 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/accent-cli/blob/master/LICENSE.md) file.
# About Mirego

@@ -340,0 +361,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc