tsoft-cli 3.14.0 → 3.14.1

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/CHANGELOG.md CHANGED
@@ -5,6 +5,11 @@ All notable changes to T-Soft CLI will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.14.1] - 2026-09-22
9
+
10
+ ### Fixed
11
+ - An expired session now says so and points at `tsoft login --org`, instead of printing a raw status line. When the store refused a session renewal the CLI wrote out `Token refresh hatası: 401 - Token refresh failed` and stopped there — a line that names an internal step, is not in the language the rest of the output uses, and says nothing about what to do next; the session was simply over and signing in again was all that was needed, but nothing on screen said that. The refusal is now recognised where it happens and reported as an expired session with the sign-in command to run. A store that is genuinely failing is still reported as a failure, so a broken store is not mistaken for an expired session and nobody is sent to sign in again over an outage. The renewal details are still available under `--verbose` for anyone diagnosing one.
12
+
8
13
  ## [3.14.0] - 2026-09-15
9
14
 
10
15
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsoft-cli",
3
- "version": "3.14.0",
3
+ "version": "3.14.1",
4
4
  "description": "Command-line tool for tsoft360 theme development and management",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { loadTokens, ensureValidToken, getTokenExpiry, isTokenValid, isRefreshTokenValid } from '../storage.js';
2
+ import { loadTokens, ensureValidToken, getTokenExpiry, isTokenValid, isRefreshTokenValid, isReloginRequired } from '../storage.js';
3
3
  import { loginCommand } from './login.js';
4
4
  import { isJsonMode, jsonOut } from '../output-mode.js';
5
5
  import { mapError } from '../errors/error-mapper.js';
@@ -30,7 +30,7 @@ export async function whoamiCommand() {
30
30
  console.log(chalk.yellow(t('whoami.token_refreshed') + '\n'));
31
31
  }
32
32
  } catch (error) {
33
- if (error.message === 'RELOGIN_REQUIRED') {
33
+ if (isReloginRequired(error)) {
34
34
  console.log(chalk.yellow(t('whoami.session_expired') + '\n'));
35
35
  await loginCommand();
36
36
  tokens = await loadTokens();
@@ -2,6 +2,7 @@
2
2
  * Push error code -> locale key mapper
3
3
  */
4
4
  import { t } from '../i18n.js';
5
+ import { isReloginRequired } from '../storage.js';
5
6
 
6
7
  const ERROR_MAP = {
7
8
  'PUSH-PENDING-REVIEW': {
@@ -120,6 +121,14 @@ export function mapError(error, { command = 'unknown', verbose = false } = {}) {
120
121
  const responseData = error.response?.data;
121
122
  const statusCode = error.response?.status;
122
123
 
124
+ if (isReloginRequired(error)) {
125
+ return {
126
+ message: t('error.auth_required.message'),
127
+ hint: t('error.auth_required.hint'),
128
+ raw: verbose ? responseData : null,
129
+ };
130
+ }
131
+
123
132
  // 1. HTTP status code — mevcut HTTP_STATUS_MAP kullan
124
133
  if (statusCode && HTTP_STATUS_MAP[statusCode]) {
125
134
  const mapped = HTTP_STATUS_MAP[statusCode];
package/src/storage.js CHANGED
@@ -3,6 +3,8 @@ import path from 'path';
3
3
  import os from 'os';
4
4
  import axios from 'axios';
5
5
  import * as config from './config.js';
6
+ import { t } from './i18n.js';
7
+ import { verboseLog } from './output-mode.js';
6
8
 
7
9
  /**
8
10
  * Global config dizini (~/.tsoft-cli/)
@@ -16,6 +18,23 @@ const ACTIVE_THEME_FILE = 'active-theme';
16
18
 
17
19
  const LEGACY_ACTIVE_THEME_FILE = 'active-theme.txt';
18
20
 
21
+ export const RELOGIN_REQUIRED = 'RELOGIN_REQUIRED';
22
+
23
+ export function createReloginRequiredError(response = null) {
24
+ const error = new Error(t('error.auth_required.message'));
25
+ error.code = RELOGIN_REQUIRED;
26
+
27
+ if (response) {
28
+ error.response = response;
29
+ }
30
+
31
+ return error;
32
+ }
33
+
34
+ export function isReloginRequired(error) {
35
+ return error?.code === RELOGIN_REQUIRED || error?.message === RELOGIN_REQUIRED;
36
+ }
37
+
19
38
  /**
20
39
  * Store domain'i dizin adına uygun formata çevirir
21
40
  * @param {string} domain - Store domain (örn: birtan.1isim.com)
@@ -347,16 +366,24 @@ export async function refreshAccessToken(refreshToken, store) {
347
366
  };
348
367
  } catch (error) {
349
368
  if (error.response?.data) {
350
- console.error('Token refresh hatası:', error.response.data);
369
+ verboseLog('Token refresh hatası:', error.response.data);
351
370
  }
352
371
  if (error.response) {
353
- throw new Error(
372
+ if (error.response.status === 401) {
373
+ throw createReloginRequiredError(error.response);
374
+ }
375
+
376
+ const refreshError = new Error(
354
377
  `Token refresh hatası: ${error.response.status} - ${
355
378
  error.response.data.error_description ||
356
379
  error.response.data.message ||
357
380
  'Bilinmeyen hata'
358
381
  }`
359
382
  );
383
+
384
+ refreshError.response = error.response;
385
+
386
+ throw refreshError;
360
387
  }
361
388
  throw new Error(`Token refresh hatası: ${error.message}`);
362
389
  }
@@ -519,7 +546,7 @@ export function isRefreshTokenValid(tokens) {
519
546
  */
520
547
  export async function ensureValidToken(tokens) {
521
548
  if (!tokens) {
522
- throw new Error('RELOGIN_REQUIRED');
549
+ throw createReloginRequiredError();
523
550
  }
524
551
 
525
552
  // Access token geçerliyse direkt dön
@@ -535,7 +562,7 @@ export async function ensureValidToken(tokens) {
535
562
  }
536
563
 
537
564
  // Her ikisi de geçersizse, otomatik re-login gerekiyor
538
- throw new Error('RELOGIN_REQUIRED');
565
+ throw createReloginRequiredError();
539
566
  }
540
567
 
541
568
  /**