@getxflow/cli 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/config.js CHANGED
@@ -17,7 +17,7 @@ const STATE_DIR = '.xflow';
17
17
  class ConfigError extends Error {
18
18
  }
19
19
  exports.ConfigError = ConfigError;
20
- /** Ищем корень проекта вверх по дереву: команду запускают из подкаталога чаще, чем из корня. */
20
+ /** Walk up from cwd. */
21
21
  function findProjectRoot(from = process.cwd()) {
22
22
  let dir = (0, node_path_1.resolve)(from);
23
23
  for (;;) {
@@ -36,30 +36,33 @@ function readConfig(root) {
36
36
  parsed = JSON.parse((0, node_fs_1.readFileSync)(path, 'utf-8'));
37
37
  }
38
38
  catch (e) {
39
- throw new ConfigError(`Не удалось прочитать ${exports.CONFIG_FILE}: ${e instanceof Error ? e.message : e}`);
39
+ throw new ConfigError(`Could not read ${exports.CONFIG_FILE}: ${e instanceof Error ? e.message : e}`);
40
40
  }
41
41
  const config = parsed;
42
42
  if (!config || typeof config.projectId !== 'string' || !config.projectId) {
43
- throw new ConfigError(`В ${exports.CONFIG_FILE} нет projectId. Свяжите папку с проектом: xflow link <id>`);
43
+ throw new ConfigError(`${exports.CONFIG_FILE} has no projectId. Link the folder to a project: xflow link <id>`);
44
44
  }
45
45
  return config;
46
46
  }
47
47
  function writeConfig(root, config) {
48
48
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(root, exports.CONFIG_FILE), `${JSON.stringify(config, null, 2)}\n`, 'utf-8');
49
49
  }
50
- /** Конфигурация проекта, из которого запущена команда. Бросает, если папка не связана. */
51
50
  function requireProject() {
52
51
  const root = findProjectRoot();
53
52
  if (!root) {
54
- throw new ConfigError(`Папка не связана с проектом: рядом нет ${exports.CONFIG_FILE}.\n` +
55
- ' Связать существующий: xflow link <id проекта>\n' +
56
- ' Создать новый: xflow init');
53
+ throw new ConfigError(`The folder is not linked to a project: there is no ${exports.CONFIG_FILE} next to it.\n` +
54
+ ' Link an existing one: xflow link <project id>\n' +
55
+ ' Create a new one: xflow init');
57
56
  }
58
57
  return { root, config: readConfig(root) };
59
58
  }
60
59
  function apiUrlFor(config) {
61
- const raw = process.env.XFLOW_API_URL?.trim() || config?.api?.trim() || version_1.DEFAULT_API_URL;
62
- return raw.replace(/\/+$/, '');
60
+ const raw = (process.env.XFLOW_API_URL?.trim() || config?.api?.trim() || version_1.DEFAULT_API_URL).replace(/\/+$/, '');
61
+ // The address ends up in headers and child processes: keep it a plain http(s) URL.
62
+ if (!/^https?:\/\/[A-Za-z0-9.-]+(:\d+)?(\/[A-Za-z0-9._/-]*)?$/.test(raw)) {
63
+ throw new ConfigError(`Invalid platform address: ${raw}`);
64
+ }
65
+ return raw;
63
66
  }
64
67
  function readState(root) {
65
68
  const path = (0, node_path_1.join)(root, STATE_DIR, 'state.json');
@@ -77,10 +80,7 @@ function writeState(root, state) {
77
80
  (0, node_fs_1.mkdirSync)(dir, { recursive: true });
78
81
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(dir, 'state.json'), `${JSON.stringify(state, null, 2)}\n`, 'utf-8');
79
82
  }
80
- /**
81
- * Состояние в git не нужно никому, но забыть про него легко: дописываем в
82
- * .gitignore сами. Если файла нет, создаём — проект почти всегда под git.
83
- */
83
+ /** Keep .xflow/ out of git. */
84
84
  function ignoreStateInGit(root) {
85
85
  const path = (0, node_path_1.join)(root, '.gitignore');
86
86
  const line = `${STATE_DIR}/`;
@@ -30,12 +30,12 @@ function writeStore(store) {
30
30
  (0, node_fs_1.mkdirSync)(dir, { recursive: true, mode: 0o700 });
31
31
  const path = credentialsPath();
32
32
  (0, node_fs_1.writeFileSync)(path, `${JSON.stringify(store, null, 2)}\n`, { mode: 0o600 });
33
- // На случай, когда файл уже существовал: writeFileSync права не меняет.
33
+ // writeFileSync does not change the mode of an existing file.
34
34
  try {
35
35
  (0, node_fs_1.chmodSync)(path, 0o600);
36
36
  }
37
37
  catch {
38
- // Windows правами POSIX не управляет — не повод падать.
38
+ // Windows has no POSIX modes.
39
39
  }
40
40
  }
41
41
  function saveCredential(apiUrl, credential) {
@@ -51,14 +51,13 @@ function forgetCredential(apiUrl) {
51
51
  writeStore(store);
52
52
  return true;
53
53
  }
54
- /**
55
- * Ключ для адреса платформы. Переменная окружения главнее файла: так работает
56
- * запуск из CI, где домашнего каталога может не быть вовсе.
57
- */
58
- function resolveToken(apiUrl) {
59
- const fromEnv = process.env.XFLOW_TOKEN?.trim();
60
- if (fromEnv)
61
- return fromEnv;
54
+ /** XFLOW_TOKEN wins over the store; the caller decides whether env is allowed for this address. */
55
+ function resolveToken(apiUrl, allowEnv = true) {
56
+ if (allowEnv) {
57
+ const fromEnv = process.env.XFLOW_TOKEN?.trim();
58
+ if (fromEnv)
59
+ return fromEnv;
60
+ }
62
61
  return readStore()[apiUrl]?.token ?? null;
63
62
  }
64
63
  function readCredential(apiUrl) {
package/dist/errors.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CliError = void 0;
4
- /** Ошибка, которую показываем человеку как есть: без стека и без «Unhandled». */
4
+ /** Shown to the user as is, without a stack trace. */
5
5
  class CliError extends Error {
6
6
  hint;
7
7
  constructor(message, hint) {