tsoft-cli 3.13.1 → 3.13.3

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,16 @@ 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.13.3] - 2026-09-10
9
+
10
+ ### Fixed
11
+ - `theme dev` no longer crashes after you sign out. With no active store it read the store name as text anyway and died with "Cannot read properties of null (reading 'replace')", which says nothing about what went wrong or how to recover. It now reports that there is no active store, points at `tsoft login`, and exits non-zero like `theme list` and `theme init` already did in the same situation.
12
+
13
+ ## [3.13.2] - 2026-09-10
14
+
15
+ ### Fixed
16
+ - Commands no longer print a theme's folder id where its name belongs. `theme push`, `theme section list`, `theme section add` and the help screen showed whatever is recorded as the active theme, and for most themes that is the folder id — so a line meant to confirm what you are about to push read "Store: example.com - Theme: adf806ec-9ee6-4ce8-af40-cd1af10a4c04" and told you nothing. The commands that already talk to the store now show the theme's name; the help screen, which must not make a network call to draw its status line, leaves the theme out rather than printing an id.
17
+
8
18
  ## [3.13.1] - 2026-09-10
9
19
 
10
20
  ### Fixed
package/locales/en.json CHANGED
@@ -395,5 +395,6 @@
395
395
  "config.autoupgrade.off": "Version checking is off.",
396
396
  "config.autoupgrade.status_on": "Version checking: on",
397
397
  "config.autoupgrade.status_off": "Version checking: off",
398
- "config.autoupgrade.usage": "Usage: tsoft config autoupgrade on | off | status"
398
+ "config.autoupgrade.usage": "Usage: tsoft config autoupgrade on | off | status",
399
+ "dev.no_active_store": "No active store.\n\nTo sign in: tsoft login"
399
400
  }
package/locales/tr.json CHANGED
@@ -395,5 +395,6 @@
395
395
  "config.autoupgrade.off": "Sürüm kontrolü kapatıldı.",
396
396
  "config.autoupgrade.status_on": "Sürüm kontrolü: açık",
397
397
  "config.autoupgrade.status_off": "Sürüm kontrolü: kapalı",
398
- "config.autoupgrade.usage": "Kullanım: tsoft config autoupgrade on | off | status"
398
+ "config.autoupgrade.usage": "Kullanım: tsoft config autoupgrade on | off | status",
399
+ "dev.no_active_store": "Aktif mağaza bulunamadı.\n\nGiriş yapmak için: tsoft login"
399
400
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsoft-cli",
3
- "version": "3.13.1",
3
+ "version": "3.13.3",
4
4
  "description": "Command-line tool for tsoft360 theme development and management",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -332,6 +332,12 @@ export async function themeDevCommand(themeName) {
332
332
  console.log(chalk.cyan(t('dev.starting') + '\n'));
333
333
 
334
334
  const store = await getActiveStore();
335
+
336
+ if (!store) {
337
+ showError(t('dev.no_active_store'));
338
+ process.exit(1);
339
+ }
340
+
335
341
  const storeSlug = normalizeStoreDomain(store);
336
342
 
337
343
  let themeSlug = themeName;
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import ora from 'ora';
3
3
  import { createApiClient } from '../api-client.js';
4
- import { resolveActiveThemeUuid, getActiveStore } from '../storage.js';
4
+ import { describeActiveTheme, getActiveStore } from '../storage.js';
5
5
  import { mapPushError } from '../errors/error-mapper.js';
6
6
  import { isJsonMode, jsonOut } from '../output-mode.js';
7
7
  import { t } from '../i18n.js';
@@ -91,11 +91,12 @@ export async function themePushCommand(themeName, options = {}) {
91
91
  if (themeName) {
92
92
  themeUuid = themeName;
93
93
  } else {
94
- themeUuid = await resolveActiveThemeUuid();
95
- if (themeUuid && !isJsonMode()) {
94
+ const active = await describeActiveTheme();
95
+ themeUuid = active?.uuid ?? null;
96
+ if (active && !isJsonMode()) {
96
97
  const store = await getActiveStore();
97
98
  if (store) {
98
- console.log(chalk.gray(t('context.line', { store, theme: themeUuid })));
99
+ console.log(chalk.gray(t('context.line', { store, theme: active.label })));
99
100
  }
100
101
  }
101
102
  if (!themeUuid) {
@@ -35,10 +35,10 @@ export async function themeSectionListCommand() {
35
35
  }
36
36
 
37
37
  console.log(chalk.cyan(t('section.list.starting') + '\n'));
38
- console.log(chalk.gray(t('section.list.active_theme', { theme: activeTheme }) + '\n'));
39
38
 
40
39
  // Tema UUID'sini al
41
40
  const themeInfo = await getThemeUuidBySlug(activeTheme);
41
+ console.log(chalk.gray(t('section.list.active_theme', { theme: themeInfo.name ?? activeTheme }) + '\n'));
42
42
 
43
43
  // Section'ları çek
44
44
  const apiClient = await createApiClient();
@@ -98,10 +98,10 @@ export async function themeSectionAddCommand() {
98
98
  }
99
99
 
100
100
  console.log(chalk.cyan(t('section.add.starting') + '\n'));
101
- console.log(chalk.gray(t('section.add.active_theme', { theme: activeTheme }) + '\n'));
102
101
 
103
102
  // Tema UUID'sini al
104
103
  const themeInfo = await getThemeUuidBySlug(activeTheme);
104
+ console.log(chalk.gray(t('section.add.active_theme', { theme: themeInfo.name ?? activeTheme }) + '\n'));
105
105
 
106
106
  // Section'ları çek
107
107
  const apiClient = await createApiClient();
package/src/storage.js CHANGED
@@ -729,6 +729,32 @@ export async function resolveActiveThemeUuid() {
729
729
  return uuid;
730
730
  }
731
731
 
732
+ /**
733
+ * Aktif temayı hem kimliğiyle hem okunabilir adıyla döner.
734
+ *
735
+ * Kayıt UUID ise ad mağazadan çözülür; mağazaya ulaşılamazsa kayıtlı değer
736
+ * olduğu gibi etiket olur. Kullanıcıya UUID göstermemek için vardır.
737
+ *
738
+ * @returns {Promise<{uuid: string, label: string}|null>}
739
+ */
740
+ export async function describeActiveTheme() {
741
+ const uuid = await resolveActiveThemeUuid();
742
+
743
+ if (!uuid) {
744
+ return null;
745
+ }
746
+
747
+ try {
748
+ const { fetchAllThemes } = await import('./theme-list.js');
749
+ const { themes } = await fetchAllThemes();
750
+ const match = themes.find(theme => theme.theme_folder === uuid);
751
+
752
+ return { uuid, label: match?.name ?? uuid };
753
+ } catch {
754
+ return { uuid, label: uuid };
755
+ }
756
+ }
757
+
732
758
  /**
733
759
  * Tema slug'ından UUID/folder adını bulur
734
760
  * @param {string} themeSlug - Tema slug (örn: 'my-theme')
@@ -4,6 +4,7 @@ import { TSOFT_COLORS, createTSoftGradient } from './prompt-wrapper.js';
4
4
  import { humanOut, isJsonMode, jsonOut } from '../output-mode.js';
5
5
  import { t } from '../i18n.js';
6
6
  import { loadTokens, getActiveStore, getActiveTheme } from '../storage.js';
7
+ import { themeStatusLabel } from './theme-choice.js';
7
8
 
8
9
  const require = createRequire(import.meta.url);
9
10
 
@@ -150,8 +151,9 @@ function buildStatusLines(status) {
150
151
  }
151
152
 
152
153
  // Theme line
153
- if (activeTheme) {
154
- const themeText = t('help.status.active_theme', { theme: activeTheme });
154
+ const themeLabel = themeStatusLabel(activeTheme);
155
+ if (themeLabel) {
156
+ const themeText = t('help.status.active_theme', { theme: themeLabel });
155
157
  lines.push(' ' + orangeBullet + ' ' + themeText);
156
158
  } else {
157
159
  lines.push(' ' + chalk.dim('○ ' + t('help.status.no_theme')));
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { slugify } from '../storage.js';
2
+ import { slugify, isThemeUuid } from '../storage.js';
3
3
  import { t } from '../i18n.js';
4
4
 
5
5
  export function themeLabels(theme, selectedTheme) {
@@ -31,3 +31,11 @@ export function decorateThemeName(theme, selectedTheme) {
31
31
 
32
32
  return [name, chalk.gray(`v${theme.version}`), ...marks].join(' ');
33
33
  }
34
+
35
+ export function themeStatusLabel(activeTheme) {
36
+ if (!activeTheme || isThemeUuid(activeTheme)) {
37
+ return null;
38
+ }
39
+
40
+ return activeTheme;
41
+ }