Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: sync & compare commands #16

Merged
merged 10 commits into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"author": "Jan Cizmar",
"license": "MIT",
"dependencies": {
"ansi-colors": "^4.1.3",
"base32-decode": "^1.0.0",
"commander": "^9.4.0",
"cosmiconfig": "^7.0.1",
Expand Down
3 changes: 3 additions & 0 deletions src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { components } from './internal/schema.generated';
import base32Decode from 'base32-decode';
import Requester from './internal/requester';

import ProjectClient from './project';
import LanguagesClient from './languages';
import ImportClient from './import';
import ExportClient from './export';
Expand Down Expand Up @@ -33,13 +34,15 @@ export type ApiKeyInfo = ApiKeyInfoPat | ApiKeyInfoPak;

export default class RestClient {
private requester: Requester;
readonly project: ProjectClient;
readonly languages: LanguagesClient;
readonly import: ImportClient;
readonly export: ExportClient;

constructor(private params: RequesterParams) {
this.requester = new Requester(params);

this.project = new ProjectClient(this.requester);
this.languages = new LanguagesClient(this.requester);
this.import = new ImportClient(this.requester);
this.export = new ExportClient(this.requester);
Expand Down
76 changes: 66 additions & 10 deletions src/client/internal/schema.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ export interface paths {
get: operations['getAll'];
post: operations['createProject'];
};
'/v2/projects/{projectId}/keys/import': {
post: operations['importKeys'];
};
'/v2/projects/{projectId}/keys/create': {
post: operations['create'];
};
Expand Down Expand Up @@ -956,11 +959,11 @@ export interface components {
/** Format: int64 */
lastUsedAt?: number;
/** Format: int64 */
expiresAt?: number;
/** Format: int64 */
createdAt: number;
/** Format: int64 */
updatedAt: number;
/** Format: int64 */
expiresAt?: number;
description: string;
};
SetOrganizationRoleDto: {
Expand Down Expand Up @@ -1079,12 +1082,12 @@ export interface components {
projectName: string;
scopes: string[];
/** Format: int64 */
lastUsedAt?: number;
/** Format: int64 */
projectId: number;
/** Format: int64 */
expiresAt?: number;
lastUsedAt?: number;
username?: string;
/** Format: int64 */
expiresAt?: number;
description: string;
};
SuperTokenRequest: {
Expand All @@ -1110,6 +1113,26 @@ export interface components {
/** @description Tag of one of created languages, to select it as base language. If not provided, first language will be selected as base. */
baseLanguageTag?: string;
};
ImportKeysDto: {
keys: components['schemas']['ImportKeysItemDto'][];
};
ImportKeysItemDto: {
/**
* @description Key name to set translations for
* @example what_a_key_to_translate
*/
name: string;
/** @description The namespace of the key. (When empty or null default namespace will be used) */
namespace?: string;
/**
* @description Object mapping language tag to translation
* @example {
* "en": "What a translated value!",
* "cs": "Jaká to přeložená hodnota!"
* }
*/
translations: { [key: string]: string };
};
CreateKeyDto: {
/** @description Name of the key */
name: string;
Expand Down Expand Up @@ -1363,6 +1386,7 @@ export interface components {
recaptchaSiteKey?: string;
openReplayApiKey?: string;
chatwootToken?: string;
capterraTracker?: string;
};
PagedModelProjectModel: {
_embedded?: {
Expand Down Expand Up @@ -1880,11 +1904,11 @@ export interface components {
/** Format: int64 */
lastUsedAt?: number;
/** Format: int64 */
expiresAt?: number;
/** Format: int64 */
createdAt: number;
/** Format: int64 */
updatedAt: number;
/** Format: int64 */
expiresAt?: number;
description: string;
};
OrganizationRequestParamsDto: {
Expand Down Expand Up @@ -1968,12 +1992,12 @@ export interface components {
projectName: string;
scopes: string[];
/** Format: int64 */
lastUsedAt?: number;
/** Format: int64 */
projectId: number;
/** Format: int64 */
expiresAt?: number;
lastUsedAt?: number;
username?: string;
/** Format: int64 */
expiresAt?: number;
description: string;
};
PagedModelUserAccountModel: {
Expand Down Expand Up @@ -4059,6 +4083,34 @@ export interface operations {
};
};
};
importKeys: {
parameters: {
path: {
projectId: number;
};
};
responses: {
/** OK */
200: unknown;
/** Bad Request */
400: {
content: {
'*/*': string;
};
};
/** Not Found */
404: {
content: {
'*/*': string;
};
};
};
requestBody: {
content: {
'application/json': components['schemas']['ImportKeysDto'];
};
};
};
create: {
parameters: {
path: {
Expand Down Expand Up @@ -4154,6 +4206,10 @@ export interface operations {
/** Prepares provided files to import. */
addFiles: {
parameters: {
query: {
/** When importing structured JSONs, you can set the delimiter which will be used in names of improted keys. */
structureDelimiter?: string;
};
path: {
projectId: number;
};
Expand Down
74 changes: 74 additions & 0 deletions src/client/project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type { ResponseOf, BodyOf } from './internal/schema.utils';

import Requester from './internal/requester';

type ResponseAllKeys = ResponseOf<
'/v2/projects/{projectId}/all-keys',
'get'
>[200];

export type ProjectInformation = ResponseOf<
'/v2/projects/{projectId}',
'get'
>[200];

export type AllKeys = Exclude<
Exclude<ResponseAllKeys['_embedded'], undefined>['keys'],
undefined
>;

export type CreateKeyPayload = BodyOf<'/v2/projects/{projectId}/keys', 'post'>;

export type CreateKeysPayload = BodyOf<
'/v2/projects/{projectId}/keys/import',
'post'
>['keys'];

export type CreateKeyResponse = ResponseOf<
'/v2/projects/{projectId}/keys',
'post'
>[201];

export default class ProjectClient {
constructor(private requester: Requester) {}

async fetchProjectInformation(): Promise<ProjectInformation> {
return this.requester.requestJson({
method: 'GET',
path: this.requester.projectUrl,
});
}

async fetchAllKeys(): Promise<AllKeys> {
return this.requester
.requestJson({
method: 'GET',
path: `${this.requester.projectUrl}/all-keys`,
})
.then((r: any) => r._embedded?.keys || []);
}

async createKey(key: CreateKeyPayload): Promise<CreateKeyResponse> {
return this.requester.requestJson({
method: 'POST',
path: `${this.requester.projectUrl}/keys`,
body: key,
});
}

async createBulkKey(keys: CreateKeysPayload): Promise<void> {
return this.requester.requestVoid({
method: 'POST',
path: `${this.requester.projectUrl}/keys/import`,
body: { keys },
});
}

async deleteBulkKeys(keyIds: number[]): Promise<void> {
return this.requester.requestVoid({
method: 'DELETE',
path: `${this.requester.projectUrl}/keys`,
body: { ids: keyIds },
});
}
}
9 changes: 2 additions & 7 deletions src/commands/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,14 @@ import { Command } from 'commander';

import extractPrint from './extract/print';
import extractCheck from './extract/check';
import { SDKS } from '../constants';
import { EXTRACTOR } from '../options';

export type BaseExtractOptions = {
extractor: string;
};

export default new Command('extract')
.description('Extracts strings from your projects')
.requiredOption(
'-e, --extractor <extractor>',
`The extractor to use. Either one of the builtins (${SDKS.join(
', '
)}), or a path to a JS/TS file with a custom extractor.`
)
.addOption(EXTRACTOR)
cyyynthia marked this conversation as resolved.
Show resolved Hide resolved
.addCommand(extractPrint)
.addCommand(extractCheck);
6 changes: 5 additions & 1 deletion src/commands/extract/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import { Command } from 'commander';

import { extractKeysOfFiles } from '../../extractor';
import { WarningMessages, emitGitHubWarning } from '../../extractor/warnings';
import { loading } from '../../utils/logger';

type ExtractLintOptions = BaseExtractOptions;

async function lintHandler(this: Command, filesPattern: string) {
const opts: ExtractLintOptions = this.optsWithGlobals();
const extracted = await extractKeysOfFiles(filesPattern, opts.extractor);
const extracted = await loading(
'Analyzing code...',
extractKeysOfFiles(filesPattern, opts.extractor)
);

let warningCount = 0;
let filesCount = 0;
Expand Down
6 changes: 5 additions & 1 deletion src/commands/extract/print.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import { Command } from 'commander';

import { extractKeysOfFiles } from '../../extractor';
import { WarningMessages } from '../../extractor/warnings';
import { loading } from '../../utils/logger';

type ExtractPrintOptions = BaseExtractOptions;

async function printHandler(this: Command, filesPattern: string) {
const opts: ExtractPrintOptions = this.optsWithGlobals();
const extracted = await extractKeysOfFiles(filesPattern, opts.extractor);
const extracted = await loading(
'Analyzing code...',
extractKeysOfFiles(filesPattern, opts.extractor)
);

let warningCount = 0;
const keySet = new Set();
Expand Down
Loading