git-slot-machine 2.3.2 → 2.4.0

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.
Files changed (64) hide show
  1. package/package.json +6 -1
  2. package/.claude/release.md +0 -74
  3. package/CHANGELOG.md +0 -250
  4. package/dist/animation/slotMachine.d.ts.map +0 -1
  5. package/dist/animation/slotMachine.js.map +0 -1
  6. package/dist/api.d.ts.map +0 -1
  7. package/dist/api.js.map +0 -1
  8. package/dist/balance.d.ts.map +0 -1
  9. package/dist/balance.js.map +0 -1
  10. package/dist/commands/auth.d.ts.map +0 -1
  11. package/dist/commands/auth.js.map +0 -1
  12. package/dist/commands/balance.d.ts.map +0 -1
  13. package/dist/commands/balance.js.map +0 -1
  14. package/dist/commands/config.d.ts.map +0 -1
  15. package/dist/commands/config.js.map +0 -1
  16. package/dist/commands/init.d.ts.map +0 -1
  17. package/dist/commands/init.js.map +0 -1
  18. package/dist/commands/play.d.ts.map +0 -1
  19. package/dist/commands/play.js.map +0 -1
  20. package/dist/commands/spin.d.ts.map +0 -1
  21. package/dist/commands/spin.js.map +0 -1
  22. package/dist/commands/sync.d.ts.map +0 -1
  23. package/dist/commands/sync.js.map +0 -1
  24. package/dist/commands/test.d.ts.map +0 -1
  25. package/dist/commands/test.js.map +0 -1
  26. package/dist/config.d.ts.map +0 -1
  27. package/dist/config.js.map +0 -1
  28. package/dist/index.d.ts.map +0 -1
  29. package/dist/index.js.map +0 -1
  30. package/dist/patterns.d.ts.map +0 -1
  31. package/dist/patterns.js.map +0 -1
  32. package/dist/secrets.d.ts.map +0 -1
  33. package/dist/secrets.js.map +0 -1
  34. package/dist/templates/post-commit.d.ts.map +0 -1
  35. package/dist/templates/post-commit.js.map +0 -1
  36. package/dist/utils/amendDetector.d.ts.map +0 -1
  37. package/dist/utils/amendDetector.js.map +0 -1
  38. package/dist/utils/fetch-polyfill.d.ts.map +0 -1
  39. package/dist/utils/fetch-polyfill.js.map +0 -1
  40. package/dist/utils/git.d.ts.map +0 -1
  41. package/dist/utils/git.js.map +0 -1
  42. package/jest.config.js +0 -12
  43. package/src/animation/slotMachine.ts +0 -164
  44. package/src/api.ts +0 -207
  45. package/src/balance.ts +0 -118
  46. package/src/commands/auth.ts +0 -92
  47. package/src/commands/balance.ts +0 -28
  48. package/src/commands/config.ts +0 -59
  49. package/src/commands/init.ts +0 -259
  50. package/src/commands/play.ts +0 -196
  51. package/src/commands/spin.ts +0 -17
  52. package/src/commands/sync.ts +0 -49
  53. package/src/commands/test.ts +0 -19
  54. package/src/config.ts +0 -189
  55. package/src/index.ts +0 -136
  56. package/src/patterns.test.ts +0 -44
  57. package/src/patterns.ts +0 -313
  58. package/src/secrets.ts +0 -44
  59. package/src/templates/post-commit.ts +0 -15
  60. package/src/utils/amendDetector.ts +0 -74
  61. package/src/utils/fetch-polyfill.ts +0 -13
  62. package/src/utils/git.ts +0 -88
  63. package/test.txt +0 -2
  64. package/tsconfig.json +0 -21
package/jest.config.js DELETED
@@ -1,12 +0,0 @@
1
- module.exports = {
2
- preset: 'ts-jest',
3
- testEnvironment: 'node',
4
- roots: ['<rootDir>/src'],
5
- testMatch: ['**/*.test.ts'],
6
- moduleFileExtensions: ['ts', 'js'],
7
- collectCoverageFrom: [
8
- 'src/**/*.ts',
9
- '!src/**/*.test.ts',
10
- '!src/**/*.d.ts'
11
- ]
12
- };
@@ -1,164 +0,0 @@
1
- import chalk from 'chalk';
2
- import { PatternResult } from '../patterns.js';
3
-
4
- const HEX_CHARS = '0123456789abcdef'.split('');
5
- const ANIMATION_SPEED = 50; // ms per frame
6
- const SPIN_DURATION = 2000; // total animation time
7
- const FRAMES = SPIN_DURATION / ANIMATION_SPEED;
8
-
9
- export interface SlotConfig {
10
- finalHash: string;
11
- small: boolean;
12
- patternResult?: PatternResult;
13
- }
14
-
15
- function getRandomHexChar(): string {
16
- return HEX_CHARS[Math.floor(Math.random() * HEX_CHARS.length)];
17
- }
18
-
19
- function clearLine(): void {
20
- process.stdout.write('\r\x1b[K');
21
- }
22
-
23
- function drawSlotMachine(chars: string[], spinning: boolean, highlightIndices: number[] = [], flash: boolean = false): void {
24
- // Casino color palette: red borders, white title
25
- const borderColor = chalk.rgb(220, 20, 60); // Crimson red
26
- const titleColor = chalk.white; // White
27
-
28
- const borderWidth = 39;
29
- const border = '═'.repeat(borderWidth);
30
- const topBorder = borderColor('╔' + border + '╗');
31
- const middleBorder = borderColor('╠' + border + '╣');
32
- const bottomBorder = borderColor('╚' + border + '╝');
33
-
34
- // Title line - emojis count as 2 visual chars each
35
- const titleText = 'GIT SLOT MACHINE';
36
- const titleVisualWidth = 2 + 2 + titleText.length + 2 + 2; // emoji + spaces + text + spaces + emoji
37
- const titlePadding = Math.floor((borderWidth - titleVisualWidth) / 2);
38
- const titleRightPad = borderWidth - titleVisualWidth - titlePadding;
39
- const titleLine = borderColor('║') + ' '.repeat(titlePadding) + chalk.rgb(255, 255, 255)('🎰 ' + titleText + ' 🎰') + ' '.repeat(titleRightPad) + borderColor('║');
40
-
41
- console.log(topBorder);
42
- console.log(titleLine);
43
- console.log(middleBorder);
44
-
45
- // Display the 7 characters as slot reels
46
- const display = chars.map((char, i) => {
47
- if (spinning) {
48
- // Spinning - white blur
49
- return chalk.rgb(255, 255, 255).bold(char);
50
- } else {
51
- // Check if this character should be highlighted
52
- const isHighlighted = highlightIndices.includes(i);
53
-
54
- if (isHighlighted && flash) {
55
- // Flash state - yellow inverse (yellow background, black text)
56
- return chalk.bgRgb(255, 255, 0).rgb(0, 0, 0).bold(char);
57
- } else if (isHighlighted) {
58
- // Normal highlighted state - yellow inverse (yellow background, black text)
59
- return chalk.bgRgb(255, 255, 0).rgb(0, 0, 0).bold(char);
60
- } else {
61
- // Not highlighted - white text
62
- return chalk.rgb(255, 255, 255)(char);
63
- }
64
- }
65
- }).join(' ');
66
-
67
- // Calculate padding for character display (7 chars + 6 double-space separators = 19 visual chars)
68
- const displayVisualWidth = 7 + 12; // 7 chars + 6*2 spaces
69
- const displayPadding = Math.floor((borderWidth - displayVisualWidth) / 2);
70
- const displayRightPad = borderWidth - displayVisualWidth - displayPadding;
71
- const displayLine = borderColor('║') + ' '.repeat(displayPadding) + display + ' '.repeat(displayRightPad) + borderColor('║');
72
-
73
- console.log(displayLine);
74
- console.log(bottomBorder);
75
- }
76
-
77
- export async function animateSlotMachine(config: SlotConfig): Promise<void> {
78
- const { finalHash, patternResult } = config;
79
- const highlightIndices = patternResult?.highlightIndices || [];
80
- const isCI = !!process.env.CLAUDECODE || !!process.env.CI;
81
-
82
- const finalChars = finalHash.split('');
83
-
84
- if (!isCI) {
85
- // Clear screen
86
- console.clear();
87
-
88
- // Initialize with random characters
89
- let currentChars = Array(7).fill(0).map(() => getRandomHexChar());
90
-
91
- // Animate spinning
92
- for (let frame = 0; frame < FRAMES; frame++) {
93
- // Gradually slow down and settle on final hash
94
- const progress = frame / FRAMES;
95
-
96
- if (progress < 0.9) {
97
- // Still spinning - show random
98
- currentChars = currentChars.map(() => getRandomHexChar());
99
- } else {
100
- // Start settling - reveal characters one by one
101
- const revealIndex = Math.floor((progress - 0.9) / 0.1 * 7);
102
- for (let i = 0; i < revealIndex; i++) {
103
- currentChars[i] = finalHash[i];
104
- }
105
- }
106
-
107
- // Redraw
108
- console.clear();
109
- drawSlotMachine(currentChars, progress < 0.9);
110
-
111
- // Wait for next frame
112
- await new Promise(resolve => setTimeout(resolve, ANIMATION_SPEED));
113
- }
114
-
115
- // Flash 3 times if there are highlighted characters
116
- if (highlightIndices.length > 0) {
117
- for (let flashCount = 0; flashCount < 3; flashCount++) {
118
- console.clear();
119
- drawSlotMachine(finalChars, false, highlightIndices, true);
120
- await new Promise(resolve => setTimeout(resolve, 200));
121
-
122
- console.clear();
123
- drawSlotMachine(finalChars, false, highlightIndices, false);
124
- await new Promise(resolve => setTimeout(resolve, 200));
125
- }
126
- }
127
-
128
- // Steady state
129
- console.clear();
130
- }
131
-
132
- drawSlotMachine(finalChars, false, highlightIndices, false);
133
- }
134
-
135
- export async function animateSmallMode(config: SlotConfig): Promise<void> {
136
- const { finalHash, patternResult } = config;
137
- const highlightIndices = patternResult?.highlightIndices || [];
138
- const isCI = !!process.env.CLAUDECODE || !!process.env.CI;
139
-
140
- if (!isCI) {
141
- // Single line, rapid character flicker
142
- process.stdout.write(chalk.cyan('🎰 '));
143
-
144
- for (let frame = 0; frame < 20; frame++) {
145
- const chars = Array(7).fill(0).map(() => getRandomHexChar()).join('');
146
- clearLine();
147
- process.stdout.write(chalk.cyan('🎰 ') + chalk.rgb(255, 255, 255)(chars));
148
- await new Promise(resolve => setTimeout(resolve, 50));
149
- }
150
-
151
- clearLine();
152
- }
153
-
154
- // Final with highlighting - don't add newline, let the caller add result info
155
- const display = finalHash.split('').map((char, i) => {
156
- if (highlightIndices.includes(i)) {
157
- return chalk.bgRgb(255, 255, 0).rgb(0, 0, 0).bold(char);
158
- } else {
159
- return chalk.rgb(255, 255, 255)(char);
160
- }
161
- }).join('');
162
- process.stdout.write(chalk.cyan('🎰 ') + display);
163
- // Don't write newline - let caller continue on same line
164
- }
package/src/api.ts DELETED
@@ -1,207 +0,0 @@
1
- import { getApiUrl, getApiToken, isSyncEnabled } from './config.js';
2
- import { getFetch } from './utils/fetch-polyfill.js';
3
-
4
- // Fallback domains to try in order (if primary fails)
5
- const FALLBACK_DOMAINS = [
6
- 'https://gitslotmachinecom-main-vilmm1.laravel.cloud',
7
- ];
8
-
9
- export interface PlayData {
10
- commit_hash: string;
11
- commit_full_hash: string;
12
- pattern_type: string;
13
- pattern_name: string;
14
- payout: number;
15
- wager: number;
16
- balance_before: number;
17
- balance_after: number;
18
- repo_url: string;
19
- github_username: string;
20
- repo_owner: string;
21
- repo_name: string;
22
- }
23
-
24
- export interface ApiResponse<T = any> {
25
- success: boolean;
26
- data?: T;
27
- message?: string;
28
- }
29
-
30
- export interface BalanceResponse {
31
- balance: number;
32
- total_commits: number;
33
- total_winnings: number;
34
- biggest_win: number;
35
- biggest_win_pattern?: string;
36
- biggest_win_hash?: string;
37
- }
38
-
39
- // Helper to build headers with authentication
40
- function getHeaders(): Record<string, string> {
41
- const headers: Record<string, string> = {
42
- 'Content-Type': 'application/json',
43
- 'Accept': 'application/json',
44
- };
45
-
46
- const token = getApiToken();
47
- if (token) {
48
- headers['Authorization'] = `Bearer ${token}`;
49
- }
50
-
51
- return headers;
52
- }
53
-
54
- // Check if API sync is enabled and available
55
- export function isApiAvailable(): boolean {
56
- return isSyncEnabled() && getApiToken() !== null;
57
- }
58
-
59
- export interface PlayResponse {
60
- balance: number;
61
- payout: number;
62
- pattern_name: string;
63
- share_url?: string;
64
- }
65
-
66
- // Helper to try API call with fallback domains
67
- async function fetchWithFallback(endpoint: string, options: RequestInit): Promise<Response | null> {
68
- const configuredUrl = getApiUrl();
69
- const fetchFn = await getFetch();
70
-
71
- // Build list of URLs to try: configured URL first, then fallbacks (excluding duplicates)
72
- const urlsToTry = [
73
- configuredUrl,
74
- ...FALLBACK_DOMAINS.filter(domain => !configuredUrl.startsWith(domain))
75
- ];
76
-
77
- for (const baseUrl of urlsToTry) {
78
- try {
79
- const url = `${baseUrl.replace(/\/api$/, '')}/api${endpoint}`;
80
- const response = await fetchFn(url, options);
81
-
82
- if (response.ok) {
83
- return response;
84
- }
85
-
86
- // If not ok, try next domain
87
- continue;
88
- } catch (error) {
89
- // Network error, try next domain
90
- continue;
91
- }
92
- }
93
-
94
- return null;
95
- }
96
-
97
- // Send play data to API
98
- export async function sendPlayToAPI(data: PlayData): Promise<PlayResponse | null> {
99
- if (!isApiAvailable()) {
100
- return null;
101
- }
102
-
103
- try {
104
- const response = await fetchWithFallback('/play', {
105
- method: 'POST',
106
- headers: getHeaders(),
107
- body: JSON.stringify(data),
108
- });
109
-
110
- if (!response) {
111
- return null;
112
- }
113
-
114
- const result = await response.json() as ApiResponse<PlayResponse>;
115
- return result.data || null;
116
- } catch (error) {
117
- // Silently fail if offline or API unavailable
118
- // The user still gets local feedback
119
- return null;
120
- }
121
- }
122
-
123
- // Get balance from API
124
- export async function getBalance(): Promise<BalanceResponse | null> {
125
- if (!isApiAvailable()) {
126
- return null;
127
- }
128
-
129
- try {
130
- const response = await fetchWithFallback('/balance', {
131
- method: 'GET',
132
- headers: getHeaders(),
133
- });
134
-
135
- if (!response) {
136
- return null;
137
- }
138
-
139
- const result = await response.json() as ApiResponse<BalanceResponse>;
140
- return result.data || null;
141
- } catch (error) {
142
- return null;
143
- }
144
- }
145
-
146
- // Create API token (simplified - just pass github username)
147
- export async function createToken(githubUsername: string): Promise<string | null> {
148
- try {
149
- const response = await fetchWithFallback('/auth/token', {
150
- method: 'POST',
151
- headers: {
152
- 'Content-Type': 'application/json',
153
- 'Accept': 'application/json',
154
- },
155
- body: JSON.stringify({
156
- github_username: githubUsername,
157
- }),
158
- });
159
-
160
- if (!response) {
161
- console.error('Failed to reach API server. Please check your network connection.');
162
- return null;
163
- }
164
-
165
- const result = await response.json() as ApiResponse<{ token: string }>;
166
- return result.data?.token || null;
167
- } catch (error) {
168
- console.error('API request failed:', (error as Error).message);
169
- return null;
170
- }
171
- }
172
-
173
- // Verify token is valid
174
- export async function verifyToken(token: string): Promise<boolean> {
175
- try {
176
- const response = await fetchWithFallback('/auth/user', {
177
- method: 'GET',
178
- headers: {
179
- 'Content-Type': 'application/json',
180
- 'Accept': 'application/json',
181
- 'Authorization': `Bearer ${token}`,
182
- },
183
- });
184
-
185
- return response !== null && response.ok;
186
- } catch (error) {
187
- return false;
188
- }
189
- }
190
-
191
- // Logout (revoke token)
192
- export async function logout(): Promise<boolean> {
193
- if (!getApiToken()) {
194
- return true;
195
- }
196
-
197
- try {
198
- const response = await fetchWithFallback('/auth/token', {
199
- method: 'DELETE',
200
- headers: getHeaders(),
201
- });
202
-
203
- return response !== null && response.ok;
204
- } catch (error) {
205
- return false;
206
- }
207
- }
package/src/balance.ts DELETED
@@ -1,118 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import * as os from 'os';
4
-
5
- interface BalanceData {
6
- repos: Record<string, {
7
- balance: number;
8
- totalCommits: number;
9
- totalWinnings: number;
10
- biggestWin: number;
11
- lastCommit: string;
12
- }>;
13
- }
14
-
15
- const BALANCE_FILE = path.join(os.homedir(), '.git-slot-machine-balance.json');
16
-
17
- function getRepoPath(): string | null {
18
- try {
19
- const { execSync } = require('child_process');
20
- return execSync('git rev-parse --show-toplevel', {
21
- encoding: 'utf-8',
22
- stdio: ['pipe', 'pipe', 'pipe']
23
- }).trim();
24
- } catch {
25
- // Not in a git repo - use global balance instead
26
- return null;
27
- }
28
- }
29
-
30
- function loadBalance(): BalanceData {
31
- if (!fs.existsSync(BALANCE_FILE)) {
32
- return { repos: {} };
33
- }
34
-
35
- const data = fs.readFileSync(BALANCE_FILE, 'utf-8');
36
- return JSON.parse(data);
37
- }
38
-
39
- function saveBalance(data: BalanceData): void {
40
- fs.writeFileSync(BALANCE_FILE, JSON.stringify(data, null, 2));
41
- }
42
-
43
- export function getBalance(): number {
44
- const repoPath = getRepoPath() || 'global';
45
- const data = loadBalance();
46
-
47
- if (!data.repos[repoPath]) {
48
- // Initialize new repo
49
- data.repos[repoPath] = {
50
- balance: 100,
51
- totalCommits: 0,
52
- totalWinnings: 0,
53
- biggestWin: 0,
54
- lastCommit: ''
55
- };
56
- saveBalance(data);
57
- }
58
-
59
- return data.repos[repoPath].balance;
60
- }
61
-
62
- export function updateBalance(hash: string, payout: number): number {
63
- const repoPath = getRepoPath() || 'global';
64
- const data = loadBalance();
65
-
66
- if (!data.repos[repoPath]) {
67
- data.repos[repoPath] = {
68
- balance: 100,
69
- totalCommits: 0,
70
- totalWinnings: 0,
71
- biggestWin: 0,
72
- lastCommit: ''
73
- };
74
- }
75
-
76
- const repo = data.repos[repoPath];
77
-
78
- // Deduct cost
79
- repo.balance -= 10;
80
- repo.totalCommits += 1;
81
-
82
- // Add winnings
83
- if (payout > 0) {
84
- repo.balance += payout;
85
- repo.totalWinnings += payout;
86
- repo.biggestWin = Math.max(repo.biggestWin, payout);
87
- }
88
-
89
- repo.lastCommit = hash;
90
-
91
- saveBalance(data);
92
- return repo.balance;
93
- }
94
-
95
- export function setBalance(newBalance: number): void {
96
- const repoPath = getRepoPath() || 'global';
97
- const data = loadBalance();
98
-
99
- if (!data.repos[repoPath]) {
100
- data.repos[repoPath] = {
101
- balance: newBalance,
102
- totalCommits: 0,
103
- totalWinnings: 0,
104
- biggestWin: 0,
105
- lastCommit: ''
106
- };
107
- } else {
108
- data.repos[repoPath].balance = newBalance;
109
- }
110
-
111
- saveBalance(data);
112
- }
113
-
114
- export function getRepoStats() {
115
- const repoPath = getRepoPath() || 'global';
116
- const data = loadBalance();
117
- return data.repos[repoPath] || null;
118
- }
@@ -1,92 +0,0 @@
1
- import chalk from 'chalk';
2
- import { createToken, logout as apiLogout, verifyToken } from '../api.js';
3
- import { setApiToken, clearApiToken, getApiToken, getApiUrl, setGitHubUsername } from '../config.js';
4
-
5
- export async function authLoginCommand(githubUsername: string): Promise<void> {
6
- try {
7
- console.log(chalk.dim(`Generating token for ${githubUsername}...`));
8
-
9
- // Generate token from GitHub username
10
- const token = await createToken(githubUsername);
11
-
12
- if (!token) {
13
- console.error(chalk.red('Failed to generate token. Please check your GitHub username.'));
14
- process.exit(1);
15
- }
16
-
17
- // Save token and username
18
- setApiToken(token);
19
- setGitHubUsername(githubUsername);
20
-
21
- console.log(chalk.green('Successfully authenticated!'));
22
- console.log(chalk.dim(`Token saved. API URL: ${getApiUrl()}`));
23
- console.log(chalk.dim(`GitHub Username: ${githubUsername}`));
24
- console.log();
25
- console.log(chalk.yellow('Data sent to server on each commit:'));
26
- console.log(chalk.dim(' • Commit hash (7 and 40 character versions)'));
27
- console.log(chalk.dim(' • Repository URL, owner, and name'));
28
- console.log(chalk.dim(' • GitHub username'));
29
- console.log(chalk.dim(' • Pattern type, payout, and balance'));
30
- console.log();
31
- console.log(chalk.dim('To disable sync: git-slot-machine config set sync-enabled false'));
32
- } catch (error) {
33
- console.error(chalk.red(`Error: ${(error as Error).message}`));
34
- process.exit(1);
35
- }
36
- }
37
-
38
- export async function authLogoutCommand(): Promise<void> {
39
- try {
40
- const token = getApiToken();
41
-
42
- if (!token) {
43
- console.log(chalk.yellow('Not currently authenticated.'));
44
- return;
45
- }
46
-
47
- // Try to revoke token on server
48
- await apiLogout();
49
-
50
- // Clear local token
51
- clearApiToken();
52
-
53
- console.log(chalk.green('Successfully logged out.'));
54
- } catch (error) {
55
- console.error(chalk.red(`Error: ${(error as Error).message}`));
56
- process.exit(1);
57
- }
58
- }
59
-
60
- export async function authStatusCommand(): Promise<void> {
61
- try {
62
- const token = getApiToken();
63
- const apiUrl = getApiUrl();
64
-
65
- if (!token) {
66
- console.log(chalk.yellow('Not authenticated.'));
67
- console.log(chalk.dim(`API URL: ${apiUrl}`));
68
- console.log();
69
- console.log('To authenticate, run:');
70
- console.log(chalk.cyan(' git-slot-machine auth login <your-github-username>'));
71
- return;
72
- }
73
-
74
- // Verify token is still valid
75
- const isValid = await verifyToken(token);
76
-
77
- if (isValid) {
78
- console.log(chalk.green('Authenticated'));
79
- console.log(chalk.dim(`API URL: ${apiUrl}`));
80
- console.log(chalk.dim(`Token: ${token.substring(0, 10)}...`));
81
- } else {
82
- console.log(chalk.red('Authentication expired or invalid.'));
83
- console.log(chalk.dim(`API URL: ${apiUrl}`));
84
- console.log();
85
- console.log('Please login again:');
86
- console.log(chalk.cyan(' git-slot-machine auth login <your-github-username>'));
87
- }
88
- } catch (error) {
89
- console.error(chalk.red(`Error: ${(error as Error).message}`));
90
- process.exit(1);
91
- }
92
- }
@@ -1,28 +0,0 @@
1
- import chalk from 'chalk';
2
- import { getRepoStats } from '../balance.js';
3
-
4
- export function balanceCommand(): void {
5
- try {
6
- const stats = getRepoStats();
7
-
8
- if (!stats) {
9
- console.log(chalk.yellow('No balance data for this repository'));
10
- console.log(chalk.dim('Run a commit or use "git-slot-machine spin" to start playing'));
11
- return;
12
- }
13
-
14
- console.log();
15
- console.log(chalk.cyan.bold('Repository Stats'));
16
- console.log(chalk.dim('━'.repeat(40)));
17
- console.log(chalk.white(`Balance: ${stats.balance >= 0 ? chalk.green(stats.balance) : chalk.red(stats.balance)} points`));
18
- console.log(chalk.white(`Total Commits: ${stats.totalCommits}`));
19
- console.log(chalk.white(`Total Winnings: ${chalk.yellow(stats.totalWinnings)} points`));
20
- console.log(chalk.white(`Biggest Win: ${chalk.yellow(stats.biggestWin)} points`));
21
- console.log(chalk.white(`Last Commit: ${chalk.dim(stats.lastCommit)}`));
22
- console.log();
23
-
24
- } catch (error) {
25
- console.error(chalk.red(`Error: ${(error as Error).message}`));
26
- process.exit(1);
27
- }
28
- }
@@ -1,59 +0,0 @@
1
- import chalk from 'chalk';
2
- import {
3
- getApiUrl,
4
- setApiUrl,
5
- isSyncEnabled,
6
- setSyncEnabled,
7
- getConfig
8
- } from '../config.js';
9
-
10
- export async function configGetCommand(key: string): Promise<void> {
11
- try {
12
- const config = getConfig();
13
-
14
- switch (key) {
15
- case 'api-url':
16
- console.log(getApiUrl());
17
- break;
18
- case 'sync-enabled':
19
- console.log(isSyncEnabled());
20
- break;
21
- case 'all':
22
- console.log(chalk.bold('Configuration:'));
23
- console.log(` API URL: ${chalk.cyan(getApiUrl())}`);
24
- console.log(` Sync Enabled: ${chalk.cyan(isSyncEnabled())}`);
25
- console.log(` Has Token: ${chalk.cyan(config.apiToken ? 'yes' : 'no')}`);
26
- break;
27
- default:
28
- console.error(chalk.red(`Unknown config key: ${key}`));
29
- console.log('Available keys: api-url, sync-enabled, all');
30
- process.exit(1);
31
- }
32
- } catch (error) {
33
- console.error(chalk.red(`Error: ${(error as Error).message}`));
34
- process.exit(1);
35
- }
36
- }
37
-
38
- export async function configSetCommand(key: string, value: string): Promise<void> {
39
- try {
40
- switch (key) {
41
- case 'api-url':
42
- setApiUrl(value);
43
- console.log(chalk.green(`API URL set to: ${value}`));
44
- break;
45
- case 'sync-enabled':
46
- const enabled = value.toLowerCase() === 'true' || value === '1';
47
- setSyncEnabled(enabled);
48
- console.log(chalk.green(`Sync ${enabled ? 'enabled' : 'disabled'}`));
49
- break;
50
- default:
51
- console.error(chalk.red(`Unknown config key: ${key}`));
52
- console.log('Available keys: api-url, sync-enabled');
53
- process.exit(1);
54
- }
55
- } catch (error) {
56
- console.error(chalk.red(`Error: ${(error as Error).message}`));
57
- process.exit(1);
58
- }
59
- }