tsoft-cli 3.12.0 → 3.12.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.12.1] - 2026-08-08
9
+
10
+ ### Fixed
11
+ - Theme lists no longer call two different things "active". Standing inside a theme directory and running `tsoft theme use` named that theme on one line and then marked a different one as active in the list below it. The mark was reading which theme is published on the storefront, while the line above was reading the theme you are working on — both were correct, and both were called active. The theme you are working on is now marked `(Selected)` and the one your customers see is marked `(Published)`, so a list can show both without the two contradicting each other. `theme list`, `theme pull` and `theme dev` use the same two marks.
12
+
8
13
  ## [3.12.0] - 2026-08-05
9
14
 
10
15
  ### Added
package/locales/en.json CHANGED
@@ -133,6 +133,8 @@
133
133
  "theme.use.select_title": "🎯 Theme Selection",
134
134
  "theme.use.set": "✓ Active theme set: {{name}}",
135
135
  "theme.use.folder": "Folder: {{folder}}",
136
+ "theme.mark.selected": "(Selected)",
137
+ "theme.mark.published": "(Published)",
136
138
  "push.no_active_theme": "No active theme found.",
137
139
  "push.usage": "Usage: tsoft theme push <theme-name>",
138
140
  "push.use_tip": "Or set an active theme with \"tsoft theme use <theme-name>\".",
package/locales/tr.json CHANGED
@@ -133,6 +133,8 @@
133
133
  "theme.use.select_title": "🎯 Tema Seçimi",
134
134
  "theme.use.set": "✓ Aktif tema ayarlandı: {{name}}",
135
135
  "theme.use.folder": "Klasör: {{folder}}",
136
+ "theme.mark.selected": "(Seçili)",
137
+ "theme.mark.published": "(Yayında)",
136
138
  "push.no_active_theme": "Aktif tema bulunamadı.",
137
139
  "push.usage": "Kullanim: tsoft theme push <theme-name>",
138
140
  "push.use_tip": "veya \"tsoft theme use <theme-name>\" ile aktif tema ayarlayın.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsoft-cli",
3
- "version": "3.12.0",
3
+ "version": "3.12.1",
4
4
  "description": "Command-line tool for tsoft360 theme development and management",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -7,6 +7,7 @@ import chokidar from 'chokidar';
7
7
  import {createApiClient} from '../api-client.js';
8
8
  import open from 'open';
9
9
  import {normalizeStoreDomain, slugify, setActiveTheme, getActiveTheme, getActiveStore, getWorkspaceRoot} from '../storage.js';
10
+ import {decorateThemeName} from '../ui/theme-choice.js';
10
11
  import {brandedConfirm, brandedSelect, showWarning, showError, showInfo} from '../ui/prompt-wrapper.js';
11
12
  import {themeSectionMenuCommand} from './theme-section.js';
12
13
  import { t } from '../i18n.js';
@@ -397,7 +398,7 @@ export async function themeDevCommand(themeName) {
397
398
 
398
399
  console.log();
399
400
  const themeChoices = themes.map(theme => ({
400
- name: `${theme.name} ${chalk.gray(`v${theme.version}`)} ${theme.active ? chalk.green('(Aktif)') : ''}`,
401
+ name: decorateThemeName(theme, themeSlug),
401
402
  value: theme,
402
403
  description: theme.description || `Klasör: ${theme.theme_folder}`
403
404
  }));
@@ -5,8 +5,9 @@ import {createWriteStream} from 'fs';
5
5
  import path from 'path';
6
6
  import AdmZip from 'adm-zip';
7
7
  import {createApiClient} from '../api-client.js';
8
- import {normalizeStoreDomain, slugify, setActiveTheme, getActiveStore, getWorkspaceRoot, getWorkspaceContext} from '../storage.js';
8
+ import {normalizeStoreDomain, slugify, setActiveTheme, getActiveTheme, getActiveStore, getWorkspaceRoot, getWorkspaceContext} from '../storage.js';
9
9
  import {brandedConfirm, brandedSelect, brandedSearch, showWarning} from '../ui/prompt-wrapper.js';
10
+ import {themeLabels, decorateThemeName} from '../ui/theme-choice.js';
10
11
  import { isJsonMode, jsonOut } from '../output-mode.js';
11
12
  import { mapError } from '../errors/error-mapper.js';
12
13
  import { t } from '../i18n.js';
@@ -48,13 +49,16 @@ export async function themeListCommand() {
48
49
 
49
50
  console.log(chalk.bold.cyan(t('theme.count', { count: themes.length }) + '\n'));
50
51
 
52
+ const localTheme = await getActiveTheme();
53
+
51
54
  themes.forEach((theme) => {
52
- const activeIndicator = theme.active ? chalk.green('●') : chalk.gray('○');
53
- const name = theme.active ? chalk.bold.green(theme.name) : chalk.white(theme.name);
54
- const version = chalk.gray(`v${theme.version}`);
55
+ const labels = themeLabels(theme, localTheme);
56
+ const indicator = labels.includes('selected')
57
+ ? chalk.cyan('●')
58
+ : (labels.includes('published') ? chalk.green('●') : chalk.gray('○'));
55
59
  const description = theme.description ? chalk.gray(` - ${theme.description}`) : '';
56
60
 
57
- console.log(`${activeIndicator} ${name} ${version}${description}`);
61
+ console.log(`${indicator} ${decorateThemeName(theme, localTheme)}${description}`);
58
62
  console.log(chalk.gray(` ${t('theme.folder_label')} ${theme.theme_folder || theme.alias}`));
59
63
  console.log();
60
64
  });
@@ -349,8 +353,10 @@ export async function themePullCommand() {
349
353
  return;
350
354
  }
351
355
 
356
+ const localTheme = await getActiveTheme();
357
+
352
358
  const themeChoices = themes.map(theme => ({
353
- name: `${theme.name} ${chalk.gray(`v${theme.version}`)} ${theme.active ? chalk.green('(Aktif)') : ''}`,
359
+ name: decorateThemeName(theme, localTheme),
354
360
  value: theme,
355
361
  description: theme.description || `${t('theme.folder_label')} ${theme.theme_folder}`
356
362
  }));
@@ -463,8 +469,10 @@ export async function themeUseCommand(themeName = null) {
463
469
  process.exit(1);
464
470
  }
465
471
  } else {
472
+ const localTheme = await getActiveTheme();
473
+
466
474
  const themeChoices = themes.map(theme => ({
467
- name: `${theme.name} ${chalk.gray(`v${theme.version}`)} ${theme.active ? chalk.green('(Şu an aktif)') : ''}`,
475
+ name: decorateThemeName(theme, localTheme),
468
476
  value: theme,
469
477
  description: theme.description || `${t('theme.folder_label')} ${theme.theme_folder}`,
470
478
  keywords: [theme.theme_folder, theme.alias].filter(Boolean),
@@ -0,0 +1,33 @@
1
+ import chalk from 'chalk';
2
+ import { slugify } from '../storage.js';
3
+ import { t } from '../i18n.js';
4
+
5
+ export function themeLabels(theme, selectedTheme) {
6
+ const labels = [];
7
+
8
+ const folder = theme.theme_folder || theme.alias;
9
+
10
+ if (selectedTheme && (folder === selectedTheme || slugify(theme.name) === selectedTheme)) {
11
+ labels.push('selected');
12
+ }
13
+
14
+ if (theme.active) {
15
+ labels.push('published');
16
+ }
17
+
18
+ return labels;
19
+ }
20
+
21
+ export function decorateThemeName(theme, selectedTheme) {
22
+ const labels = themeLabels(theme, selectedTheme);
23
+
24
+ const name = labels.includes('selected')
25
+ ? chalk.bold.cyan(theme.name)
26
+ : chalk.white(theme.name);
27
+
28
+ const marks = labels.map(label => label === 'selected'
29
+ ? chalk.cyan(t('theme.mark.selected'))
30
+ : chalk.green(t('theme.mark.published')));
31
+
32
+ return [name, chalk.gray(`v${theme.version}`), ...marks].join(' ');
33
+ }