tsoft-cli 2.6.15 → 3.4.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.
@@ -0,0 +1,219 @@
1
+ import chalk from 'chalk';
2
+ import { createRequire } from 'module';
3
+ import { TSOFT_COLORS, createTSoftGradient } from './prompt-wrapper.js';
4
+ import { humanOut, isJsonMode, jsonOut } from '../output-mode.js';
5
+ import { t } from '../i18n.js';
6
+ import { loadTokens, getActiveStore, getActiveTheme } from '../storage.js';
7
+
8
+ const require = createRequire(import.meta.url);
9
+
10
+ /**
11
+ * Read version from package.json
12
+ */
13
+ function getVersion() {
14
+ try {
15
+ const pkg = require('../../package.json');
16
+ return pkg.version || '0.0.0';
17
+ } catch {
18
+ return '0.0.0';
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Hardcoded ASCII art for "TSOFT" — compact 5-line design
24
+ */
25
+ const TSOFT_ASCII_ART = `
26
+ ████████╗███████╗ ██████╗ ███████╗████████╗
27
+ ██╔══╝██╔════╝██╔═══██╗██╔════╝╚══██╔══╝
28
+ ██║ ███████╗██║ ██║█████╗ ██║
29
+ ██║ ╚════██║██║ ██║██╔══╝ ██║
30
+ ██║ ███████║╚██████╔╝██║ ██║
31
+ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝
32
+ `.trim();
33
+
34
+ /**
35
+ * Command groups definition — maps group key to command entries.
36
+ * Each entry has a nameKey (locale) and command path for display.
37
+ */
38
+ const COMMAND_GROUPS = [
39
+ {
40
+ groupKey: 'help.group.development',
41
+ commands: [
42
+ { display: 'theme dev', descKey: 'help.cmd.theme_dev' },
43
+ { display: 'theme push', descKey: 'help.cmd.theme_push' },
44
+ { display: 'theme section list', descKey: 'help.cmd.theme_section_list' },
45
+ { display: 'theme section add', descKey: 'help.cmd.theme_section_add' },
46
+ ]
47
+ },
48
+ {
49
+ groupKey: 'help.group.theme_management',
50
+ commands: [
51
+ { display: 'theme list', descKey: 'help.cmd.theme_list' },
52
+ { display: 'theme create', descKey: 'help.cmd.theme_create' },
53
+ { display: 'theme pull', descKey: 'help.cmd.theme_pull' },
54
+ { display: 'theme use', descKey: 'help.cmd.theme_use' },
55
+ { display: 'theme init', descKey: 'help.cmd.theme_init' },
56
+ ]
57
+ },
58
+ {
59
+ groupKey: 'help.group.account',
60
+ commands: [
61
+ { display: 'login', descKey: 'help.cmd.login' },
62
+ { display: 'logout', descKey: 'help.cmd.logout' },
63
+ { display: 'whoami', descKey: 'help.cmd.whoami' },
64
+ { display: 'org switch', descKey: 'help.cmd.org_switch' },
65
+ ]
66
+ }
67
+ ];
68
+
69
+ /**
70
+ * Compute the max display name length across all command groups
71
+ * for consistent column alignment.
72
+ */
73
+ function computeMaxNameWidth() {
74
+ let max = 0;
75
+ for (const group of COMMAND_GROUPS) {
76
+ for (const cmd of group.commands) {
77
+ if (cmd.display.length > max) max = cmd.display.length;
78
+ }
79
+ }
80
+ return max;
81
+ }
82
+
83
+ /**
84
+ * Render a single command group block.
85
+ * @param {object} group
86
+ * @param {number} maxWidth - max command name width for column alignment
87
+ * @returns {string[]} lines
88
+ */
89
+ function renderGroup(group, maxWidth) {
90
+ const lines = [];
91
+ const groupName = t(group.groupKey);
92
+ lines.push(' ' + chalk.bold.white(groupName));
93
+ lines.push('');
94
+ for (const cmd of group.commands) {
95
+ const padding = ' '.repeat(maxWidth - cmd.display.length + 2);
96
+ const namePart = chalk.hex(TSOFT_COLORS.primary)('tsoft ' + cmd.display);
97
+ const descPart = chalk.dim(t(cmd.descKey));
98
+ lines.push(' ' + namePart + padding + descPart);
99
+ }
100
+ return lines;
101
+ }
102
+
103
+ /**
104
+ * Read contextual status data (logged-in user, store, active theme).
105
+ * Returns all nulls gracefully on any error.
106
+ * @returns {Promise<{store: string|null, tokens: object|null, activeTheme: string|null}>}
107
+ */
108
+ async function loadStatusData() {
109
+ try {
110
+ const store = await getActiveStore();
111
+ const tokens = store ? await loadTokens(store) : null;
112
+ const activeTheme = await getActiveTheme();
113
+ return { store, tokens, activeTheme };
114
+ } catch {
115
+ return { store: null, tokens: null, activeTheme: null };
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Build status block lines from context data.
121
+ * @param {{store: string|null, tokens: object|null, activeTheme: string|null}} status
122
+ * @returns {string[]} lines to print
123
+ */
124
+ function buildStatusLines(status) {
125
+ const { store, tokens, activeTheme } = status;
126
+ const lines = [];
127
+ const orangeBullet = chalk.hex(TSOFT_COLORS.primary)('●');
128
+
129
+ // User line
130
+ if (tokens?.user?.email) {
131
+ const userText = t('help.status.logged_in', { email: tokens.user.email, store: store || '' });
132
+ lines.push(' ' + orangeBullet + ' ' + userText);
133
+ } else {
134
+ lines.push(' ' + chalk.dim('○ ' + t('help.status.not_logged_in')));
135
+ }
136
+
137
+ // Organization line — only shown when available
138
+ const orgName = tokens?.user?.organizationName;
139
+ if (orgName) {
140
+ lines.push(' ' + orangeBullet + ' ' + orgName);
141
+ }
142
+
143
+ // Theme line
144
+ if (activeTheme) {
145
+ const themeText = t('help.status.active_theme', { theme: activeTheme });
146
+ lines.push(' ' + orangeBullet + ' ' + themeText);
147
+ } else {
148
+ lines.push(' ' + chalk.dim('○ ' + t('help.status.no_theme')));
149
+ }
150
+
151
+ return lines;
152
+ }
153
+
154
+ /**
155
+ * Render the branded help to stdout.
156
+ * Wraps all human-readable output in humanOut().
157
+ * In JSON mode, outputs structured data instead.
158
+ *
159
+ * @param {import('commander').Command} _program — kept for future use / extensibility
160
+ */
161
+ export async function renderBrandedHelp(_program) {
162
+ const status = await loadStatusData();
163
+
164
+ if (isJsonMode()) {
165
+ const groups = COMMAND_GROUPS.map(g => ({
166
+ group: t(g.groupKey),
167
+ commands: g.commands.map(c => ({
168
+ command: 'tsoft ' + c.display,
169
+ description: t(c.descKey)
170
+ }))
171
+ }));
172
+
173
+ const commands = groups.flatMap(g => g.commands);
174
+ jsonOut({
175
+ user: status.tokens?.user || null,
176
+ store: status.store,
177
+ activeTheme: status.activeTheme,
178
+ commands,
179
+ groups,
180
+ });
181
+ return;
182
+ }
183
+
184
+ humanOut(() => {
185
+ const version = getVersion();
186
+ const maxWidth = computeMaxNameWidth();
187
+
188
+ // Header — ASCII art with orange gradient
189
+ console.log('');
190
+ console.log(createTSoftGradient(TSOFT_ASCII_ART));
191
+ console.log('');
192
+
193
+ // Tagline + version
194
+ const tagline = chalk.dim(t('help.tagline'));
195
+ const versionBadge = chalk.dim('v' + version);
196
+ console.log(' ' + tagline + ' ' + versionBadge);
197
+
198
+ // Contextual status block
199
+ console.log('');
200
+ const statusLines = buildStatusLines(status);
201
+ for (const line of statusLines) {
202
+ console.log(line);
203
+ }
204
+ console.log('');
205
+
206
+ // Command groups
207
+ for (const group of COMMAND_GROUPS) {
208
+ const groupLines = renderGroup(group, maxWidth);
209
+ for (const line of groupLines) {
210
+ console.log(line);
211
+ }
212
+ console.log('');
213
+ }
214
+
215
+ // Footer hint
216
+ console.log(' ' + chalk.dim(t('help.footer')));
217
+ console.log('');
218
+ });
219
+ }
@@ -0,0 +1,183 @@
1
+ import boxen from 'boxen';
2
+ import gradient from 'gradient-string';
3
+ import chalk from 'chalk';
4
+ import {input as inquirerInput, confirm as inquirerConfirm, select as inquirerSelect} from '@inquirer/prompts';
5
+ import { t } from '../i18n.js';
6
+
7
+ /**
8
+ * T-Soft branding renkleri
9
+ */
10
+ export const TSOFT_ORANGE = '#FF6B35';
11
+ export const TSOFT_COLORS = {
12
+ primary: TSOFT_ORANGE,
13
+ light: '#FFA500',
14
+ dark: '#FF4500'
15
+ };
16
+
17
+ /**
18
+ * T-Soft gradient oluşturur
19
+ */
20
+ export function createTSoftGradient(text) {
21
+ return gradient([TSOFT_COLORS.light, TSOFT_COLORS.primary, TSOFT_COLORS.dark])(text);
22
+ }
23
+
24
+ /**
25
+ * Box içinde branding ile mesaj gösterir
26
+ * @param {string} message - Gösterilecek mesaj
27
+ * @param {string} title - Sol üst başlık
28
+ * @param {object} options - Boxen seçenekleri
29
+ */
30
+ export function showBrandedBox(message, title = '', options = {}) {
31
+ // T-Soft branding'ini mesajın sonuna sağa hizalanmış olarak ekle
32
+ const tsoftBranding = createTSoftGradient('T-Soft');
33
+ const brandingPadding = ' '.repeat(50); // Sağa hizalama için boşluk
34
+ const messageWithBranding = `${message}\n\n${brandingPadding}${tsoftBranding}`;
35
+
36
+ const defaultOptions = {
37
+ padding: 1,
38
+ margin: {top: 0, bottom: 0, left: 0, right: 0},
39
+ borderStyle: 'round',
40
+ borderColor: TSOFT_ORANGE,
41
+ title: title,
42
+ titleAlignment: 'left',
43
+ ...options
44
+ };
45
+
46
+ const box = boxen(messageWithBranding, defaultOptions);
47
+ console.log('\n' + box + '\n');
48
+ }
49
+
50
+ /**
51
+ * Özelleştirilmiş confirm prompt
52
+ * @param {object} options - Prompt seçenekleri
53
+ * @param {string} boxTitle - Box başlığı
54
+ */
55
+ export async function brandedConfirm(options, boxTitle = t('ui.label.confirm')) {
56
+ const {message, ...restOptions} = options;
57
+
58
+ // Box içinde mesajı göster
59
+ showBrandedBox(message, boxTitle);
60
+
61
+ // Prompt'u çalıştır
62
+ return await inquirerConfirm({
63
+ message: t('ui.prompt.continue'),
64
+ ...restOptions
65
+ });
66
+ }
67
+
68
+ /**
69
+ * Özelleştirilmiş select prompt
70
+ * @param {object} options - Prompt seçenekleri
71
+ * @param {string} boxTitle - Box başlığı
72
+ */
73
+ export async function brandedSelect(options, boxTitle = t('ui.label.select')) {
74
+ const {message, choices, ...restOptions} = options;
75
+
76
+ // Box içinde mesajı göster (sadece başlık)
77
+ if (message) {
78
+ showBrandedBox(message, boxTitle);
79
+ }
80
+
81
+ // Choices'ı işle - disabled olanları görsel olarak farklılaştır
82
+ const processedChoices = choices.map(choice => {
83
+ if (choice.disabled) {
84
+ return {
85
+ ...choice,
86
+ name: chalk.gray(choice.name + ` ${t('ui.label.disabled')}`),
87
+ disabled: true
88
+ };
89
+ }
90
+ return choice;
91
+ });
92
+
93
+ // Prompt'u çalıştır
94
+ return await inquirerSelect({
95
+ message: '',
96
+ choices: processedChoices,
97
+ ...restOptions
98
+ });
99
+ }
100
+
101
+ /**
102
+ * Özelleştirilmiş input prompt
103
+ * @param {object} options - Prompt seçenekleri
104
+ * @param {string} boxTitle - Box başlığı
105
+ */
106
+ export async function brandedInput(options, boxTitle = t('ui.label.input')) {
107
+ const {message, ...restOptions} = options;
108
+
109
+ // Box içinde açıklama varsa göster
110
+ if (restOptions.description) {
111
+ showBrandedBox(restOptions.description, boxTitle);
112
+ delete restOptions.description;
113
+ }
114
+
115
+ // Prompt'u çalıştır
116
+ return await inquirerInput({
117
+ message,
118
+ ...restOptions
119
+ });
120
+ }
121
+
122
+ /**
123
+ * Uyarı mesajı gösterir
124
+ * @param {string} message - Uyarı mesajı
125
+ */
126
+ export function showWarning(message) {
127
+ showBrandedBox(message, t('ui.label.warning'), {
128
+ borderColor: 'yellow'
129
+ });
130
+ }
131
+
132
+ /**
133
+ * Hata mesajı gösterir
134
+ * @param {string} message - Hata mesajı
135
+ */
136
+ export function showError(message) {
137
+ showBrandedBox(message, t('ui.label.error'), {
138
+ borderColor: 'red'
139
+ });
140
+ }
141
+
142
+ /**
143
+ * Başarı mesajı gösterir
144
+ * @param {string} message - Başarı mesajı
145
+ */
146
+ export function showSuccess(message) {
147
+ showBrandedBox(message, t('ui.label.success'), {
148
+ borderColor: 'green'
149
+ });
150
+ }
151
+
152
+ /**
153
+ * Bilgi mesajı gösterir
154
+ * @param {string} message - Bilgi mesajı
155
+ */
156
+ export function showInfo(message) {
157
+ showBrandedBox(message, t('ui.label.info'), {
158
+ borderColor: 'blue'
159
+ });
160
+ }
161
+
162
+ /**
163
+ * Tema seçimi için özel prompt
164
+ * @param {string} message - Mesaj
165
+ * @param {array} themes - Tema listesi
166
+ */
167
+ export async function showThemeSelection(message, themes) {
168
+ return await brandedSelect({
169
+ message,
170
+ choices: themes
171
+ }, t('ui.label.theme_selection'));
172
+ }
173
+
174
+ /**
175
+ * Loading göstergesi (gelecekte animasyon için)
176
+ * @param {string} message - Loading mesajı
177
+ */
178
+ export function showLoading(message) {
179
+ showBrandedBox(message, t('ui.label.loading'), {
180
+ borderColor: TSOFT_ORANGE
181
+ });
182
+ }
183
+
package/bin/run.js DELETED
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { execute } from '@oclif/core'
4
-
5
- await execute({ dir: import.meta.url })
package/build/enums.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare const packageJson: any;
package/build/enums.js DELETED
@@ -1,7 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- const __filename = fileURLToPath(import.meta.url);
5
- const __dirname = path.dirname(__filename);
6
- export const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf-8'));
7
- //# sourceMappingURL=enums.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"enums.js","sourceRoot":"","sources":["../enums.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;AAE1C,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAA"}
package/build/index.d.ts DELETED
@@ -1,5 +0,0 @@
1
- import { CLIAllCommands, VersionCommand } from '@tsoft-cli/shared';
2
- export declare const COMMANDS: {
3
- commands: typeof CLIAllCommands;
4
- version: typeof VersionCommand;
5
- };
package/build/index.js DELETED
@@ -1,10 +0,0 @@
1
- import theme from '@tsoft-cli/theme';
2
- import { CLIAllCommands, VersionCommand } from '@tsoft-cli/shared';
3
- import { packageJson } from './enums.js';
4
- VersionCommand.version = packageJson.version;
5
- export const COMMANDS = {
6
- ...theme,
7
- [CLIAllCommands.cliTopic]: CLIAllCommands,
8
- [VersionCommand.cliTopic]: VersionCommand,
9
- };
10
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,kBAAkB,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAExC,cAAc,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAAA;AAE5C,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,GAAG,KAAK;IACR,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,cAAc;IACzC,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,cAAc;CAC1C,CAAA"}