@tolgee/cli 2.3.4 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
1
  import { extname, join } from 'path';
2
2
  import { readdir, readFile, stat } from 'fs/promises';
3
3
  import { Command, Option } from 'commander';
4
+ import { glob } from 'tinyglobby';
4
5
  import { loading, success, error, warn, exitWithError, } from '../utils/logger.js';
5
6
  import { askString } from '../utils/ask.js';
6
7
  import { mapImportFormat } from '../utils/mapImportFormat.js';
7
8
  import { handleLoadableError } from '../client/TolgeeClient.js';
8
- import { windowsCompatibleGlob } from '../utils/windowsCompatibleGlob.js';
9
9
  async function allInPattern(pattern) {
10
10
  const files = [];
11
- const items = await windowsCompatibleGlob(pattern);
11
+ const items = await glob(pattern);
12
12
  for (const item of items) {
13
13
  if ((await stat(item)).isDirectory()) {
14
14
  files.push(...(await readDirectory(item)));
@@ -28,25 +28,25 @@ function parseConfig(input, configDir) {
28
28
  }
29
29
  // convert relative paths in config to absolute
30
30
  if (rc.extractor !== undefined) {
31
- rc.extractor = resolve(configDir, rc.extractor);
31
+ rc.extractor = resolve(configDir, rc.extractor).replace(/\\/g, '/');
32
32
  if (!existsSync(rc.extractor)) {
33
33
  throw new Error(`Invalid config: extractor points to a file that does not exists (${rc.extractor})`);
34
34
  }
35
35
  }
36
36
  // convert relative paths in config to absolute
37
37
  if (rc.patterns !== undefined) {
38
- rc.patterns = rc.patterns.map((pattern) => resolve(configDir, pattern));
38
+ rc.patterns = rc.patterns.map((pattern) => resolve(configDir, pattern).replace(/\\/g, '/'));
39
39
  }
40
40
  // convert relative paths in config to absolute
41
41
  if (rc.push?.files) {
42
42
  rc.push.files = rc.push.files.map((r) => ({
43
43
  ...r,
44
- path: resolve(configDir, r.path),
44
+ path: resolve(configDir, r.path).replace(/\\/g, '/'),
45
45
  }));
46
46
  }
47
47
  // convert relative paths in config to absolute
48
48
  if (rc.pull?.path !== undefined) {
49
- rc.pull.path = resolve(configDir, rc.pull.path);
49
+ rc.pull.path = resolve(configDir, rc.pull.path).replace(/\\/g, '/');
50
50
  }
51
51
  return rc;
52
52
  }
@@ -1,18 +1,27 @@
1
+ import { glob } from 'tinyglobby';
1
2
  import { extname } from 'path';
2
3
  import { callWorker } from './worker.js';
3
4
  import { exitWithError } from '../utils/logger.js';
4
- import { windowsCompatibleGlob } from '../utils/windowsCompatibleGlob.js';
5
5
  export const NullNamespace = Symbol('namespace.null');
6
6
  function parseVerbose(v) {
7
7
  return Array.isArray(v) ? v : v ? [] : undefined;
8
8
  }
9
9
  export async function extractKeysFromFile(file, parserType, options, extractor) {
10
- return callWorker({
11
- extractor: extractor,
12
- parserType,
13
- file: file,
14
- options,
15
- });
10
+ if (typeof extractor !== 'undefined') {
11
+ return callWorker({
12
+ extractor,
13
+ file,
14
+ options,
15
+ });
16
+ }
17
+ else if (typeof parserType !== 'undefined') {
18
+ return callWorker({
19
+ parserType,
20
+ file,
21
+ options,
22
+ });
23
+ }
24
+ throw new Error('Internal error: neither the parser type nor a custom extractors have been defined! Please report this.');
16
25
  }
17
26
  export function findPossibleFrameworks(fileNames) {
18
27
  const possibleFrameworks = [];
@@ -54,14 +63,12 @@ export async function extractKeysOfFiles(opts) {
54
63
  if (!opts.patterns?.length) {
55
64
  exitWithError("Missing '--patterns' or 'config.patterns' option");
56
65
  }
57
- const files = await windowsCompatibleGlob(opts.patterns, {
58
- nodir: true,
59
- });
66
+ const files = await glob(opts.patterns, { onlyFiles: true });
60
67
  if (files.length === 0) {
61
68
  exitWithError('No files were matched for extraction');
62
69
  }
63
70
  let parserType = opts.parser;
64
- if (!parserType) {
71
+ if (!parserType && !opts.extractor) {
65
72
  parserType = detectParserType(files);
66
73
  }
67
74
  const result = new Map();
@@ -1,30 +1,26 @@
1
1
  import { fileURLToPath } from 'url';
2
- import { resolve, extname } from 'path';
3
- import { Worker, isMainThread, parentPort } from 'worker_threads';
4
- import { readFile } from 'fs/promises';
2
+ import { extname, resolve } from 'path';
3
+ import { isMainThread, parentPort, SHARE_ENV, Worker } from 'worker_threads';
4
+ import { readFileSync } from 'fs';
5
5
  import internalExtractor from './extractor.js';
6
6
  import { loadModule } from '../utils/moduleLoader.js';
7
7
  import { createDeferred } from '../utils/deferred.js';
8
8
  const FILE_TIME_LIMIT = 60 * 1000; // one minute
9
- const IS_TS_NODE = extname(import.meta.url) === '.ts';
9
+ const IS_TSX = extname(import.meta.url) === '.ts';
10
10
  // --- Worker functions
11
- let loadedExtractor = Symbol('unloaded');
12
11
  let extractor;
13
12
  async function handleJob(args) {
14
13
  const file = resolve(args.file);
15
- const code = await readFile(file, 'utf8');
16
- if (args.extractor) {
17
- if (args.extractor !== loadedExtractor) {
18
- loadedExtractor = args.extractor;
14
+ const code = readFileSync(file, 'utf8');
15
+ if ('extractor' in args) {
16
+ if (!extractor) {
19
17
  extractor = await loadModule(args.extractor).then((mdl) => mdl.default);
20
18
  }
21
19
  return extractor(code, file, args.options);
22
20
  }
23
- else {
24
- return internalExtractor(code, file, args.parserType, args.options);
25
- }
21
+ return internalExtractor(code, file, args.parserType, args.options);
26
22
  }
27
- async function workerInit() {
23
+ function workerInit() {
28
24
  parentPort.on('message', (params) => {
29
25
  handleJob(params)
30
26
  .then((res) => parentPort.postMessage({ data: res }))
@@ -37,12 +33,18 @@ if (!isMainThread)
37
33
  let worker;
38
34
  const jobQueue = [];
39
35
  function createWorker() {
40
- const worker = IS_TS_NODE
41
- ? new Worker(fileURLToPath(new URL(import.meta.url)).replace('.ts', '.js'), {
42
- // ts-node workaround
43
- execArgv: ['--require', 'ts-node/register'],
44
- })
45
- : new Worker(fileURLToPath(new URL(import.meta.url)));
36
+ let worker;
37
+ if (IS_TSX) {
38
+ worker = new Worker(`import('tsx/esm/api').then(({ register }) => { register(); import('${fileURLToPath(new URL(import.meta.url))}') })`, {
39
+ env: SHARE_ENV,
40
+ eval: true,
41
+ });
42
+ }
43
+ else {
44
+ worker = new Worker(fileURLToPath(new URL(import.meta.url)), {
45
+ env: SHARE_ENV,
46
+ });
47
+ }
46
48
  let timeout;
47
49
  let currentDeferred;
48
50
  function workOrDie() {
@@ -1,33 +1,26 @@
1
- import { extname } from 'path';
2
- let tsService;
3
- async function registerTsNode() {
4
- if (!tsService) {
5
- // try {
6
- // const tsNode = await import('ts-node');
7
- // tsService = tsNode.register({ compilerOptions: { module: 'CommonJS' } });
8
- // } catch (e: any) {
9
- // if (e.code === 'ERR_MODULE_NOT_FOUND') {
10
- // throw new Error('ts-node is required to load TypeScript files.');
11
- // }
12
- // throw e;
13
- // }
14
- }
15
- }
1
+ import { pathToFileURL } from 'url';
2
+ let jiti;
3
+ // https://github.com/eslint/eslint/blob/6f37b0747a14dfa9a9e3bdebc5caed1f39b6b0e2/lib/config/config-loader.js#L164-L197
16
4
  async function importTypeScript(file) {
17
- if (extname(import.meta.url) === '.ts') {
5
+ // @ts-ignore
6
+ if (!!globalThis.Bun || !!globalThis.Deno) {
7
+ // We're in an env that natively supports TS
18
8
  return import(file);
19
9
  }
20
- await registerTsNode();
21
- tsService.enabled(true);
22
- const mdl = await import(file);
23
- tsService.enabled(false);
24
- return mdl;
10
+ if (!jiti) {
11
+ const { createJiti } = await import('jiti').catch(() => {
12
+ throw new Error("The 'jiti' library is required for loading TypeScript extractors. Make sure to install it.");
13
+ });
14
+ jiti = createJiti(import.meta.url);
15
+ }
16
+ return jiti.import(file);
25
17
  }
26
18
  export async function loadModule(module) {
27
19
  if (module.endsWith('.ts')) {
28
20
  return importTypeScript(module);
29
21
  }
30
- const mdl = await import(module);
22
+ const fileUrl = pathToFileURL(module);
23
+ const mdl = await import(fileUrl.href);
31
24
  if (mdl.default?.default) {
32
25
  return mdl.default;
33
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tolgee/cli",
3
- "version": "2.3.4",
3
+ "version": "2.4.0",
4
4
  "type": "module",
5
5
  "description": "A tool to interact with the Tolgee Platform through CLI",
6
6
  "repository": {
@@ -34,40 +34,49 @@
34
34
  "base32-decode": "^1.0.0",
35
35
  "commander": "^12.1.0",
36
36
  "cosmiconfig": "^9.0.0",
37
- "glob": "^11.0.0",
38
37
  "json5": "^2.2.3",
39
38
  "jsonschema": "^1.4.1",
40
- "openapi-fetch": "^0.10.6",
39
+ "openapi-fetch": "0.13.1",
40
+ "tinyglobby": "^0.2.10",
41
41
  "unescape-js": "^1.1.4",
42
42
  "vscode-oniguruma": "^2.0.1",
43
43
  "vscode-textmate": "^9.1.0",
44
- "yauzl": "^3.1.3"
44
+ "yauzl": "^3.2.0"
45
45
  },
46
46
  "devDependencies": {
47
- "@eslint/js": "^9.8.0",
47
+ "@eslint/js": "^9.16.0",
48
48
  "@semantic-release/changelog": "^6.0.3",
49
49
  "@semantic-release/git": "^10.0.1",
50
50
  "@tsconfig/node18": "^18.2.4",
51
- "@tsconfig/recommended": "^1.0.7",
51
+ "@tsconfig/recommended": "^1.0.8",
52
52
  "@types/eslint__js": "^8.42.3",
53
53
  "@types/js-yaml": "^4.0.9",
54
- "@types/node": "^22.1.0",
54
+ "@types/node": "^22.10.1",
55
55
  "@types/yauzl": "^2.10.3",
56
56
  "cross-env": "^7.0.3",
57
- "eslint": "^9.8.0",
57
+ "eslint": "^9.16.0",
58
58
  "eslint-config-prettier": "^9.1.0",
59
59
  "eslint-plugin-prettier": "^5.2.1",
60
+ "jiti": "^2.4.1",
60
61
  "js-yaml": "^4.1.0",
61
- "json-schema-to-typescript": "^15.0.0",
62
- "openapi-typescript": "^7.3.0",
62
+ "json-schema-to-typescript": "^15.0.3",
63
+ "openapi-typescript": "^7.4.4",
63
64
  "premove": "^4.0.0",
64
- "prettier": "^3.3.3",
65
- "semantic-release": "^24.0.0",
65
+ "prettier": "^3.4.1",
66
+ "semantic-release": "^24.2.0",
66
67
  "tree-cli": "^0.6.7",
67
- "tsx": "^4.17.0",
68
- "typescript": "^5.5.4",
69
- "typescript-eslint": "^8.0.1",
70
- "vitest": "^2.0.5"
68
+ "tsx": "^4.19.2",
69
+ "typescript": "~5.6.3",
70
+ "typescript-eslint": "^8.17.0",
71
+ "vitest": "^2.1.8"
72
+ },
73
+ "peerDependencies": {
74
+ "jiti": ">= 2"
75
+ },
76
+ "peerDependenciesMeta": {
77
+ "jiti": {
78
+ "optional": true
79
+ }
71
80
  },
72
81
  "engines": {
73
82
  "node": ">= 18"
@@ -1,7 +0,0 @@
1
- import { glob } from 'glob';
2
- export const windowsCompatibleGlob = (pattern, options) => {
3
- return glob(pattern, {
4
- ...options,
5
- windowsPathsNoEscape: process.platform === 'win32',
6
- });
7
- };