@tolgee/cli
Advanced tools
Comparing version 1.1.0 to 1.1.1
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.HttpError = void 0; | ||
class HttpError extends Error { | ||
export class HttpError extends Error { | ||
request; | ||
@@ -36,2 +33,1 @@ response; | ||
} | ||
exports.HttpError = HttpError; |
@@ -1,4 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class ExportClient { | ||
export default class ExportClient { | ||
requester; | ||
@@ -23,2 +21,1 @@ constructor(requester) { | ||
} | ||
exports.default = ExportClient; |
@@ -1,9 +0,4 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const form_data_1 = __importDefault(require("form-data")); | ||
const errors_1 = require("./errors"); | ||
class ImportClient { | ||
import FormData from 'form-data'; | ||
import { HttpError } from './errors.js'; | ||
export default class ImportClient { | ||
requester; | ||
@@ -14,3 +9,3 @@ constructor(requester) { | ||
async addFiles(req) { | ||
const body = new form_data_1.default(); | ||
const body = new FormData(); | ||
for (const file of req.files) { | ||
@@ -56,3 +51,3 @@ body.append('files', file.data, { filepath: file.name }); | ||
catch (e) { | ||
if (e instanceof errors_1.HttpError && e.response.status === 404) | ||
if (e instanceof HttpError && e.response.status === 404) | ||
return; | ||
@@ -63,2 +58,1 @@ throw e; | ||
} | ||
exports.default = ImportClient; |
@@ -1,14 +0,9 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const base32_decode_1 = __importDefault(require("base32-decode")); | ||
const requester_1 = __importDefault(require("./internal/requester")); | ||
const project_1 = __importDefault(require("./project")); | ||
const languages_1 = __importDefault(require("./languages")); | ||
const import_1 = __importDefault(require("./import")); | ||
const export_1 = __importDefault(require("./export")); | ||
const constants_1 = require("../constants"); | ||
class RestClient { | ||
import base32Decode from 'base32-decode'; | ||
import Requester from './internal/requester.js'; | ||
import ProjectClient from './project.js'; | ||
import LanguagesClient from './languages.js'; | ||
import ImportClient from './import.js'; | ||
import ExportClient from './export.js'; | ||
import { API_KEY_PAK_PREFIX } from '../constants.js'; | ||
export default class RestClient { | ||
params; | ||
@@ -22,7 +17,7 @@ requester; | ||
this.params = params; | ||
this.requester = new requester_1.default(params); | ||
this.project = new project_1.default(this.requester); | ||
this.languages = new languages_1.default(this.requester); | ||
this.import = new import_1.default(this.requester); | ||
this.export = new export_1.default(this.requester); | ||
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); | ||
} | ||
@@ -39,3 +34,3 @@ async getProjectApiKeyInformation() { | ||
static projectIdFromKey(key) { | ||
const keyBuffer = (0, base32_decode_1.default)(key.slice(constants_1.API_KEY_PAK_PREFIX.length).toUpperCase(), 'RFC4648'); | ||
const keyBuffer = base32Decode(key.slice(API_KEY_PAK_PREFIX.length).toUpperCase(), 'RFC4648'); | ||
const decoded = Buffer.from(keyBuffer).toString('utf8'); | ||
@@ -45,3 +40,3 @@ return Number(decoded.split('_')[0]); | ||
static getProjectApiKeyInformation(api, key) { | ||
return new requester_1.default({ apiUrl: api, apiKey: key }).requestJson({ | ||
return new Requester({ apiUrl: api, apiKey: key }).requestJson({ | ||
path: '/v2/api-keys/current', | ||
@@ -52,3 +47,3 @@ method: 'GET', | ||
static getPersonalAccessTokenInformation(api, key) { | ||
return new requester_1.default({ apiUrl: api, apiKey: key }).requestJson({ | ||
return new Requester({ apiUrl: api, apiKey: key }).requestJson({ | ||
path: '/v2/pats/current', | ||
@@ -59,3 +54,3 @@ method: 'GET', | ||
static async getApiKeyInformation(api, key) { | ||
if (key.startsWith(constants_1.API_KEY_PAK_PREFIX)) { | ||
if (key.startsWith(API_KEY_PAK_PREFIX)) { | ||
const info = await RestClient.getProjectApiKeyInformation(api, key); | ||
@@ -84,2 +79,1 @@ const username = info.userFullName || info.username || '<unknown user>'; | ||
} | ||
exports.default = RestClient; |
@@ -1,13 +0,8 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const undici_1 = require("undici"); | ||
const undici_2 = require("undici"); | ||
const form_data_1 = __importDefault(require("form-data")); | ||
const errors_1 = require("../errors"); | ||
const logger_1 = require("../../utils/logger"); | ||
const constants_1 = require("../../constants"); | ||
class Requester { | ||
import { Request } from 'undici'; | ||
import { fetch } from 'undici'; | ||
import FormData from 'form-data'; | ||
import { HttpError } from '../errors.js'; | ||
import { debug } from '../../utils/logger.js'; | ||
import { USER_AGENT } from '../../constants.js'; | ||
export default class Requester { | ||
params; | ||
@@ -47,3 +42,3 @@ constructor(params) { | ||
...(req.headers || {}), | ||
'user-agent': constants_1.USER_AGENT, | ||
'user-agent': USER_AGENT, | ||
'x-api-key': this.params.apiKey, | ||
@@ -53,3 +48,3 @@ }; | ||
if (req.body) { | ||
if (req.body instanceof form_data_1.default) { | ||
if (req.body instanceof FormData) { | ||
const header = `multipart/form-data; boundary=${req.body.getBoundary()}`; | ||
@@ -64,3 +59,3 @@ headers['content-type'] = header; | ||
} | ||
const request = new undici_1.Request(url, { | ||
const request = new Request(url, { | ||
method: req.method, | ||
@@ -70,7 +65,7 @@ headers: headers, | ||
}); | ||
(0, logger_1.debug)(`[HTTP] Requesting: ${request.method} ${request.url}`); | ||
const response = await (0, undici_2.fetch)(request); | ||
(0, logger_1.debug)(`[HTTP] ${request.method} ${request.url} -> ${response.status} ${response.statusText}`); | ||
debug(`[HTTP] Requesting: ${request.method} ${request.url}`); | ||
const response = await fetch(request); | ||
debug(`[HTTP] ${request.method} ${request.url} -> ${response.status} ${response.statusText}`); | ||
if (!response.ok) | ||
throw new errors_1.HttpError(request, response); | ||
throw new HttpError(request, response); | ||
return response; | ||
@@ -149,2 +144,1 @@ } | ||
} | ||
exports.default = Requester; |
@@ -1,2 +0,1 @@ | ||
"use strict"; | ||
/** | ||
@@ -6,2 +5,2 @@ * This file was auto-generated by openapi-typescript. | ||
*/ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
export {}; |
@@ -1,2 +0,1 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
export {}; |
@@ -1,4 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class LanguagesClient { | ||
export default class LanguagesClient { | ||
requester; | ||
@@ -16,2 +14,1 @@ constructor(requester) { | ||
} | ||
exports.default = LanguagesClient; |
@@ -1,4 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class ProjectClient { | ||
export default class ProjectClient { | ||
requester; | ||
@@ -44,2 +42,1 @@ constructor(requester) { | ||
} | ||
exports.default = ProjectClient; |
@@ -1,14 +0,9 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const commander_1 = require("commander"); | ||
const print_1 = __importDefault(require("./extract/print")); | ||
const check_1 = __importDefault(require("./extract/check")); | ||
const options_1 = require("../options"); | ||
exports.default = new commander_1.Command('extract') | ||
import { Command } from 'commander'; | ||
import extractPrint from './extract/print.js'; | ||
import extractCheck from './extract/check.js'; | ||
import { EXTRACTOR } from '../options.js'; | ||
export default new Command('extract') | ||
.description('Extracts strings from your projects') | ||
.addOption(options_1.EXTRACTOR) | ||
.addCommand(print_1.default) | ||
.addCommand(check_1.default); | ||
.addOption(EXTRACTOR) | ||
.addCommand(extractPrint) | ||
.addCommand(extractCheck); |
@@ -1,11 +0,9 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const path_1 = require("path"); | ||
const commander_1 = require("commander"); | ||
const runner_1 = require("../../extractor/runner"); | ||
const warnings_1 = require("../../extractor/warnings"); | ||
const logger_1 = require("../../utils/logger"); | ||
import { relative } from 'path'; | ||
import { Command } from 'commander'; | ||
import { extractKeysOfFiles } from '../../extractor/runner.js'; | ||
import { WarningMessages, emitGitHubWarning, } from '../../extractor/warnings.js'; | ||
import { loading } from '../../utils/logger.js'; | ||
async function lintHandler(filesPattern) { | ||
const opts = this.optsWithGlobals(); | ||
const extracted = await (0, logger_1.loading)('Analyzing code...', (0, runner_1.extractKeysOfFiles)(filesPattern, opts.extractor)); | ||
const extracted = await loading('Analyzing code...', extractKeysOfFiles(filesPattern, opts.extractor)); | ||
let warningCount = 0; | ||
@@ -17,7 +15,7 @@ let filesCount = 0; | ||
filesCount++; | ||
const relFile = (0, path_1.relative)(process.cwd(), file); | ||
const relFile = relative(process.cwd(), file); | ||
console.log('%s:', relFile); | ||
for (const warning of warnings) { | ||
if (warning.warning in warnings_1.WarningMessages) { | ||
const { name } = warnings_1.WarningMessages[warning.warning]; | ||
if (warning.warning in WarningMessages) { | ||
const { name } = WarningMessages[warning.warning]; | ||
console.log('\tline %d: %s', warning.line, name); | ||
@@ -28,3 +26,3 @@ } | ||
} | ||
(0, warnings_1.emitGitHubWarning)(warning.warning, file, warning.line); | ||
emitGitHubWarning(warning.warning, file, warning.line); | ||
} | ||
@@ -40,5 +38,5 @@ } | ||
} | ||
exports.default = new commander_1.Command('check') | ||
export default new Command('check') | ||
.description('Checks if the keys can be extracted automatically, and reports problems if any') | ||
.argument('<pattern>', 'File pattern to include (hint: make sure to escape it in quotes, or your shell might attempt to unroll some tokens like *)') | ||
.action(lintHandler); |
@@ -1,11 +0,9 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const path_1 = require("path"); | ||
const commander_1 = require("commander"); | ||
const runner_1 = require("../../extractor/runner"); | ||
const warnings_1 = require("../../extractor/warnings"); | ||
const logger_1 = require("../../utils/logger"); | ||
import { relative } from 'path'; | ||
import { Command } from 'commander'; | ||
import { extractKeysOfFiles } from '../../extractor/runner.js'; | ||
import { WarningMessages } from '../../extractor/warnings.js'; | ||
import { loading } from '../../utils/logger.js'; | ||
async function printHandler(filesPattern) { | ||
const opts = this.optsWithGlobals(); | ||
const extracted = await (0, logger_1.loading)('Analyzing code...', (0, runner_1.extractKeysOfFiles)(filesPattern, opts.extractor)); | ||
const extracted = await loading('Analyzing code...', extractKeysOfFiles(filesPattern, opts.extractor)); | ||
let warningCount = 0; | ||
@@ -15,3 +13,3 @@ const keySet = new Set(); | ||
if (keys.length) { | ||
const relFile = (0, path_1.relative)(process.cwd(), file); | ||
const relFile = relative(process.cwd(), file); | ||
console.log('%d key%s found in %s:', keys.length, keys.length !== 1 ? 's' : '', relFile); | ||
@@ -33,4 +31,4 @@ for (const key of keys) { | ||
for (const warning of warnings) { | ||
if (warning.warning in warnings_1.WarningMessages) { | ||
const { name } = warnings_1.WarningMessages[warning.warning]; | ||
if (warning.warning in WarningMessages) { | ||
const { name } = WarningMessages[warning.warning]; | ||
console.log('\tline %d: %s', warning.line, name); | ||
@@ -50,5 +48,5 @@ } | ||
} | ||
exports.default = new commander_1.Command('print') | ||
export default new Command('print') | ||
.description('Prints extracted data to the console') | ||
.argument('<pattern>', 'File glob pattern to include (hint: make sure to escape it in quotes, or your shell might attempt to unroll some tokens like *)') | ||
.action(printHandler); |
@@ -1,12 +0,6 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Logout = exports.Login = void 0; | ||
const commander_1 = require("commander"); | ||
const client_1 = __importDefault(require("../client")); | ||
const errors_1 = require("../client/errors"); | ||
const credentials_1 = require("../config/credentials"); | ||
const logger_1 = require("../utils/logger"); | ||
import { Command } from 'commander'; | ||
import RestClient from '../client/index.js'; | ||
import { HttpError } from '../client/errors.js'; | ||
import { saveApiKey, removeApiKeys, clearAuthStore, } from '../config/credentials.js'; | ||
import { success, error } from '../utils/logger.js'; | ||
async function loginHandler(key) { | ||
@@ -16,7 +10,7 @@ const opts = this.optsWithGlobals(); | ||
try { | ||
keyInfo = await client_1.default.getApiKeyInformation(opts.apiUrl, key); | ||
keyInfo = await RestClient.getApiKeyInformation(opts.apiUrl, key); | ||
} | ||
catch (e) { | ||
if (e instanceof errors_1.HttpError && e.response.status === 403) { | ||
(0, logger_1.error)("Couldn't log in: the API key you provided is invalid."); | ||
if (e instanceof HttpError && e.response.status === 403) { | ||
error("Couldn't log in: the API key you provided is invalid."); | ||
process.exit(1); | ||
@@ -26,4 +20,4 @@ } | ||
} | ||
await (0, credentials_1.saveApiKey)(opts.apiUrl, keyInfo); | ||
(0, logger_1.success)(keyInfo.type === 'PAK' | ||
await saveApiKey(opts.apiUrl, keyInfo); | ||
success(keyInfo.type === 'PAK' | ||
? `Logged in as ${keyInfo.username} on ${opts.apiUrl.hostname} for project ${keyInfo.project.name} (#${keyInfo.project.id}). Welcome back!` | ||
@@ -35,10 +29,10 @@ : `Logged in as ${keyInfo.username} on ${opts.apiUrl.hostname}. Welcome back!`); | ||
if (opts.all) { | ||
await (0, credentials_1.clearAuthStore)(); | ||
(0, logger_1.success)("You've been logged out of all Tolgee instances you were logged in."); | ||
await clearAuthStore(); | ||
success("You've been logged out of all Tolgee instances you were logged in."); | ||
return; | ||
} | ||
await (0, credentials_1.removeApiKeys)(opts.apiUrl); | ||
(0, logger_1.success)(`You're now logged out of ${opts.apiUrl.hostname}.`); | ||
await removeApiKeys(opts.apiUrl); | ||
success(`You're now logged out of ${opts.apiUrl.hostname}.`); | ||
} | ||
exports.Login = new commander_1.Command() | ||
export const Login = new Command() | ||
.name('login') | ||
@@ -48,3 +42,3 @@ .description('Login to Tolgee with an API key. You can be logged into multiple Tolgee instances at the same time by using --api-url') | ||
.action(loginHandler); | ||
exports.Logout = new commander_1.Command() | ||
export const Logout = new Command() | ||
.name('logout') | ||
@@ -51,0 +45,0 @@ .description('Logs out of Tolgee') |
@@ -1,7 +0,5 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const commander_1 = require("commander"); | ||
const zip_1 = require("../utils/zip"); | ||
const overwriteDir_1 = require("../utils/overwriteDir"); | ||
const logger_1 = require("../utils/logger"); | ||
import { Command, Option } from 'commander'; | ||
import { unzipBuffer } from '../utils/zip.js'; | ||
import { overwriteDir } from '../utils/overwriteDir.js'; | ||
import { loading, success } from '../utils/logger.js'; | ||
async function fetchZipBlob(opts) { | ||
@@ -17,12 +15,12 @@ return opts.client.export.export({ | ||
const opts = this.optsWithGlobals(); | ||
await (0, overwriteDir_1.overwriteDir)(path, opts.overwrite); | ||
const zipBlob = await (0, logger_1.loading)('Fetching strings from Tolgee...', fetchZipBlob(opts)); | ||
await (0, logger_1.loading)('Extracting strings...', (0, zip_1.unzipBuffer)(zipBlob, path)); | ||
(0, logger_1.success)('Done!'); | ||
await overwriteDir(path, opts.overwrite); | ||
const zipBlob = await loading('Fetching strings from Tolgee...', fetchZipBlob(opts)); | ||
await loading('Extracting strings...', unzipBuffer(zipBlob, path)); | ||
success('Done!'); | ||
} | ||
exports.default = new commander_1.Command() | ||
export default new Command() | ||
.name('pull') | ||
.description('Pulls translations to Tolgee') | ||
.argument('<path>', 'Destination path where translation files will be stored in') | ||
.addOption(new commander_1.Option('-f, --format <format>', 'Format of the exported files') | ||
.addOption(new Option('-f, --format <format>', 'Format of the exported files') | ||
.choices(['JSON', 'XLIFF']) | ||
@@ -32,6 +30,6 @@ .default('JSON') | ||
.option('-l, --languages <languages...>', 'List of languages to pull. Leave unspecified to export them all') | ||
.addOption(new commander_1.Option('-s, --states <states...>', 'List of translation states to include. Defaults all except untranslated') | ||
.addOption(new Option('-s, --states <states...>', 'List of translation states to include. Defaults all except untranslated') | ||
.choices(['UNTRANSLATED', 'TRANSLATED', 'REVIEWED']) | ||
.argParser((v, a) => [v.toUpperCase(), ...(a || [])])) | ||
.addOption(new commander_1.Option('-d, --delimiter', 'Structure delimiter to use. By default, Tolgee interprets `.` as a nested structure. You can change the delimiter, or disable structure formatting by not specifying any value to the option') | ||
.addOption(new Option('-d, --delimiter', 'Structure delimiter to use. By default, Tolgee interprets `.` as a nested structure. You can change the delimiter, or disable structure formatting by not specifying any value to the option') | ||
.default('.') | ||
@@ -38,0 +36,0 @@ .argParser((v) => v || '')) |
@@ -1,15 +0,13 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const path_1 = require("path"); | ||
const promises_1 = require("fs/promises"); | ||
const commander_1 = require("commander"); | ||
const errors_1 = require("../client/errors"); | ||
const ask_1 = require("../utils/ask"); | ||
const logger_1 = require("../utils/logger"); | ||
import { join } from 'path'; | ||
import { readdir, readFile, stat } from 'fs/promises'; | ||
import { Command, Option } from 'commander'; | ||
import { HttpError } from '../client/errors.js'; | ||
import { askString } from '../utils/ask.js'; | ||
import { loading, success, warn, error } from '../utils/logger.js'; | ||
async function readDirectory(directory, base = '') { | ||
const files = []; | ||
const dir = await (0, promises_1.readdir)(directory); | ||
const dir = await readdir(directory); | ||
for (const file of dir) { | ||
const filePath = (0, path_1.join)(directory, file); | ||
const fileStat = await (0, promises_1.stat)(filePath); | ||
const filePath = join(directory, file); | ||
const fileStat = await stat(filePath); | ||
if (fileStat.isDirectory()) { | ||
@@ -20,3 +18,3 @@ const dirFiles = await readDirectory(filePath, `${file}/`); | ||
else { | ||
const blob = await (0, promises_1.readFile)(filePath); | ||
const blob = await readFile(filePath); | ||
files.push({ name: base + file, data: blob }); | ||
@@ -43,3 +41,3 @@ } | ||
if (opts.forceMode === 'NO') { | ||
(0, logger_1.error)(`There are conflicts in the import. You can resolve them and complete the import here: ${resolveUrl}.`); | ||
error(`There are conflicts in the import. You can resolve them and complete the import here: ${resolveUrl}.`); | ||
process.exit(1); | ||
@@ -51,9 +49,9 @@ } | ||
if (!process.stdout.isTTY) { | ||
(0, logger_1.error)(`There are conflicts in the import. Please specify a --force-mode, or resolve them in your browser at ${resolveUrl}.`); | ||
error(`There are conflicts in the import. Please specify a --force-mode, or resolve them in your browser at ${resolveUrl}.`); | ||
process.exit(1); | ||
} | ||
(0, logger_1.warn)('There are conflicts in the import. What do you want to do?'); | ||
const resp = await (0, ask_1.askString)('Type "KEEP" to preserve the version on the server, "OVERRIDE" to use the version from the import, and nothing to abort: '); | ||
warn('There are conflicts in the import. What do you want to do?'); | ||
const resp = await askString('Type "KEEP" to preserve the version on the server, "OVERRIDE" to use the version from the import, and nothing to abort: '); | ||
if (resp !== 'KEEP' && resp !== 'OVERRIDE') { | ||
(0, logger_1.error)(`Aborting. You can resolve the conflicts and complete the import here: ${resolveUrl}`); | ||
error(`Aborting. You can resolve the conflicts and complete the import here: ${resolveUrl}`); | ||
process.exit(1); | ||
@@ -64,3 +62,3 @@ } | ||
async function prepareImport(client, files) { | ||
return (0, logger_1.loading)('Deleting import...', client.import.deleteImportIfExists()).then(() => (0, logger_1.loading)('Uploading files...', client.import.addFiles({ files: files }))); | ||
return loading('Deleting import...', client.import.deleteImportIfExists()).then(() => loading('Uploading files...', client.import.addFiles({ files: files }))); | ||
} | ||
@@ -79,7 +77,7 @@ async function resolveConflicts(client, locales, method) { | ||
try { | ||
await (0, logger_1.loading)('Applying changes...', client.import.applyImport()); | ||
await loading('Applying changes...', client.import.applyImport()); | ||
} | ||
catch (e) { | ||
if (e instanceof errors_1.HttpError && e.response.status === 400) { | ||
(0, logger_1.error)("Some of the imported languages weren't recognized. Please create a language with corresponding tag in the Tolgee Platform."); | ||
if (e instanceof HttpError && e.response.status === 400) { | ||
error("Some of the imported languages weren't recognized. Please create a language with corresponding tag in the Tolgee Platform."); | ||
return; | ||
@@ -93,5 +91,5 @@ } | ||
try { | ||
const stats = await (0, promises_1.stat)(path); | ||
const stats = await stat(path); | ||
if (!stats.isDirectory()) { | ||
(0, logger_1.error)('The specified path is not a directory.'); | ||
error('The specified path is not a directory.'); | ||
process.exit(1); | ||
@@ -102,3 +100,3 @@ } | ||
if (e.code === 'ENOENT') { | ||
(0, logger_1.error)('The specified path does not exist.'); | ||
error('The specified path does not exist.'); | ||
process.exit(1); | ||
@@ -108,5 +106,5 @@ } | ||
} | ||
const files = await (0, logger_1.loading)('Reading files...', readDirectory(path)); | ||
const files = await loading('Reading files...', readDirectory(path)); | ||
if (files.length === 0) { | ||
(0, logger_1.error)('Nothing to import.'); | ||
error('Nothing to import.'); | ||
return; | ||
@@ -118,14 +116,14 @@ } | ||
const resolveMethod = await promptConflicts(opts); | ||
await (0, logger_1.loading)('Resolving conflicts...', resolveConflicts(opts.client, conflicts, resolveMethod)); | ||
await loading('Resolving conflicts...', resolveConflicts(opts.client, conflicts, resolveMethod)); | ||
} | ||
await applyImport(opts.client); | ||
(0, logger_1.success)('Done!'); | ||
success('Done!'); | ||
} | ||
exports.default = new commander_1.Command() | ||
export default new Command() | ||
.name('push') | ||
.description('Pushes translations to Tolgee') | ||
.argument('<path>', 'Path to the files to push to Tolgee') | ||
.addOption(new commander_1.Option('-f, --force-mode <mode>', 'What should we do with possible conflicts? If unspecified, the user will be prompted interactively, or the command will fail when in non-interactive') | ||
.addOption(new Option('-f, --force-mode <mode>', 'What should we do with possible conflicts? If unspecified, the user will be prompted interactively, or the command will fail when in non-interactive') | ||
.choices(['OVERRIDE', 'KEEP', 'NO']) | ||
.argParser((v) => v.toUpperCase())) | ||
.action(pushHandler); |
@@ -1,22 +0,17 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const commander_1 = require("commander"); | ||
const ansi_colors_1 = __importDefault(require("ansi-colors")); | ||
const syncUtils_1 = require("./syncUtils"); | ||
const runner_1 = require("../../extractor/runner"); | ||
const warnings_1 = require("../../extractor/warnings"); | ||
const options_1 = require("../../options"); | ||
const logger_1 = require("../../utils/logger"); | ||
import { Command } from 'commander'; | ||
import ansi from 'ansi-colors'; | ||
import { compareKeys, printKey } from './syncUtils.js'; | ||
import { extractKeysOfFiles, filterExtractionResult, } from '../../extractor/runner.js'; | ||
import { dumpWarnings } from '../../extractor/warnings.js'; | ||
import { EXTRACTOR } from '../../options.js'; | ||
import { loading } from '../../utils/logger.js'; | ||
async function compareHandler(pattern) { | ||
const opts = this.optsWithGlobals(); | ||
const rawKeys = await (0, logger_1.loading)('Analyzing code...', (0, runner_1.extractKeysOfFiles)(pattern, opts.extractor)); | ||
(0, warnings_1.dumpWarnings)(rawKeys); | ||
const localKeys = (0, runner_1.filterExtractionResult)(rawKeys); | ||
const rawKeys = await loading('Analyzing code...', extractKeysOfFiles(pattern, opts.extractor)); | ||
dumpWarnings(rawKeys); | ||
const localKeys = filterExtractionResult(rawKeys); | ||
const remoteKeys = await opts.client.project.fetchAllKeys(); | ||
const diff = (0, syncUtils_1.compareKeys)(localKeys, remoteKeys); | ||
const diff = compareKeys(localKeys, remoteKeys); | ||
if (!diff.added.length && !diff.removed.length) { | ||
console.log(ansi_colors_1.default.green('Your code project is in sync with the associated Tolgee project!')); | ||
console.log(ansi.green('Your code project is in sync with the associated Tolgee project!')); | ||
process.exit(0); | ||
@@ -27,5 +22,5 @@ } | ||
const key = diff.added.length === 1 ? 'key' : 'keys'; | ||
console.log(ansi_colors_1.default.green.bold(`${diff.added.length} new ${key} found`)); | ||
console.log(ansi.green.bold(`${diff.added.length} new ${key} found`)); | ||
for (const key of diff.added) { | ||
(0, syncUtils_1.printKey)(key, false); | ||
printKey(key, false); | ||
} | ||
@@ -37,5 +32,5 @@ // Line break | ||
const key = diff.removed.length === 1 ? 'key' : 'keys'; | ||
console.log(ansi_colors_1.default.red.bold(`${diff.removed.length} unused ${key}`)); | ||
console.log(ansi.red.bold(`${diff.removed.length} unused ${key}`)); | ||
for (const key of diff.removed) { | ||
(0, syncUtils_1.printKey)(key, true); | ||
printKey(key, true); | ||
} | ||
@@ -47,7 +42,7 @@ // Line break | ||
} | ||
exports.default = new commander_1.Command() | ||
export default new Command() | ||
.name('compare') | ||
.description('Compares the keys in your code project and in the Tolgee project.') | ||
.argument('<pattern>', 'File pattern to include (hint: make sure to escape it in quotes, or your shell might attempt to unroll some tokens like *)') | ||
.addOption(options_1.EXTRACTOR) | ||
.addOption(EXTRACTOR) | ||
.action(compareHandler); |
@@ -1,16 +0,11 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const commander_1 = require("commander"); | ||
const ansi_colors_1 = __importDefault(require("ansi-colors")); | ||
const runner_1 = require("../../extractor/runner"); | ||
const warnings_1 = require("../../extractor/warnings"); | ||
const syncUtils_1 = require("./syncUtils"); | ||
const overwriteDir_1 = require("../../utils/overwriteDir"); | ||
const zip_1 = require("../../utils/zip"); | ||
const ask_1 = require("../../utils/ask"); | ||
const logger_1 = require("../../utils/logger"); | ||
const options_1 = require("../../options"); | ||
import { Command } from 'commander'; | ||
import ansi from 'ansi-colors'; | ||
import { extractKeysOfFiles, filterExtractionResult, } from '../../extractor/runner.js'; | ||
import { dumpWarnings } from '../../extractor/warnings.js'; | ||
import { compareKeys, printKey } from './syncUtils.js'; | ||
import { overwriteDir } from '../../utils/overwriteDir.js'; | ||
import { unzipBuffer } from '../../utils/zip.js'; | ||
import { askBoolean } from '../../utils/ask.js'; | ||
import { loading, error } from '../../utils/logger.js'; | ||
import { EXTRACTOR } from '../../options.js'; | ||
async function backup(client, dest) { | ||
@@ -22,15 +17,15 @@ const blob = await client.export.export({ | ||
}); | ||
await (0, zip_1.unzipBuffer)(blob, dest); | ||
await unzipBuffer(blob, dest); | ||
} | ||
async function askForConfirmation(keys, operation) { | ||
if (!process.stdout.isTTY) { | ||
(0, logger_1.error)('You must run this command interactively, or specify --yes to proceed.'); | ||
error('You must run this command interactively, or specify --yes to proceed.'); | ||
process.exit(1); | ||
} | ||
const str = `The following keys will be ${operation}:`; | ||
console.log(operation === 'created' ? ansi_colors_1.default.bold.green(str) : ansi_colors_1.default.bold.red(str)); | ||
keys.forEach((k) => (0, syncUtils_1.printKey)(k, operation === 'deleted')); | ||
const shouldContinue = await (0, ask_1.askBoolean)('Does this look correct?', true); | ||
console.log(operation === 'created' ? ansi.bold.green(str) : ansi.bold.red(str)); | ||
keys.forEach((k) => printKey(k, operation === 'deleted')); | ||
const shouldContinue = await askBoolean('Does this look correct?', true); | ||
if (!shouldContinue) { | ||
(0, logger_1.error)('Aborting.'); | ||
error('Aborting.'); | ||
process.exit(1); | ||
@@ -41,13 +36,13 @@ } | ||
const opts = this.optsWithGlobals(); | ||
const rawKeys = await (0, logger_1.loading)('Analyzing code...', (0, runner_1.extractKeysOfFiles)(pattern, opts.extractor)); | ||
const warnCount = (0, warnings_1.dumpWarnings)(rawKeys); | ||
const rawKeys = await loading('Analyzing code...', extractKeysOfFiles(pattern, opts.extractor)); | ||
const warnCount = dumpWarnings(rawKeys); | ||
if (!opts.continueOnWarning && warnCount) { | ||
console.log(ansi_colors_1.default.bold.red('Aborting as warnings have been emitted.')); | ||
console.log(ansi.bold.red('Aborting as warnings have been emitted.')); | ||
process.exit(1); | ||
} | ||
const localKeys = (0, runner_1.filterExtractionResult)(rawKeys); | ||
const localKeys = filterExtractionResult(rawKeys); | ||
const remoteKeys = await opts.client.project.fetchAllKeys(); | ||
const diff = (0, syncUtils_1.compareKeys)(localKeys, remoteKeys); | ||
const diff = compareKeys(localKeys, remoteKeys); | ||
if (!diff.added.length && !diff.removed.length) { | ||
console.log(ansi_colors_1.default.green('Your code project is in sync with the associated Tolgee project!')); | ||
console.log(ansi.green('Your code project is in sync with the associated Tolgee project!')); | ||
process.exit(0); | ||
@@ -59,3 +54,3 @@ } | ||
// I'm highly unsure how we could reach this state, but this is what the OAI spec tells me ยฏ\_(ใ)_/ยฏ | ||
(0, logger_1.error)('Your project does not have a base language!'); | ||
error('Your project does not have a base language!'); | ||
process.exit(1); | ||
@@ -65,4 +60,4 @@ } | ||
if (opts.backup) { | ||
await (0, overwriteDir_1.overwriteDir)(opts.backup, opts.yes); | ||
await (0, logger_1.loading)('Backing up Tolgee project', backup(opts.client, opts.backup)); | ||
await overwriteDir(opts.backup, opts.yes); | ||
await loading('Backing up Tolgee project', backup(opts.client, opts.backup)); | ||
} | ||
@@ -81,3 +76,3 @@ // Create new keys | ||
})); | ||
await (0, logger_1.loading)('Creating missing keys...', opts.client.project.createBulkKey(keys)); | ||
await loading('Creating missing keys...', opts.client.project.createBulkKey(keys)); | ||
} | ||
@@ -91,22 +86,22 @@ if (opts.removeUnused) { | ||
const ids = await diff.removed.map((k) => k.id); | ||
await (0, logger_1.loading)('Deleting unused keys...', opts.client.project.deleteBulkKeys(ids)); | ||
await loading('Deleting unused keys...', opts.client.project.deleteBulkKeys(ids)); | ||
} | ||
} | ||
console.log(ansi_colors_1.default.bold.green('Sync complete!')); | ||
console.log(ansi_colors_1.default.green(`+ ${diff.added.length} string${diff.added.length === 1 ? '' : 's'}`)); | ||
console.log(ansi.bold.green('Sync complete!')); | ||
console.log(ansi.green(`+ ${diff.added.length} string${diff.added.length === 1 ? '' : 's'}`)); | ||
if (opts.removeUnused) { | ||
console.log(ansi_colors_1.default.red(`- ${diff.removed.length} string${diff.removed.length === 1 ? '' : 's'}`)); | ||
console.log(ansi.red(`- ${diff.removed.length} string${diff.removed.length === 1 ? '' : 's'}`)); | ||
} | ||
else { | ||
console.log(ansi_colors_1.default.italic(`${diff.removed.length} unused key${diff.removed.length === 1 ? '' : 's'} could be deleted.`)); | ||
console.log(ansi.italic(`${diff.removed.length} unused key${diff.removed.length === 1 ? '' : 's'} could be deleted.`)); | ||
} | ||
if (opts.backup) { | ||
console.log(ansi_colors_1.default.blueBright(`A backup of the project prior to the synchronization has been dumped in ${opts.backup}.`)); | ||
console.log(ansi.blueBright(`A backup of the project prior to the synchronization has been dumped in ${opts.backup}.`)); | ||
} | ||
} | ||
exports.default = new commander_1.Command() | ||
export default new Command() | ||
.name('sync') | ||
.description('Synchronizes the keys in your code project and in the Tolgee project, by creating missing keys and optionally deleting unused ones. For a dry-run, use `tolgee compare`.') | ||
.argument('<pattern>', 'File pattern to include (hint: make sure to escape it in quotes, or your shell might attempt to unroll some tokens like *)') | ||
.addOption(options_1.EXTRACTOR) | ||
.addOption(EXTRACTOR) | ||
.option('-B, --backup <path>', 'Path where a backup should be downloaded before performing the sync. If something goes wrong, the backup can be used to restore the project to its previous state.') | ||
@@ -113,0 +108,0 @@ .option('--continue-on-warning', 'Set this flag to continue the sync if warnings are detected during string extraction. By default, as warnings may indicate an invalid extraction, the CLI will abort the sync.') |
@@ -1,9 +0,3 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.compareKeys = exports.printKey = void 0; | ||
const runner_1 = require("../../extractor/runner"); | ||
const ansi_colors_1 = __importDefault(require("ansi-colors")); | ||
import { NullNamespace } from '../../extractor/runner.js'; | ||
import ansi from 'ansi-colors'; | ||
/** | ||
@@ -15,14 +9,13 @@ * Prints information about a key, with coloring and formatting. | ||
*/ | ||
function printKey(key, deletion) { | ||
export function printKey(key, deletion) { | ||
const namespace = key.namespace | ||
? ` ${ansi_colors_1.default.italic(`(namespace: ${key.namespace})`)}` | ||
? ` ${ansi.italic(`(namespace: ${key.namespace})`)}` | ||
: ''; | ||
if (deletion) { | ||
console.log(`${ansi_colors_1.default.red(`- ${key.keyName}`)}${namespace}`); | ||
console.log(`${ansi.red(`- ${key.keyName}`)}${namespace}`); | ||
} | ||
else { | ||
console.log(`${ansi_colors_1.default.green(`+ ${key.keyName}`)}${namespace}`); | ||
console.log(`${ansi.green(`+ ${key.keyName}`)}${namespace}`); | ||
} | ||
} | ||
exports.printKey = printKey; | ||
/** | ||
@@ -36,7 +29,7 @@ * Compares local and remote keys to detect added and deleted keys. | ||
*/ | ||
function compareKeys(local, remote) { | ||
export function compareKeys(local, remote) { | ||
const result = { added: [], removed: [] }; | ||
// Deleted keys | ||
for (const remoteKey of remote) { | ||
const namespace = remoteKey.namespace || runner_1.NullNamespace; | ||
const namespace = remoteKey.namespace || NullNamespace; | ||
const keyExists = local[namespace]?.delete(remoteKey.name); | ||
@@ -52,3 +45,3 @@ if (!keyExists) { | ||
// Added keys | ||
const namespaces = [runner_1.NullNamespace, ...Object.keys(local).sort()]; | ||
const namespaces = [NullNamespace, ...Object.keys(local).sort()]; | ||
for (const namespace of namespaces) { | ||
@@ -61,3 +54,3 @@ if (namespace in local && local[namespace].size) { | ||
keyName: keyName, | ||
namespace: namespace === runner_1.NullNamespace ? undefined : namespace, | ||
namespace: namespace === NullNamespace ? undefined : namespace, | ||
defaultValue: keys.get(keyName) || undefined, | ||
@@ -86,2 +79,1 @@ }); | ||
} | ||
exports.compareKeys = compareKeys; |
@@ -1,12 +0,9 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.clearAuthStore = exports.removeApiKeys = exports.saveApiKey = exports.getApiKey = exports.savePak = exports.savePat = exports.API_TOKENS_FILE = void 0; | ||
const path_1 = require("path"); | ||
const promises_1 = require("fs/promises"); | ||
const logger_1 = require("../utils/logger"); | ||
const constants_1 = require("../constants"); | ||
exports.API_TOKENS_FILE = (0, path_1.join)(constants_1.CONFIG_PATH, 'authentication.json'); | ||
import { join, dirname } from 'path'; | ||
import { mkdir, readFile, writeFile } from 'fs/promises'; | ||
import { warn } from '../utils/logger.js'; | ||
import { CONFIG_PATH } from '../constants.js'; | ||
const API_TOKENS_FILE = join(CONFIG_PATH, 'authentication.json'); | ||
async function ensureConfigPath() { | ||
try { | ||
await (0, promises_1.mkdir)((0, path_1.dirname)(exports.API_TOKENS_FILE)); | ||
await mkdir(dirname(API_TOKENS_FILE)); | ||
} | ||
@@ -22,3 +19,3 @@ catch (e) { | ||
await ensureConfigPath(); | ||
const storeData = await (0, promises_1.readFile)(exports.API_TOKENS_FILE, 'utf8'); | ||
const storeData = await readFile(API_TOKENS_FILE, 'utf8'); | ||
return JSON.parse(storeData); | ||
@@ -35,3 +32,3 @@ } | ||
const blob = JSON.stringify(store); | ||
await (0, promises_1.writeFile)(exports.API_TOKENS_FILE, blob, { | ||
await writeFile(API_TOKENS_FILE, blob, { | ||
mode: 0o600, | ||
@@ -62,13 +59,11 @@ encoding: 'utf8', | ||
} | ||
async function savePat(instance, pat) { | ||
export async function savePat(instance, pat) { | ||
const store = await loadStore(); | ||
return storePat(store, instance, pat); | ||
} | ||
exports.savePat = savePat; | ||
async function savePak(instance, projectId, pak) { | ||
export async function savePak(instance, projectId, pak) { | ||
const store = await loadStore(); | ||
return storePak(store, instance, projectId, pak); | ||
} | ||
exports.savePak = savePak; | ||
async function getApiKey(instance, projectId) { | ||
export async function getApiKey(instance, projectId) { | ||
const store = await loadStore(); | ||
@@ -82,3 +77,3 @@ if (!store[instance.hostname]) { | ||
Date.now() > scopedStore.user.expires) { | ||
(0, logger_1.warn)(`Your personal access token for ${instance.hostname} expired.`); | ||
warn(`Your personal access token for ${instance.hostname} expired.`); | ||
await storePat(store, instance, undefined); | ||
@@ -95,3 +90,3 @@ return null; | ||
if (pak.expires !== 0 && Date.now() > pak.expires) { | ||
(0, logger_1.warn)(`Your project API key for project #${projectId} on ${instance.hostname} expired.`); | ||
warn(`Your project API key for project #${projectId} on ${instance.hostname} expired.`); | ||
await storePak(store, instance, projectId, undefined); | ||
@@ -104,4 +99,3 @@ return null; | ||
} | ||
exports.getApiKey = getApiKey; | ||
async function saveApiKey(instance, token) { | ||
export async function saveApiKey(instance, token) { | ||
const store = await loadStore(); | ||
@@ -119,4 +113,3 @@ if (token.type === 'PAT') { | ||
} | ||
exports.saveApiKey = saveApiKey; | ||
async function removeApiKeys(api) { | ||
export async function removeApiKeys(api) { | ||
const store = await loadStore(); | ||
@@ -128,6 +121,4 @@ return saveStore({ | ||
} | ||
exports.removeApiKeys = removeApiKeys; | ||
async function clearAuthStore() { | ||
export async function clearAuthStore() { | ||
return saveStore({}); | ||
} | ||
exports.clearAuthStore = clearAuthStore; |
@@ -1,10 +0,8 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const cosmiconfig_1 = require("cosmiconfig"); | ||
const path_1 = require("path"); | ||
const fs_1 = require("fs"); | ||
const constants_1 = require("../constants"); | ||
const explorer = (0, cosmiconfig_1.cosmiconfig)('tolgee', { | ||
import { cosmiconfig, defaultLoaders } from 'cosmiconfig'; | ||
import { resolve } from 'path'; | ||
import { existsSync } from 'fs'; | ||
import { SDKS } from '../constants.js'; | ||
const explorer = cosmiconfig('tolgee', { | ||
loaders: { | ||
noExt: cosmiconfig_1.defaultLoaders['.json'], | ||
noExt: defaultLoaders['.json'], | ||
}, | ||
@@ -35,4 +33,4 @@ }); | ||
if ('sdk' in rc) { | ||
if (!constants_1.SDKS.includes(rc.sdk)) { | ||
throw new Error(`Invalid config: invalid sdk. Must be one of: ${constants_1.SDKS.join(' ')}`); | ||
if (!SDKS.includes(rc.sdk)) { | ||
throw new Error(`Invalid config: invalid sdk. Must be one of: ${SDKS.join(' ')}`); | ||
} | ||
@@ -45,4 +43,4 @@ cfg.sdk = rc.sdk; | ||
} | ||
const extractorPath = (0, path_1.resolve)(rc.extractor); | ||
if (!(0, fs_1.existsSync)(extractorPath)) { | ||
const extractorPath = resolve(rc.extractor); | ||
if (!existsSync(extractorPath)) { | ||
throw new Error(`Invalid config: extractor points to a file that does not exists (${extractorPath})`); | ||
@@ -60,3 +58,3 @@ } | ||
} | ||
async function loadTolgeeRc() { | ||
export default async function loadTolgeeRc() { | ||
const res = await explorer.search(); | ||
@@ -67,2 +65,1 @@ if (!res || res.isEmpty) | ||
} | ||
exports.default = loadTolgeeRc; |
@@ -1,18 +0,11 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SDKS = exports.API_KEY_PAK_PREFIX = exports.API_KEY_PAT_PREFIX = exports.DEFAULT_API_URL = exports.USER_AGENT = exports.VERSION = exports.CONFIG_PATH = void 0; | ||
const path_1 = require("path"); | ||
const fs_1 = require("fs"); | ||
const configPath_1 = __importDefault(require("./utils/configPath")); | ||
const packageJson = (0, path_1.join)(__dirname, '..', 'package.json'); | ||
const pkg = (0, fs_1.readFileSync)(packageJson, 'utf8'); | ||
exports.CONFIG_PATH = (0, configPath_1.default)(); | ||
exports.VERSION = JSON.parse(pkg).version; | ||
exports.USER_AGENT = `Tolgee-CLI/${exports.VERSION} (+https://github.com/tolgee/tolgee-cli)`; | ||
exports.DEFAULT_API_URL = new URL('https://app.tolgee.io'); | ||
exports.API_KEY_PAT_PREFIX = 'tgpat_'; | ||
exports.API_KEY_PAK_PREFIX = 'tgpak_'; | ||
exports.SDKS = ['react']; | ||
import { readFileSync } from 'fs'; | ||
import getConfigPath from './utils/configPath.js'; | ||
const packageJson = new URL('../package.json', import.meta.url); | ||
const pkg = readFileSync(packageJson, 'utf8'); | ||
export const CONFIG_PATH = getConfigPath(); | ||
export const VERSION = JSON.parse(pkg).version; | ||
export const USER_AGENT = `Tolgee-CLI/${VERSION} (+https://github.com/tolgee/tolgee-cli)`; | ||
export const DEFAULT_API_URL = new URL('https://app.tolgee.io'); | ||
export const API_KEY_PAT_PREFIX = 'tgpat_'; | ||
export const API_KEY_PAK_PREFIX = 'tgpak_'; | ||
export const SDKS = ['react']; |
@@ -1,12 +0,7 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const path_1 = require("path"); | ||
const xstate_1 = require("xstate"); | ||
const react_1 = __importDefault(require("./machines/react")); | ||
const svelte_1 = __importDefault(require("./machines/svelte")); | ||
const comments_1 = __importDefault(require("./machines/comments")); | ||
const tokenizer_1 = __importDefault(require("./tokenizer")); | ||
import { extname } from 'path'; | ||
import { interpret } from 'xstate'; | ||
import reactExtractorMachine from './machines/react.js'; | ||
import svelteExtractorMachine from './machines/svelte.js'; | ||
import commentsExtractorMachine from './machines/comments.js'; | ||
import tokenizer from './tokenizer.js'; | ||
const REACT_EXTS = [ | ||
@@ -34,16 +29,16 @@ '.js', | ||
function pickMachine(code, fileName) { | ||
const ext = (0, path_1.extname)(fileName); | ||
const ext = extname(fileName); | ||
if (REACT_EXTS.includes(ext) && code.includes('@tolgee/react')) { | ||
return react_1.default; | ||
return reactExtractorMachine; | ||
} | ||
if (ext === '.svelte' && code.includes('@tolgee/svelte')) { | ||
return svelte_1.default; | ||
return svelteExtractorMachine; | ||
} | ||
if (ALL_EXTS.includes(ext) && | ||
(code.includes('@tolgee-key') || code.includes('@tolgee-ignore'))) { | ||
return comments_1.default; | ||
return commentsExtractorMachine; | ||
} | ||
return null; | ||
} | ||
async function extractor(code, fileName) { | ||
export default async function extractor(code, fileName) { | ||
const machineSpec = pickMachine(code, fileName); | ||
@@ -53,5 +48,5 @@ if (!machineSpec) { | ||
} | ||
const tokens = await (0, tokenizer_1.default)(code, fileName); | ||
const tokens = await tokenizer(code, fileName); | ||
// @ts-ignore -- Types are whacky, complains about withConfig but it's not a problem here. | ||
const machine = (0, xstate_1.interpret)(machineSpec); | ||
const machine = interpret(machineSpec); | ||
machine.start(); | ||
@@ -67,2 +62,1 @@ for (const token of tokens) { | ||
} | ||
exports.default = extractor; |
@@ -1,2 +0,1 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
export {}; |
@@ -1,9 +0,4 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const xstate_1 = require("xstate"); | ||
const comments_1 = __importDefault(require("./shared/comments")); | ||
exports.default = (0, xstate_1.createMachine)({ | ||
import { createMachine, assign, send } from 'xstate'; | ||
import commentsService from './shared/comments.js'; | ||
export default createMachine({ | ||
predictableActionArguments: true, | ||
@@ -17,3 +12,3 @@ id: 'commentsExtractor', | ||
id: 'comments', | ||
src: () => comments_1.default, | ||
src: () => commentsService, | ||
}, | ||
@@ -37,3 +32,3 @@ on: { | ||
'comment.line.double-slash.ts': { | ||
actions: (0, xstate_1.send)((_ctx, evt) => ({ | ||
actions: send((_ctx, evt) => ({ | ||
type: 'COMMENT', | ||
@@ -45,3 +40,3 @@ data: evt.token, | ||
'comment.block.ts': { | ||
actions: (0, xstate_1.send)((_ctx, evt) => ({ | ||
actions: send((_ctx, evt) => ({ | ||
type: 'COMMENT', | ||
@@ -53,3 +48,3 @@ data: evt.token, | ||
'comment.block.svelte': { | ||
actions: (0, xstate_1.send)((_ctx, evt) => ({ | ||
actions: send((_ctx, evt) => ({ | ||
type: 'COMMENT', | ||
@@ -63,3 +58,3 @@ data: evt.token, | ||
actions: { | ||
warnUnusedIgnore: (0, xstate_1.assign)({ | ||
warnUnusedIgnore: assign({ | ||
warnings: (ctx, evt) => [ | ||
@@ -70,3 +65,3 @@ ...ctx.warnings, | ||
}), | ||
pushKey: (0, xstate_1.assign)({ | ||
pushKey: assign({ | ||
keys: (ctx, evt) => [ | ||
@@ -82,3 +77,3 @@ ...ctx.keys, | ||
}), | ||
pushWarning: (0, xstate_1.assign)({ | ||
pushWarning: assign({ | ||
warnings: (ctx, evt) => [ | ||
@@ -85,0 +80,0 @@ ...ctx.warnings, |
@@ -1,11 +0,6 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const xstate_1 = require("xstate"); | ||
const properties_1 = __importDefault(require("./shared/properties")); | ||
const comments_1 = __importDefault(require("./shared/comments")); | ||
import { createMachine, assign, send, forwardTo } from 'xstate'; | ||
import propertiesMachine from './shared/properties.js'; | ||
import commentsService from './shared/comments.js'; | ||
const VOID_KEY = { keyName: '', line: -1 }; | ||
exports.default = (0, xstate_1.createMachine)({ | ||
export default createMachine({ | ||
predictableActionArguments: true, | ||
@@ -28,3 +23,3 @@ id: 'reactExtractor', | ||
id: 'comments', | ||
src: () => comments_1.default, | ||
src: () => commentsService, | ||
}, | ||
@@ -48,3 +43,3 @@ on: { | ||
'comment.line.double-slash.ts': { | ||
actions: (0, xstate_1.send)((_ctx, evt) => ({ | ||
actions: send((_ctx, evt) => ({ | ||
type: 'COMMENT', | ||
@@ -56,3 +51,3 @@ data: evt.token, | ||
'comment.block.ts': { | ||
actions: (0, xstate_1.send)((_ctx, evt) => ({ | ||
actions: send((_ctx, evt) => ({ | ||
type: 'COMMENT', | ||
@@ -227,3 +222,3 @@ data: evt.token, | ||
id: 'propertiesMachine', | ||
src: properties_1.default, | ||
src: propertiesMachine, | ||
data: { | ||
@@ -252,3 +247,3 @@ depth: 1, | ||
'*': { | ||
actions: (0, xstate_1.forwardTo)('propertiesMachine'), | ||
actions: forwardTo('propertiesMachine'), | ||
}, | ||
@@ -353,3 +348,3 @@ }, | ||
id: 'propertiesMachine', | ||
src: properties_1.default, | ||
src: propertiesMachine, | ||
onDone: [ | ||
@@ -376,3 +371,3 @@ { | ||
'*': { | ||
actions: (0, xstate_1.forwardTo)('propertiesMachine'), | ||
actions: forwardTo('propertiesMachine'), | ||
}, | ||
@@ -557,3 +552,3 @@ }, | ||
id: 'propertiesMachine', | ||
src: properties_1.default, | ||
src: propertiesMachine, | ||
data: { | ||
@@ -576,3 +571,3 @@ depth: 1, | ||
'*': { | ||
actions: (0, xstate_1.forwardTo)('propertiesMachine'), | ||
actions: forwardTo('propertiesMachine'), | ||
}, | ||
@@ -589,19 +584,19 @@ }, | ||
actions: { | ||
incrementDepth: (0, xstate_1.assign)({ | ||
incrementDepth: assign({ | ||
blockDepth: (ctx) => ctx.blockDepth + 1, | ||
}), | ||
decrementDepth: (0, xstate_1.assign)({ | ||
decrementDepth: assign({ | ||
blockDepth: (ctx) => ctx.blockDepth - 1, | ||
hooks: (ctx) => ctx.hooks.filter((n) => n.depth !== ctx.blockDepth), | ||
}), | ||
storeLine: (0, xstate_1.assign)({ | ||
storeLine: assign({ | ||
line: (_ctx, evt) => evt.line, | ||
}), | ||
ignoreNextLine: (0, xstate_1.assign)({ | ||
ignoreNextLine: assign({ | ||
ignore: (_ctx, evt) => ({ type: 'ignore', line: evt.line + 1 }), | ||
}), | ||
consumeIgnoredLine: (0, xstate_1.assign)({ | ||
consumeIgnoredLine: assign({ | ||
ignore: (_ctx, _evt) => null, | ||
}), | ||
warnUnusedIgnore: (0, xstate_1.assign)({ | ||
warnUnusedIgnore: assign({ | ||
warnings: (ctx, evt) => [ | ||
@@ -612,6 +607,6 @@ ...ctx.warnings, | ||
}), | ||
pushHook: (0, xstate_1.assign)({ | ||
pushHook: assign({ | ||
hooks: (ctx) => [...ctx.hooks, { depth: ctx.blockDepth }], | ||
}), | ||
pushNamespacedHook: (0, xstate_1.assign)({ | ||
pushNamespacedHook: assign({ | ||
hooks: (ctx, evt) => [ | ||
@@ -622,3 +617,3 @@ ...ctx.hooks, | ||
}), | ||
markHookAsDynamic: (0, xstate_1.assign)({ | ||
markHookAsDynamic: assign({ | ||
hooks: (ctx, _evt) => [ | ||
@@ -633,3 +628,3 @@ ...ctx.hooks.slice(0, -1), | ||
}), | ||
consumeParameters: (0, xstate_1.assign)({ | ||
consumeParameters: assign({ | ||
key: (ctx, evt) => ({ | ||
@@ -654,3 +649,3 @@ // We don't want the key and default value to be overridable | ||
}), | ||
emitWarningFromParameters: (0, xstate_1.assign)({ | ||
emitWarningFromParameters: assign({ | ||
warnings: (ctx, evt) => [ | ||
@@ -667,6 +662,6 @@ ...ctx.warnings, | ||
}), | ||
appendChildren: (0, xstate_1.assign)({ | ||
appendChildren: assign({ | ||
children: (ctx, evt) => (ctx.children ?? '') + evt.token, | ||
}), | ||
consumeChildren: (0, xstate_1.assign)({ | ||
consumeChildren: assign({ | ||
key: (ctx, _evt) => ({ | ||
@@ -679,9 +674,9 @@ ...ctx.key, | ||
}), | ||
storeKeyName: (0, xstate_1.assign)({ | ||
storeKeyName: assign({ | ||
key: (ctx, evt) => ({ ...ctx.key, keyName: evt.token }), | ||
}), | ||
storeKeyDefault: (0, xstate_1.assign)({ | ||
storeKeyDefault: assign({ | ||
key: (ctx, evt) => ({ ...ctx.key, defaultValue: evt.token }), | ||
}), | ||
storeKeyCurrentNamespace: (0, xstate_1.assign)({ | ||
storeKeyCurrentNamespace: assign({ | ||
key: (ctx, _evt) => ({ | ||
@@ -694,3 +689,3 @@ ...ctx.key, | ||
}), | ||
dynamicKeyName: (0, xstate_1.assign)({ | ||
dynamicKeyName: assign({ | ||
warnings: (ctx, _evt) => [ | ||
@@ -702,3 +697,3 @@ ...ctx.warnings, | ||
}), | ||
dynamicKeyDefault: (0, xstate_1.assign)({ | ||
dynamicKeyDefault: assign({ | ||
key: (ctx, _evt) => ({ ...ctx.key, defaultValue: undefined }), | ||
@@ -710,3 +705,3 @@ warnings: (ctx, _evt) => [ | ||
}), | ||
dynamicOptions: (0, xstate_1.assign)({ | ||
dynamicOptions: assign({ | ||
key: (ctx, _evt) => VOID_KEY, | ||
@@ -718,3 +713,3 @@ warnings: (ctx, _evt) => [ | ||
}), | ||
dynamicChildren: (0, xstate_1.assign)({ | ||
dynamicChildren: assign({ | ||
key: (ctx, _evt) => ctx.key.keyName ? { ...ctx.key, defaultValue: undefined } : VOID_KEY, | ||
@@ -731,3 +726,3 @@ warnings: (ctx, _evt) => [ | ||
}), | ||
pushKey: (0, xstate_1.assign)({ | ||
pushKey: assign({ | ||
warnings: (ctx, _evt) => { | ||
@@ -756,3 +751,3 @@ if (!ctx.key.keyName || ctx.key.namespace !== false) | ||
}), | ||
pushImmediateKey: (0, xstate_1.assign)({ | ||
pushImmediateKey: assign({ | ||
ignore: (_ctx, evt) => ({ type: 'key', line: evt.line + 1 }), | ||
@@ -769,3 +764,3 @@ keys: (ctx, evt) => [ | ||
}), | ||
pushWarning: (0, xstate_1.assign)({ | ||
pushWarning: assign({ | ||
warnings: (ctx, evt) => [ | ||
@@ -772,0 +767,0 @@ ...ctx.warnings, |
@@ -1,4 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const json5_1 = require("json5"); | ||
import JSON5 from 'json5'; | ||
function isValidKeyOverride(data) { | ||
@@ -20,3 +18,3 @@ if (!('key' in data)) { | ||
// This service is responsible for emitting events when magic comments are encountered | ||
function default_1(callback, onReceive) { | ||
export default function (callback, onReceive) { | ||
onReceive((evt) => { | ||
@@ -45,3 +43,3 @@ const comment = evt.data.trim(); | ||
try { | ||
const key = (0, json5_1.parse)(data); | ||
const key = JSON5.parse(data); | ||
if (!isValidKeyOverride(key)) { | ||
@@ -84,2 +82,1 @@ // No key in the struct; invalid override | ||
} | ||
exports.default = default_1; |
@@ -1,6 +0,4 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const xstate_1 = require("xstate"); | ||
import { createMachine, send, assign } from 'xstate'; | ||
// This state machine is responsible for extracting translation key properties from an object/props | ||
exports.default = (0, xstate_1.createMachine)({ | ||
export default createMachine({ | ||
predictableActionArguments: true, | ||
@@ -119,3 +117,3 @@ id: 'properties', | ||
'clearPropertyType', | ||
(0, xstate_1.send)((_ctx, evt) => evt), | ||
send((_ctx, evt) => evt), | ||
], | ||
@@ -242,9 +240,9 @@ }, | ||
actions: { | ||
storePropertyType: (0, xstate_1.assign)({ | ||
storePropertyType: assign({ | ||
property: (_ctx, evt) => evt.token, | ||
}), | ||
clearPropertyType: (0, xstate_1.assign)({ | ||
clearPropertyType: assign({ | ||
property: (_ctx, _evt) => null, | ||
}), | ||
storePropertyValue: (0, xstate_1.assign)({ | ||
storePropertyValue: assign({ | ||
keyName: (ctx, evt) => ctx.property === 'key' || ctx.property === 'keyName' | ||
@@ -256,3 +254,3 @@ ? evt.token | ||
}), | ||
storeEmptyPropertyValue: (0, xstate_1.assign)({ | ||
storeEmptyPropertyValue: assign({ | ||
keyName: (ctx) => ctx.property === 'key' || ctx.property === 'keyName' | ||
@@ -264,3 +262,3 @@ ? '' | ||
}), | ||
markPropertyAsDynamic: (0, xstate_1.assign)({ | ||
markPropertyAsDynamic: assign({ | ||
keyName: (ctx, _evt) => ctx.property === 'key' || ctx.property === 'keyName' | ||
@@ -272,3 +270,3 @@ ? false | ||
}), | ||
markImmediatePropertyAsDynamic: (0, xstate_1.assign)({ | ||
markImmediatePropertyAsDynamic: assign({ | ||
keyName: (ctx, evt) => evt.token === 'key' || evt.token === 'keyName' ? false : ctx.keyName, | ||
@@ -278,12 +276,12 @@ defaultValue: (ctx, evt) => evt.token === 'defaultValue' ? false : ctx.defaultValue, | ||
}), | ||
incrementDepth: (0, xstate_1.assign)({ | ||
incrementDepth: assign({ | ||
depth: (ctx, _evt) => ctx.depth + 1, | ||
}), | ||
decrementDepth: (0, xstate_1.assign)({ | ||
decrementDepth: assign({ | ||
depth: (ctx, _evt) => ctx.depth - 1, | ||
}), | ||
markAsStatic: (0, xstate_1.assign)({ | ||
markAsStatic: assign({ | ||
static: (_ctx, _evt) => true, | ||
}), | ||
unmarkAsStatic: (0, xstate_1.assign)({ | ||
unmarkAsStatic: assign({ | ||
static: (_ctx, _evt) => false, | ||
@@ -290,0 +288,0 @@ }), |
@@ -1,11 +0,6 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const xstate_1 = require("xstate"); | ||
const properties_1 = __importDefault(require("./shared/properties")); | ||
const comments_1 = __importDefault(require("./shared/comments")); | ||
import { createMachine, assign, send, forwardTo } from 'xstate'; | ||
import propertiesMachine from './shared/properties.js'; | ||
import commentsService from './shared/comments.js'; | ||
const VOID_KEY = { keyName: '', line: -1 }; | ||
exports.default = (0, xstate_1.createMachine)({ | ||
export default createMachine({ | ||
predictableActionArguments: true, | ||
@@ -27,3 +22,3 @@ id: 'svelteExtractor', | ||
id: 'comments', | ||
src: () => comments_1.default, | ||
src: () => commentsService, | ||
}, | ||
@@ -47,3 +42,3 @@ on: { | ||
'comment.line.double-slash.ts': { | ||
actions: (0, xstate_1.send)((_ctx, evt) => ({ | ||
actions: send((_ctx, evt) => ({ | ||
type: 'COMMENT', | ||
@@ -55,3 +50,3 @@ data: evt.token, | ||
'comment.block.ts': { | ||
actions: (0, xstate_1.send)((_ctx, evt) => ({ | ||
actions: send((_ctx, evt) => ({ | ||
type: 'COMMENT', | ||
@@ -63,3 +58,3 @@ data: evt.token, | ||
'comment.block.svelte': { | ||
actions: (0, xstate_1.send)((_ctx, evt) => ({ | ||
actions: send((_ctx, evt) => ({ | ||
type: 'COMMENT', | ||
@@ -181,3 +176,3 @@ data: evt.token, | ||
id: 'propertiesMachine', | ||
src: properties_1.default, | ||
src: propertiesMachine, | ||
onDone: [ | ||
@@ -204,3 +199,3 @@ { | ||
'*': { | ||
actions: (0, xstate_1.forwardTo)('propertiesMachine'), | ||
actions: forwardTo('propertiesMachine'), | ||
}, | ||
@@ -337,3 +332,3 @@ }, | ||
id: 'propertiesMachine', | ||
src: properties_1.default, | ||
src: propertiesMachine, | ||
data: { | ||
@@ -356,3 +351,3 @@ depth: 1, | ||
'*': { | ||
actions: (0, xstate_1.forwardTo)('propertiesMachine'), | ||
actions: forwardTo('propertiesMachine'), | ||
}, | ||
@@ -369,12 +364,12 @@ }, | ||
actions: { | ||
storeLine: (0, xstate_1.assign)({ | ||
storeLine: assign({ | ||
line: (_ctx, evt) => evt.line, | ||
}), | ||
ignoreNextLine: (0, xstate_1.assign)({ | ||
ignoreNextLine: assign({ | ||
ignore: (_ctx, evt) => ({ type: 'ignore', line: evt.line + 1 }), | ||
}), | ||
consumeIgnoredLine: (0, xstate_1.assign)({ | ||
consumeIgnoredLine: assign({ | ||
ignore: (_ctx, _evt) => null, | ||
}), | ||
warnUnusedIgnore: (0, xstate_1.assign)({ | ||
warnUnusedIgnore: assign({ | ||
warnings: (ctx, evt) => [ | ||
@@ -385,9 +380,9 @@ ...ctx.warnings, | ||
}), | ||
storeUseTranslate: (0, xstate_1.assign)({ | ||
storeUseTranslate: assign({ | ||
useTranslate: (_ctx, _evt) => '', | ||
}), | ||
storeNamespacedUseTranslate: (0, xstate_1.assign)({ | ||
storeNamespacedUseTranslate: assign({ | ||
useTranslate: (_ctx, evt) => evt.token, | ||
}), | ||
markUseTranslateAsDynamic: (0, xstate_1.assign)({ | ||
markUseTranslateAsDynamic: assign({ | ||
useTranslate: (_ctx, _evt) => false, | ||
@@ -399,3 +394,3 @@ warnings: (ctx, _evt) => [ | ||
}), | ||
consumeParameters: (0, xstate_1.assign)({ | ||
consumeParameters: assign({ | ||
key: (ctx, evt) => ({ | ||
@@ -416,3 +411,3 @@ keyName: ctx.key.keyName || evt.data.keyName, | ||
}), | ||
emitWarningFromParameters: (0, xstate_1.assign)({ | ||
emitWarningFromParameters: assign({ | ||
warnings: (ctx, evt) => [ | ||
@@ -429,9 +424,9 @@ ...ctx.warnings, | ||
}), | ||
storeKeyName: (0, xstate_1.assign)({ | ||
storeKeyName: assign({ | ||
key: (ctx, evt) => ({ ...ctx.key, keyName: evt.token }), | ||
}), | ||
storeKeyDefault: (0, xstate_1.assign)({ | ||
storeKeyDefault: assign({ | ||
key: (ctx, evt) => ({ ...ctx.key, defaultValue: evt.token }), | ||
}), | ||
storeKeyCurrentNamespace: (0, xstate_1.assign)({ | ||
storeKeyCurrentNamespace: assign({ | ||
key: (ctx, _evt) => ({ | ||
@@ -442,3 +437,3 @@ ...ctx.key, | ||
}), | ||
dynamicKeyName: (0, xstate_1.assign)({ | ||
dynamicKeyName: assign({ | ||
warnings: (ctx, _evt) => [ | ||
@@ -450,3 +445,3 @@ ...ctx.warnings, | ||
}), | ||
dynamicKeyDefault: (0, xstate_1.assign)({ | ||
dynamicKeyDefault: assign({ | ||
key: (ctx, _evt) => ({ ...ctx.key, defaultValue: undefined }), | ||
@@ -458,3 +453,3 @@ warnings: (ctx, _evt) => [ | ||
}), | ||
dynamicOptions: (0, xstate_1.assign)({ | ||
dynamicOptions: assign({ | ||
key: (_ctx, _evt) => VOID_KEY, | ||
@@ -466,3 +461,3 @@ warnings: (ctx, _evt) => [ | ||
}), | ||
pushKey: (0, xstate_1.assign)({ | ||
pushKey: assign({ | ||
warnings: (ctx, _evt) => { | ||
@@ -493,3 +488,3 @@ if (!ctx.key.keyName || ctx.key.namespace !== false) | ||
}), | ||
pushImmediateKey: (0, xstate_1.assign)({ | ||
pushImmediateKey: assign({ | ||
ignore: (_ctx, evt) => ({ type: 'key', line: evt.line + 1 }), | ||
@@ -506,3 +501,3 @@ keys: (ctx, evt) => [ | ||
}), | ||
pushWarning: (0, xstate_1.assign)({ | ||
pushWarning: assign({ | ||
warnings: (ctx, evt) => [ | ||
@@ -509,0 +504,0 @@ ...ctx.warnings, |
@@ -1,11 +0,6 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.filterExtractionResult = exports.extractKeysOfFiles = exports.extractKeysFromFile = exports.NullNamespace = void 0; | ||
const glob_1 = require("glob"); | ||
const worker_1 = require("./worker"); | ||
const util_1 = require("util"); | ||
const glob = (0, util_1.promisify)(glob_1.glob); | ||
exports.NullNamespace = Symbol('namespace.null'); | ||
async function extractKeysFromFile(file, extractor) { | ||
return (0, worker_1.callWorker)({ | ||
import { glob } from 'glob'; | ||
import { callWorker } from './worker.js'; | ||
export const NullNamespace = Symbol('namespace.null'); | ||
export async function extractKeysFromFile(file, extractor) { | ||
return callWorker({ | ||
extractor: extractor, | ||
@@ -15,4 +10,3 @@ file: file, | ||
} | ||
exports.extractKeysFromFile = extractKeysFromFile; | ||
async function extractKeysOfFiles(filesPattern, extractor) { | ||
export async function extractKeysOfFiles(filesPattern, extractor) { | ||
const files = await glob(filesPattern, { nodir: true }); | ||
@@ -26,8 +20,7 @@ const result = new Map(); | ||
} | ||
exports.extractKeysOfFiles = extractKeysOfFiles; | ||
function filterExtractionResult(data) { | ||
export function filterExtractionResult(data) { | ||
const result = Object.create(null); | ||
for (const { keys } of data.values()) { | ||
for (const key of keys) { | ||
const namespace = key.namespace || exports.NullNamespace; | ||
const namespace = key.namespace || NullNamespace; | ||
if (!(namespace in result)) { | ||
@@ -41,2 +34,1 @@ result[namespace] = new Map(); | ||
} | ||
exports.filterExtractionResult = filterExtractionResult; |
@@ -1,12 +0,11 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const path_1 = require("path"); | ||
const promises_1 = require("fs/promises"); | ||
const vscode_textmate_1 = require("vscode-textmate"); | ||
const vscode_oniguruma_1 = require("vscode-oniguruma"); | ||
const GRAMMAR_PATH = (0, path_1.join)(__dirname, '..', '..', 'textmate'); | ||
import { extname } from 'path'; | ||
import { readFile } from 'fs/promises'; | ||
import { createRequire } from 'module'; | ||
import TextMate from 'vscode-textmate'; | ||
import Oniguruma from 'vscode-oniguruma'; | ||
const GRAMMAR_PATH = new URL('../../textmate/', import.meta.url); | ||
const GrammarFiles = { | ||
["source.ts" /* Grammar.TYPESCRIPT */]: (0, path_1.join)(GRAMMAR_PATH, 'TypeScript.tmLanguage'), | ||
["source.tsx" /* Grammar.TYPESCRIPT_TSX */]: (0, path_1.join)(GRAMMAR_PATH, 'TypeScriptReact.tmLanguage'), | ||
["source.svelte" /* Grammar.SVELTE */]: (0, path_1.join)(GRAMMAR_PATH, 'Svelte.tmLanguage'), | ||
["source.ts" /* Grammar.TYPESCRIPT */]: new URL('TypeScript.tmLanguage', GRAMMAR_PATH), | ||
["source.tsx" /* Grammar.TYPESCRIPT_TSX */]: new URL('TypeScriptReact.tmLanguage', GRAMMAR_PATH), | ||
["source.svelte" /* Grammar.SVELTE */]: new URL('Svelte.tmLanguage', GRAMMAR_PATH), | ||
}; | ||
@@ -16,10 +15,11 @@ let oniguruma; | ||
async function initializeOniguruma() { | ||
const require = createRequire(import.meta.url); | ||
const wasmBlobPath = require | ||
.resolve('vscode-oniguruma') | ||
.replace('main.js', 'onig.wasm'); | ||
const wasmBlob = await (0, promises_1.readFile)(wasmBlobPath); | ||
await (0, vscode_oniguruma_1.loadWASM)(wasmBlob); | ||
const wasmBlob = await readFile(wasmBlobPath); | ||
await Oniguruma.loadWASM(wasmBlob); | ||
return { | ||
createOnigScanner: (patterns) => new vscode_oniguruma_1.OnigScanner(patterns), | ||
createOnigString: (s) => new vscode_oniguruma_1.OnigString(s), | ||
createOnigScanner: (patterns) => new Oniguruma.OnigScanner(patterns), | ||
createOnigString: (s) => new Oniguruma.OnigString(s), | ||
}; | ||
@@ -31,6 +31,6 @@ } | ||
return null; | ||
const grammar = await (0, promises_1.readFile)(file, 'utf8'); | ||
const grammar = await readFile(file, 'utf8'); | ||
return grammar.startsWith('{') | ||
? JSON.parse(grammar) | ||
: (0, vscode_textmate_1.parseRawGrammar)(grammar); | ||
: TextMate.parseRawGrammar(grammar); | ||
} | ||
@@ -54,3 +54,3 @@ function extnameToGrammar(extname) { | ||
function tokenize(code, grammar) { | ||
let stack = vscode_textmate_1.INITIAL; | ||
let stack = TextMate.INITIAL; | ||
let linePtr = 0; | ||
@@ -90,7 +90,7 @@ const lines = code.split('\n'); | ||
} | ||
async function default_1(code, fileName) { | ||
export default async function (code, fileName) { | ||
if (!oniguruma) { | ||
// Lazily initialize the WebAssembly runtime | ||
oniguruma = initializeOniguruma(); | ||
registry = new vscode_textmate_1.Registry({ | ||
registry = new TextMate.Registry({ | ||
onigLib: oniguruma, | ||
@@ -100,3 +100,3 @@ loadGrammar: loadGrammar, | ||
} | ||
const fileType = (0, path_1.extname)(fileName); | ||
const fileType = extname(fileName); | ||
const grammarName = extnameToGrammar(fileType); | ||
@@ -112,2 +112,1 @@ if (!grammarName) { | ||
} | ||
exports.default = default_1; |
@@ -1,6 +0,3 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.emitGitHubWarning = exports.dumpWarnings = exports.WarningMessages = void 0; | ||
const path_1 = require("path"); | ||
exports.WarningMessages = { | ||
import { relative } from 'path'; | ||
export const WarningMessages = { | ||
W_DYNAMIC_KEY: { | ||
@@ -45,3 +42,3 @@ name: 'Dynamic key', | ||
*/ | ||
function dumpWarnings(extractionResult) { | ||
export function dumpWarnings(extractionResult) { | ||
let warningCount = 0; | ||
@@ -55,4 +52,4 @@ for (const [file, { warnings }] of extractionResult.entries()) { | ||
for (const warning of warnings) { | ||
const warnText = warning.warning in exports.WarningMessages | ||
? exports.WarningMessages[warning.warning].name | ||
const warnText = warning.warning in WarningMessages | ||
? WarningMessages[warning.warning].name | ||
: warning.warning; | ||
@@ -70,9 +67,8 @@ console.error('\tline %d: %s', warning.line, warnText); | ||
} | ||
exports.dumpWarnings = dumpWarnings; | ||
function emitGitHubWarning(warning, file, line) { | ||
export function emitGitHubWarning(warning, file, line) { | ||
if (!process.env.GITHUB_ACTIONS) | ||
return; | ||
file = (0, path_1.relative)(process.env.GITHUB_WORKSPACE ?? process.cwd(), file); | ||
if (warning in exports.WarningMessages) { | ||
const { name, description } = exports.WarningMessages[warning]; | ||
file = relative(process.env.GITHUB_WORKSPACE ?? process.cwd(), file); | ||
if (warning in WarningMessages) { | ||
const { name, description } = WarningMessages[warning]; | ||
const encodedDescription = description | ||
@@ -90,2 +86,1 @@ .replaceAll('%', '%25') | ||
} | ||
exports.emitGitHubWarning = emitGitHubWarning; |
@@ -1,14 +0,8 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.callWorker = void 0; | ||
const path_1 = require("path"); | ||
const worker_threads_1 = require("worker_threads"); | ||
const promises_1 = require("fs/promises"); | ||
const extractor_1 = __importDefault(require("./extractor")); | ||
const moduleLoader_1 = require("../utils/moduleLoader"); | ||
const deferred_1 = require("../utils/deferred"); | ||
const IS_TS_NODE = (0, path_1.extname)(__filename) === '.ts'; | ||
import { resolve, extname } from 'path'; | ||
import { Worker, isMainThread, parentPort } from 'worker_threads'; | ||
import { readFile } from 'fs/promises'; | ||
import internalExtractor from './extractor.js'; | ||
import { loadModule } from '../utils/moduleLoader.js'; | ||
import { createDeferred } from '../utils/deferred.js'; | ||
const IS_TS_NODE = extname(import.meta.url) === '.ts'; | ||
// --- Worker functions | ||
@@ -21,17 +15,17 @@ let loadedExtractor = Symbol('unloaded'); | ||
extractor = args.extractor | ||
? await (0, moduleLoader_1.loadModule)(args.extractor).then((mdl) => mdl.default) | ||
: extractor_1.default; | ||
? await loadModule(args.extractor).then((mdl) => mdl.default) | ||
: internalExtractor; | ||
} | ||
const file = (0, path_1.resolve)(args.file); | ||
const code = await (0, promises_1.readFile)(file, 'utf8'); | ||
const file = resolve(args.file); | ||
const code = await readFile(file, 'utf8'); | ||
return extractor(code, file); | ||
} | ||
async function workerInit() { | ||
worker_threads_1.parentPort.on('message', (params) => { | ||
parentPort.on('message', (params) => { | ||
handleJob(params) | ||
.then((res) => worker_threads_1.parentPort.postMessage({ data: res })) | ||
.catch((e) => worker_threads_1.parentPort.postMessage({ err: e })); | ||
.then((res) => parentPort.postMessage({ data: res })) | ||
.catch((e) => parentPort.postMessage({ err: e })); | ||
}); | ||
} | ||
if (!worker_threads_1.isMainThread) | ||
if (!isMainThread) | ||
workerInit(); | ||
@@ -42,6 +36,8 @@ // --- Main thread functions | ||
function createWorker() { | ||
const worker = new worker_threads_1.Worker(__filename, { | ||
// ts-node workaround | ||
execArgv: IS_TS_NODE ? ['--require', 'ts-node/register'] : undefined, | ||
}); | ||
const worker = IS_TS_NODE | ||
? new Worker(new URL(import.meta.url).pathname.replace('.ts', '.js'), { | ||
// ts-node workaround | ||
execArgv: ['--require', 'ts-node/register'], | ||
}) | ||
: new Worker(new URL(import.meta.url).pathname); | ||
let timeout; | ||
@@ -75,4 +71,4 @@ let currentDeferred; | ||
} | ||
async function callWorker(params) { | ||
const deferred = (0, deferred_1.createDeferred)(); | ||
export async function callWorker(params) { | ||
const deferred = createDeferred(); | ||
jobQueue.push([params, deferred]); | ||
@@ -84,2 +80,1 @@ if (!worker) { | ||
} | ||
exports.callWorker = callWorker; |
#!/usr/bin/env node | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const commander_1 = require("commander"); | ||
const ansi_colors_1 = __importDefault(require("ansi-colors")); | ||
const credentials_1 = require("./config/credentials"); | ||
const tolgeerc_1 = __importDefault(require("./config/tolgeerc")); | ||
const client_1 = __importDefault(require("./client")); | ||
const errors_1 = require("./client/errors"); | ||
const logger_1 = require("./utils/logger"); | ||
const options_1 = require("./options"); | ||
const constants_1 = require("./constants"); | ||
const login_1 = require("./commands/login"); | ||
const push_1 = __importDefault(require("./commands/push")); | ||
const pull_1 = __importDefault(require("./commands/pull")); | ||
const extract_1 = __importDefault(require("./commands/extract")); | ||
const compare_1 = __importDefault(require("./commands/sync/compare")); | ||
const sync_1 = __importDefault(require("./commands/sync/sync")); | ||
import { Command } from 'commander'; | ||
import ansi from 'ansi-colors'; | ||
import { getApiKey, savePak, savePat } from './config/credentials.js'; | ||
import loadTolgeeRc from './config/tolgeerc.js'; | ||
import RestClient from './client/index.js'; | ||
import { HttpError } from './client/errors.js'; | ||
import { setDebug, isDebugEnabled, debug, info, error, } from './utils/logger.js'; | ||
import { API_KEY_OPT, API_URL_OPT, PROJECT_ID_OPT } from './options.js'; | ||
import { API_KEY_PAK_PREFIX, API_KEY_PAT_PREFIX, VERSION, } from './constants.js'; | ||
import { Login, Logout } from './commands/login.js'; | ||
import PushCommand from './commands/push.js'; | ||
import PullCommand from './commands/pull.js'; | ||
import ExtractCommand from './commands/extract.js'; | ||
import CompareCommand from './commands/sync/compare.js'; | ||
import SyncCommand from './commands/sync/sync.js'; | ||
const NO_KEY_COMMANDS = ['login', 'logout', 'extract']; | ||
ansi_colors_1.default.enabled = process.stdout.isTTY; | ||
ansi.enabled = process.stdout.isTTY; | ||
function topLevelName(command) { | ||
@@ -36,3 +31,3 @@ return command.parent && command.parent.parent | ||
// This is not done as part of the init routine or via the mandatory flag, as this is dependent on the API URL. | ||
const key = await (0, credentials_1.getApiKey)(opts.apiUrl, opts.projectId); | ||
const key = await getApiKey(opts.apiUrl, opts.projectId); | ||
// No key in store, stop here. | ||
@@ -43,7 +38,7 @@ if (!key) | ||
program.setOptionValue('_removeApiKeyFromStore', () => { | ||
if (key.startsWith(constants_1.API_KEY_PAT_PREFIX)) { | ||
(0, credentials_1.savePat)(opts.apiUrl); | ||
if (key.startsWith(API_KEY_PAT_PREFIX)) { | ||
savePat(opts.apiUrl); | ||
} | ||
else { | ||
(0, credentials_1.savePak)(opts.apiUrl, opts.projectId); | ||
savePak(opts.apiUrl, opts.projectId); | ||
} | ||
@@ -54,10 +49,10 @@ }); | ||
const opts = cmd.optsWithGlobals(); | ||
if (opts.apiKey.startsWith(constants_1.API_KEY_PAK_PREFIX)) { | ||
if (opts.apiKey?.startsWith(API_KEY_PAK_PREFIX)) { | ||
// Parse the key and ensure we can access the specified Project ID | ||
const projectId = client_1.default.projectIdFromKey(opts.apiKey); | ||
const projectId = RestClient.projectIdFromKey(opts.apiKey); | ||
program.setOptionValue('projectId', projectId); | ||
if (opts.projectId !== -1 && opts.projectId !== projectId) { | ||
(0, logger_1.error)('The specified API key cannot be used to perform operations on the specified project.'); | ||
(0, logger_1.info)(`The API key you specified is tied to project #${projectId}, you tried to perform operations on project #${opts.projectId}.`); | ||
(0, logger_1.info)('Learn more about how API keys in Tolgee work here: https://tolgee.io/platform/account_settings/api_keys_and_pat_tokens'); | ||
error('The specified API key cannot be used to perform operations on the specified project.'); | ||
info(`The API key you specified is tied to project #${projectId}, you tried to perform operations on project #${opts.projectId}.`); | ||
info('Learn more about how API keys in Tolgee work here: https://tolgee.io/platform/account_settings/api_keys_and_pat_tokens'); | ||
process.exit(1); | ||
@@ -70,8 +65,8 @@ } | ||
if (opts.projectId === -1) { | ||
(0, logger_1.error)('No Project ID have been specified. You must either provide one via --project-ir, or by setting up a `.tolgeerc` file.'); | ||
(0, logger_1.info)('Learn more about configuring the CLI here: https://tolgee.io/tolgee-cli/project-configuration'); | ||
error('No Project ID have been specified. You must either provide one via --project-id, or by setting up a `.tolgeerc` file.'); | ||
info('Learn more about configuring the CLI here: https://tolgee.io/tolgee-cli/project-configuration'); | ||
process.exit(1); | ||
} | ||
if (!opts.apiKey) { | ||
(0, logger_1.error)('No API key has been provided. You must either provide one via --api-key, or login via `tolgee login`.'); | ||
error('No API key has been provided. You must either provide one via --api-key, or login via `tolgee login`.'); | ||
process.exit(1); | ||
@@ -86,3 +81,3 @@ } | ||
const opts = cmd.optsWithGlobals(); | ||
const client = new client_1.default({ | ||
const client = new RestClient({ | ||
apiUrl: opts.apiUrl, | ||
@@ -95,7 +90,7 @@ apiKey: opts.apiKey, | ||
// Apply verbosity | ||
(0, logger_1.setDebug)(prog.opts().verbose); | ||
setDebug(prog.opts().verbose); | ||
} | ||
const program = new commander_1.Command('tolgee') | ||
.version(constants_1.VERSION) | ||
.configureOutput({ writeErr: logger_1.error }) | ||
const program = new Command('tolgee') | ||
.version(VERSION) | ||
.configureOutput({ writeErr: error }) | ||
.description('Command Line Interface to interact with the Tolgee Platform') | ||
@@ -105,15 +100,15 @@ .option('-v, --verbose', 'Enable verbose logging.') | ||
// Global options | ||
program.addOption(options_1.API_URL_OPT); | ||
program.addOption(options_1.API_KEY_OPT); | ||
program.addOption(options_1.PROJECT_ID_OPT); | ||
program.addOption(API_URL_OPT); | ||
program.addOption(API_KEY_OPT); | ||
program.addOption(PROJECT_ID_OPT); | ||
// Register commands | ||
program.addCommand(login_1.Login); | ||
program.addCommand(login_1.Logout); | ||
program.addCommand(push_1.default); | ||
program.addCommand(pull_1.default); | ||
program.addCommand(extract_1.default); | ||
program.addCommand(compare_1.default); | ||
program.addCommand(sync_1.default); | ||
program.addCommand(Login); | ||
program.addCommand(Logout); | ||
program.addCommand(PushCommand); | ||
program.addCommand(PullCommand); | ||
program.addCommand(ExtractCommand); | ||
program.addCommand(CompareCommand); | ||
program.addCommand(SyncCommand); | ||
async function loadConfig() { | ||
const tgConfig = await (0, tolgeerc_1.default)(); | ||
const tgConfig = await loadTolgeeRc(); | ||
if (tgConfig) { | ||
@@ -126,5 +121,5 @@ for (const [key, value] of Object.entries(tgConfig)) { | ||
async function handleHttpError(e) { | ||
(0, logger_1.error)('An error occurred while requesting the API.'); | ||
(0, logger_1.error)(`${e.request.method} ${e.request.url}`); | ||
(0, logger_1.error)(e.getErrorText()); | ||
error('An error occurred while requesting the API.'); | ||
error(`${e.request.method} ${e.request.url}`); | ||
error(e.getErrorText()); | ||
// Remove token from store if necessary | ||
@@ -134,3 +129,3 @@ if (e.response.status === 401) { | ||
if (removeFn) { | ||
(0, logger_1.info)('Removing the API key from the authentication store.'); | ||
info('Removing the API key from the authentication store.'); | ||
removeFn(); | ||
@@ -140,3 +135,3 @@ } | ||
// Print server output for server errors | ||
if ((0, logger_1.isDebugEnabled)()) { | ||
if (isDebugEnabled()) { | ||
// We cannot parse the response as JSON and pull error codes here as we may be here due to a 5xx error: | ||
@@ -148,3 +143,3 @@ // by nature 5xx class errors can happen for a lot of reasons (e.g. upstream issues, server issues, | ||
const res = await e.response.text(); | ||
(0, logger_1.debug)(`Server response:\n\n---\n${res}\n---`); | ||
debug(`Server response:\n\n---\n${res}\n---`); | ||
} | ||
@@ -158,3 +153,3 @@ } | ||
catch (e) { | ||
if (e instanceof errors_1.HttpError) { | ||
if (e instanceof HttpError) { | ||
await handleHttpError(e); | ||
@@ -167,4 +162,4 @@ process.exit(1); | ||
// - Something went wrong with the code | ||
(0, logger_1.error)('An unexpected error occurred while running the command.'); | ||
(0, logger_1.error)('Please report this to our issue tracker: https://github.com/tolgee/tolgee-cli/issues'); | ||
error('An unexpected error occurred while running the command.'); | ||
error('Please report this to our issue tracker: https://github.com/tolgee/tolgee-cli/issues'); | ||
console.log(e.stack); | ||
@@ -171,0 +166,0 @@ process.exit(1); |
@@ -1,12 +0,9 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.EXTRACTOR = exports.API_URL_OPT = exports.PROJECT_ID_OPT = exports.API_KEY_OPT = void 0; | ||
const fs_1 = require("fs"); | ||
const path_1 = require("path"); | ||
const commander_1 = require("commander"); | ||
const constants_1 = require("./constants"); | ||
import { existsSync } from 'fs'; | ||
import { resolve } from 'path'; | ||
import { Option, InvalidArgumentError } from 'commander'; | ||
import { DEFAULT_API_URL } from './constants.js'; | ||
function parseProjectId(v) { | ||
const val = Number(v); | ||
if (!Number.isInteger(val) || val < 1) { | ||
throw new commander_1.InvalidArgumentError('Not a valid project ID.'); | ||
throw new InvalidArgumentError('Not a valid project ID.'); | ||
} | ||
@@ -20,19 +17,19 @@ return val; | ||
catch { | ||
throw new commander_1.InvalidArgumentError('Malformed URL.'); | ||
throw new InvalidArgumentError('Malformed URL.'); | ||
} | ||
} | ||
function parsePath(v) { | ||
const path = (0, path_1.resolve)(v); | ||
if (!(0, fs_1.existsSync)(path)) { | ||
throw new commander_1.InvalidArgumentError(`The specified path "${v}" does not exist.`); | ||
const path = resolve(v); | ||
if (!existsSync(path)) { | ||
throw new InvalidArgumentError(`The specified path "${v}" does not exist.`); | ||
} | ||
return path; | ||
} | ||
exports.API_KEY_OPT = new commander_1.Option('-ak, --api-key <key>', 'Tolgee API Key. Can be a Project API Key or a Personal Access Token.').env('TOLGEE_API_KEY'); | ||
exports.PROJECT_ID_OPT = new commander_1.Option('-p, --project-id <id>', 'Project ID. Only required when using a Personal Access Token.') | ||
export const API_KEY_OPT = new Option('-ak, --api-key <key>', 'Tolgee API Key. Can be a Project API Key or a Personal Access Token.').env('TOLGEE_API_KEY'); | ||
export const PROJECT_ID_OPT = new Option('-p, --project-id <id>', 'Project ID. Only required when using a Personal Access Token.') | ||
.default(-1) | ||
.argParser(parseProjectId); | ||
exports.API_URL_OPT = new commander_1.Option('-au, --api-url <url>', 'The url of Tolgee API.') | ||
.default(constants_1.DEFAULT_API_URL) | ||
export const API_URL_OPT = new Option('-au, --api-url <url>', 'The url of Tolgee API.') | ||
.default(DEFAULT_API_URL) | ||
.argParser(parseUrlArgument); | ||
exports.EXTRACTOR = new commander_1.Option('-e, --extractor <extractor>', `A path to a custom extractor to use instead of the default one.`).argParser(parsePath); | ||
export const EXTRACTOR = new Option('-e, --extractor <extractor>', `A path to a custom extractor to use instead of the default one.`).argParser(parsePath); |
@@ -1,11 +0,5 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.askBoolean = exports.askString = void 0; | ||
const readline_1 = __importDefault(require("readline")); // readline/promises is Node 17, currently supporting Node 16+ | ||
async function askString(question) { | ||
import readline from 'readline'; // readline/promises is Node 17, currently supporting Node 16+ | ||
export async function askString(question) { | ||
return new Promise((resolve) => { | ||
const rl = readline_1.default.createInterface({ | ||
const rl = readline.createInterface({ | ||
input: process.stdin, | ||
@@ -20,4 +14,3 @@ output: process.stdout, | ||
} | ||
exports.askString = askString; | ||
async function askBoolean(question, def = false) { | ||
export async function askBoolean(question, def = false) { | ||
const yn = def === true ? '[Y/n]' : '[y/N]'; | ||
@@ -35,2 +28,1 @@ let res = def; | ||
} | ||
exports.askBoolean = askBoolean; |
@@ -1,17 +0,17 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const os_1 = require("os"); | ||
const path_1 = require("path"); | ||
function getConfigPath() { | ||
import { homedir } from 'os'; | ||
import { resolve } from 'path'; | ||
export default function getConfigPath() { | ||
if (process.env.TOLGEE_CLI_CONFIG_PATH) { | ||
return process.env.TOLGEE_CLI_CONFIG_PATH; | ||
} | ||
switch (process.platform) { | ||
case 'win32': | ||
return (0, path_1.resolve)(process.env.APPDATA, 'tolgee'); | ||
return resolve(process.env.APPDATA, 'tolgee'); | ||
case 'darwin': | ||
return (0, path_1.resolve)((0, os_1.homedir)(), 'Library', 'Application Support', 'tolgee'); | ||
return resolve(homedir(), 'Library', 'Application Support', 'tolgee'); | ||
default: | ||
return process.env.XDG_CONFIG_HOME | ||
? (0, path_1.resolve)(process.env.XDG_CONFIG_HOME, 'tolgee') | ||
: (0, path_1.resolve)((0, os_1.homedir)(), '.config', 'tolgee'); | ||
? resolve(process.env.XDG_CONFIG_HOME, 'tolgee') | ||
: resolve(homedir(), '.config', 'tolgee'); | ||
} | ||
} | ||
exports.default = getConfigPath; |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createDeferred = void 0; | ||
function createDeferred() { | ||
export function createDeferred() { | ||
const deferred = {}; | ||
@@ -11,2 +8,1 @@ deferred.promise = new Promise((resolve, reject) => { | ||
} | ||
exports.createDeferred = createDeferred; |
@@ -1,4 +0,1 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.loading = exports.error = exports.warn = exports.success = exports.info = exports.debug = exports.isDebugEnabled = exports.setDebug = void 0; | ||
const SYMBOLS = [' ๐', ' ๐ ', ' ๐ ', '๐ ']; | ||
@@ -11,6 +8,5 @@ let debugEnabled = false; | ||
*/ | ||
function setDebug(enabled) { | ||
export function setDebug(enabled) { | ||
debugEnabled = enabled; | ||
} | ||
exports.setDebug = setDebug; | ||
/** | ||
@@ -21,6 +17,5 @@ * Gets the current status of debug logging. | ||
*/ | ||
function isDebugEnabled() { | ||
export function isDebugEnabled() { | ||
return debugEnabled; | ||
} | ||
exports.isDebugEnabled = isDebugEnabled; | ||
/** | ||
@@ -31,3 +26,3 @@ * Logs a debug message to the console if debugging is enabled. | ||
*/ | ||
function debug(msg) { | ||
export function debug(msg) { | ||
if (debugEnabled) { | ||
@@ -37,3 +32,2 @@ console.log(`โช ${msg}`); | ||
} | ||
exports.debug = debug; | ||
/** | ||
@@ -44,6 +38,5 @@ * Logs an informative message to the console. | ||
*/ | ||
function info(msg) { | ||
export function info(msg) { | ||
console.log(`๐ต ${msg}`); | ||
} | ||
exports.info = info; | ||
/** | ||
@@ -54,6 +47,5 @@ * Logs a success to the console. | ||
*/ | ||
function success(msg) { | ||
export function success(msg) { | ||
console.log(`โ ${msg}`); | ||
} | ||
exports.success = success; | ||
/** | ||
@@ -64,6 +56,5 @@ * Logs a warning message to the console. | ||
*/ | ||
function warn(msg) { | ||
export function warn(msg) { | ||
console.log(`๐ก ${msg}`); | ||
} | ||
exports.warn = warn; | ||
/** | ||
@@ -74,6 +65,5 @@ * Logs an error message to the console. | ||
*/ | ||
function error(msg) { | ||
export function error(msg) { | ||
console.log(`๐ด ${msg}`); | ||
} | ||
exports.error = error; | ||
/** | ||
@@ -86,3 +76,3 @@ * Shows a loading indicator for a Promise until it resolves. | ||
*/ | ||
function loading(comment, promise) { | ||
export function loading(comment, promise) { | ||
if (!process.stdout.isTTY) { | ||
@@ -108,2 +98,1 @@ // Simple stdout without animations | ||
} | ||
exports.loading = loading; |
@@ -1,14 +0,7 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.loadModule = void 0; | ||
const path_1 = require("path"); | ||
import { extname } from 'path'; | ||
let tsService; | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
function realImport(file) { | ||
return eval('import(file)'); | ||
} | ||
async function registerTsNode() { | ||
if (!tsService) { | ||
try { | ||
const tsNode = require('ts-node'); | ||
const tsNode = await import('ts-node'); | ||
tsService = tsNode.register({ compilerOptions: { module: 'CommonJS' } }); | ||
@@ -25,16 +18,16 @@ } | ||
async function importTypeScript(file) { | ||
if ((0, path_1.extname)(__filename) === '.ts') { | ||
return require(file); | ||
if (extname(import.meta.url) === '.ts') { | ||
return import(file); | ||
} | ||
await registerTsNode(); | ||
tsService.enabled(true); | ||
const mdl = await realImport(file); | ||
const mdl = await import(file); | ||
tsService.enabled(false); | ||
return mdl; | ||
} | ||
async function loadModule(module) { | ||
export async function loadModule(module) { | ||
if (module.endsWith('.ts')) { | ||
return importTypeScript(module); | ||
} | ||
const mdl = await realImport(module); | ||
const mdl = await import(module); | ||
if (mdl.default?.default) { | ||
@@ -45,2 +38,1 @@ return mdl.default; | ||
} | ||
exports.loadModule = loadModule; |
@@ -1,13 +0,10 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.overwriteDir = void 0; | ||
const path_1 = require("path"); | ||
const promises_1 = require("fs/promises"); | ||
const ask_1 = require("./ask"); | ||
const logger_1 = require("./logger"); | ||
async function overwriteDir(path, overwrite) { | ||
import { resolve } from 'path'; | ||
import { stat, rm, mkdir } from 'fs/promises'; | ||
import { askBoolean } from './ask.js'; | ||
import { warn, error } from './logger.js'; | ||
export async function overwriteDir(path, overwrite) { | ||
try { | ||
const stats = await (0, promises_1.stat)(path); | ||
const stats = await stat(path); | ||
if (!stats.isDirectory()) { | ||
(0, logger_1.error)('The specified path already exists and is not a directory.'); | ||
error('The specified path already exists and is not a directory.'); | ||
process.exit(1); | ||
@@ -17,13 +14,13 @@ } | ||
if (!process.stdout.isTTY) { | ||
(0, logger_1.error)('The specified path already exists.'); | ||
error('The specified path already exists.'); | ||
process.exit(1); | ||
} | ||
(0, logger_1.warn)(`The specified path ${(0, path_1.resolve)(path)} already exists.`); | ||
const userOverwrite = await (0, ask_1.askBoolean)('Do you want to overwrite data? *BE CAREFUL, ALL THE CONTENTS OF THE DESTINATION FOLDER WILL BE DESTROYED*.'); | ||
warn(`The specified path ${resolve(path)} already exists.`); | ||
const userOverwrite = await askBoolean('Do you want to overwrite data? *BE CAREFUL, ALL THE CONTENTS OF THE DESTINATION FOLDER WILL BE DESTROYED*.'); | ||
if (!userOverwrite) { | ||
(0, logger_1.error)('Aborting.'); | ||
error('Aborting.'); | ||
process.exit(1); | ||
} | ||
// Purge data as requested. | ||
await (0, promises_1.rm)(path, { recursive: true }); | ||
await rm(path, { recursive: true }); | ||
} | ||
@@ -37,4 +34,3 @@ } | ||
// Create the directory | ||
await (0, promises_1.mkdir)(path, { recursive: true }); | ||
await mkdir(path, { recursive: true }); | ||
} | ||
exports.overwriteDir = overwriteDir; |
@@ -1,8 +0,5 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.unzip = exports.unzipBuffer = void 0; | ||
const fs_1 = require("fs"); | ||
const promises_1 = require("fs/promises"); | ||
const path_1 = require("path"); | ||
const yauzl_1 = require("yauzl"); | ||
import { createWriteStream } from 'fs'; | ||
import { mkdir } from 'fs/promises'; | ||
import { join, dirname } from 'path'; | ||
import { fromBuffer } from 'yauzl'; | ||
const ZIP_PARSER_OPTS = { | ||
@@ -17,3 +14,3 @@ strictFileNames: true, | ||
throw err; | ||
const writeStream = (0, fs_1.createWriteStream)(dest); | ||
const writeStream = createWriteStream(dest); | ||
stream.pipe(writeStream); | ||
@@ -30,7 +27,7 @@ // Unlock reading loop | ||
*/ | ||
function unzipBuffer(zipBlob, dest) { | ||
export function unzipBuffer(zipBlob, dest) { | ||
return new Promise((resolve, reject) => { | ||
zipBlob.arrayBuffer().then((buffer) => { | ||
const nodeBuffer = Buffer.from(buffer); | ||
(0, yauzl_1.fromBuffer)(nodeBuffer, ZIP_PARSER_OPTS, (err, zip) => { | ||
fromBuffer(nodeBuffer, ZIP_PARSER_OPTS, (err, zip) => { | ||
if (err) { | ||
@@ -44,3 +41,2 @@ return reject(err); | ||
} | ||
exports.unzipBuffer = unzipBuffer; | ||
/** | ||
@@ -52,3 +48,3 @@ * Unzips a ZIP file loaded in memory to a destination on disk. | ||
*/ | ||
function unzip(zip, dest) { | ||
export function unzip(zip, dest) { | ||
// Enforce expected & security options. | ||
@@ -75,7 +71,7 @@ // Lazy entries is what this reader is based upon. | ||
} | ||
const entryPath = (0, path_1.join)(dest, entry.fileName); | ||
const entryPath = join(dest, entry.fileName); | ||
// Handle directory creation | ||
const entryDirName = (0, path_1.dirname)(entryPath); | ||
const entryDirName = dirname(entryPath); | ||
if (!seenDirectories.has(entryDirName)) { | ||
(0, promises_1.mkdir)(entryDirName, { recursive: true }).then(() => dumpFile(zip, entry, entryPath)); | ||
mkdir(entryDirName, { recursive: true }).then(() => dumpFile(zip, entry, entryPath)); | ||
} | ||
@@ -88,2 +84,1 @@ else { | ||
} | ||
exports.unzip = unzip; |
{ | ||
"name": "@tolgee/cli", | ||
"version": "1.1.0", | ||
"type": "commonjs", | ||
"version": "1.1.1", | ||
"type": "module", | ||
"description": "A tool to interact with the Tolgee Platform through CLI", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/tolgee/tolgee-cli.git" | ||
}, | ||
"bin": { | ||
@@ -12,13 +16,13 @@ "tolgee": "./dist/index.js" | ||
"test": "npm run test:unit && npm run test:e2e && npm run test:package", | ||
"test:unit": "jest -c jest.unit.config.ts", | ||
"test:unit": "cross-env NODE_OPTIONS=\"--experimental-vm-modules\" jest -c jest.unit.config.ts", | ||
"pretest:e2e": "npm run build && npm run tolgee:start", | ||
"posttest:e2e": "npm run tolgee:stop", | ||
"test:e2e": "jest -c jest.e2e.config.ts --runInBand", | ||
"test:e2e-run": "jest -c jest.e2e.config.ts --runInBand", | ||
"test:package": "node scripts/validatePackage.mjs", | ||
"tolgee:start": "node scripts/startDocker.mjs", | ||
"test:e2e": "cross-env NODE_OPTIONS=\"--experimental-vm-modules\" jest -c jest.e2e.config.ts --runInBand", | ||
"test:e2e-run": "cross-env NODE_OPTIONS=\"--experimental-vm-modules\" jest -c jest.e2e.config.ts --runInBand", | ||
"test:package": "node scripts/validatePackage.js", | ||
"tolgee:start": "node scripts/startDocker.js", | ||
"tolgee:stop": "docker stop tolgee_cli_e2e", | ||
"lint": "eslint --ext .ts --ext .js --ext .mjs ./src ./test ./scripts jest.config.ts jest.*.config.ts", | ||
"lint": "eslint --ext .ts --ext .js --ext .cjs ./src ./test ./scripts jest.config.ts jest.*.config.ts", | ||
"prettier": "prettier --write ./src ./test ./scripts jest.config.ts jest.*.config.ts", | ||
"run-dev": "ts-node ./src/index.ts", | ||
"run-dev": "cross-env NODE_OPTIONS=\"--loader=ts-node/esm\" node ./src/index.ts", | ||
"schema": "openapi-typescript http://localhost:22222/v3/api-docs/All%20Internal%20-%20for%20Tolgee%20Web%20application --output src/client/internal/schema.generated.ts", | ||
@@ -32,35 +36,34 @@ "release": "semantic-release" | ||
"base32-decode": "^1.0.0", | ||
"commander": "^10.0.0", | ||
"cosmiconfig": "^8.0.0", | ||
"commander": "^10.0.1", | ||
"cosmiconfig": "^8.1.3", | ||
"form-data": "^4.0.0", | ||
"glob": "^8.1.0", | ||
"glob": "^10.2.5", | ||
"json5": "^2.2.3", | ||
"undici": "^5.15.0", | ||
"undici": "^5.22.1", | ||
"vscode-oniguruma": "^1.7.0", | ||
"vscode-textmate": "^8.0.0", | ||
"xstate": "^4.35.2", | ||
"vscode-textmate": "^9.0.0", | ||
"xstate": "^4.37.2", | ||
"yauzl": "^2.10.0" | ||
}, | ||
"devDependencies": { | ||
"@jest/types": "^29.3.1", | ||
"@semantic-release/changelog": "^6.0.2", | ||
"@semantic-release/changelog": "^6.0.3", | ||
"@semantic-release/git": "^10.0.1", | ||
"@types/glob": "^8.0.0", | ||
"@types/jest": "^29.2.5", | ||
"@types/node": "^18.11.18", | ||
"@types/jest": "^29.5.1", | ||
"@types/node": "^20.2.1", | ||
"@types/yauzl": "^2.10.0", | ||
"@typescript-eslint/eslint-plugin": "^5.59.1", | ||
"@typescript-eslint/parser": "^5.59.1", | ||
"eslint": "^8.39.0", | ||
"@typescript-eslint/eslint-plugin": "^5.59.6", | ||
"@typescript-eslint/parser": "^5.59.6", | ||
"cross-env": "^7.0.3", | ||
"eslint": "^8.40.0", | ||
"eslint-plugin-jest": "^27.2.1", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"jest": "^29.3.1", | ||
"jest": "^29.5.0", | ||
"js-yaml": "^4.1.0", | ||
"openapi-typescript": "^6.1.0", | ||
"prettier": "^2.8.3", | ||
"rimraf": "^4.0.7", | ||
"semantic-release": "^20.0.2", | ||
"ts-jest": "^29.0.5", | ||
"openapi-typescript": "^6.2.4", | ||
"prettier": "^2.8.8", | ||
"rimraf": "^5.0.1", | ||
"semantic-release": "^21.0.2", | ||
"ts-jest": "^29.1.0", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^4.9.4" | ||
"typescript": "^5.0.4" | ||
}, | ||
@@ -67,0 +70,0 @@ "engines": { |
# Tolgee CLI ๐ | ||
An experimental ๐งช command line tool to interact with Tolgee directly from your terminal. | ||
A CLI tool to interact with Tolgee directly from your terminal. | ||
The CLI lets you pull strings from the Tolgee platform into your projects, push local strings to the Tolgee platform, | ||
The Tolgee CLI lets you pull strings from the Tolgee platform into your projects, push local strings to the Tolgee platform, | ||
extract strings from your code, and much more! | ||
- Pull requests welcome! ๐คฉ | ||
![Tolgee CLI screenshot](tolgee-cli-screenshot.png) | ||
## Installation | ||
The Tolgee CLI is published as a NPM package. You simply need to install it, and you're good to go! | ||
```sh | ||
# npm | ||
npm i --global @tolgee/cli | ||
# Yarn | ||
yarn global add @tolgee/cli | ||
# pnpm | ||
pnpm add --global @tolgee/cli | ||
``` | ||
> **Warning**: The Tolgee CLI is currently experimental and subject to bugs. Breaking changes may happen before stable release! | ||
> | ||
> Help us reach stable version faster by reporting any bug you encounter on the [issue tracker](https://github.com/tolgee/tolgee-cli/issues/new?labels=bug). | ||
> Feedback is also greatly appreciated! | ||
See our [documentation](https://tolgee.io/tolgee-cli/installation) for more information. | ||
@@ -22,0 +25,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 2 instances in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
20
38
Yes
955149
3619
18
+ Added@isaacs/cliui@8.0.2(transitive)
+ Added@pkgjs/parseargs@0.11.0(transitive)
+ Addedansi-regex@5.0.16.1.0(transitive)
+ Addedansi-styles@4.3.06.2.1(transitive)
+ Addedcolor-convert@2.0.1(transitive)
+ Addedcolor-name@1.1.4(transitive)
+ Addedcross-spawn@7.0.6(transitive)
+ Addedeastasianwidth@0.2.0(transitive)
+ Addedemoji-regex@8.0.09.2.2(transitive)
+ Addedforeground-child@3.3.0(transitive)
+ Addedglob@10.4.5(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedjackspeak@3.4.3(transitive)
+ Addedlru-cache@10.4.3(transitive)
+ Addedminimatch@9.0.5(transitive)
+ Addedminipass@7.1.2(transitive)
+ Addedpackage-json-from-dist@1.0.1(transitive)
+ Addedpath-key@3.1.1(transitive)
+ Addedpath-scurry@1.11.1(transitive)
+ Addedshebang-command@2.0.0(transitive)
+ Addedshebang-regex@3.0.0(transitive)
+ Addedsignal-exit@4.1.0(transitive)
+ Addedstring-width@4.2.35.1.2(transitive)
+ Addedstrip-ansi@6.0.17.1.0(transitive)
+ Addedvscode-textmate@9.2.0(transitive)
+ Addedwhich@2.0.2(transitive)
+ Addedwrap-ansi@7.0.08.1.0(transitive)
- Removedfs.realpath@1.0.0(transitive)
- Removedglob@8.1.0(transitive)
- Removedinflight@1.0.6(transitive)
- Removedinherits@2.0.4(transitive)
- Removedminimatch@5.1.6(transitive)
- Removedonce@1.4.0(transitive)
- Removedvscode-textmate@8.0.0(transitive)
- Removedwrappy@1.0.2(transitive)
Updatedcommander@^10.0.1
Updatedcosmiconfig@^8.1.3
Updatedglob@^10.2.5
Updatedundici@^5.22.1
Updatedvscode-textmate@^9.0.0
Updatedxstate@^4.37.2