git-slot-machine 1.0.0 → 1.1.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +15 -0
  3. package/dist/animation/slotMachine.d.ts +1 -1
  4. package/dist/animation/slotMachine.d.ts.map +1 -1
  5. package/dist/animation/slotMachine.js +15 -22
  6. package/dist/animation/slotMachine.js.map +1 -1
  7. package/dist/api.js +11 -19
  8. package/dist/api.js.map +1 -1
  9. package/dist/balance.js +7 -46
  10. package/dist/balance.js.map +1 -1
  11. package/dist/commands/auth.js +40 -48
  12. package/dist/commands/auth.js.map +1 -1
  13. package/dist/commands/balance.js +14 -20
  14. package/dist/commands/balance.js.map +1 -1
  15. package/dist/commands/config.js +19 -26
  16. package/dist/commands/config.js.map +1 -1
  17. package/dist/commands/init.d.ts.map +1 -1
  18. package/dist/commands/init.js +87 -90
  19. package/dist/commands/init.js.map +1 -1
  20. package/dist/commands/play.js +31 -37
  21. package/dist/commands/play.js.map +1 -1
  22. package/dist/commands/spin.js +6 -9
  23. package/dist/commands/spin.js.map +1 -1
  24. package/dist/commands/sync.js +23 -29
  25. package/dist/commands/sync.js.map +1 -1
  26. package/dist/commands/test.js +3 -6
  27. package/dist/commands/test.js.map +1 -1
  28. package/dist/config.d.ts +3 -0
  29. package/dist/config.d.ts.map +1 -1
  30. package/dist/config.js +49 -52
  31. package/dist/config.js.map +1 -1
  32. package/dist/index.js +21 -23
  33. package/dist/index.js.map +1 -1
  34. package/dist/patterns.js +3 -7
  35. package/dist/patterns.js.map +1 -1
  36. package/dist/templates/post-commit.js +1 -4
  37. package/dist/templates/post-commit.js.map +1 -1
  38. package/dist/utils/git.js +7 -12
  39. package/dist/utils/git.js.map +1 -1
  40. package/package.json +2 -1
  41. package/src/animation/slotMachine.ts +1 -1
  42. package/src/api.ts +1 -1
  43. package/src/commands/auth.ts +2 -2
  44. package/src/commands/balance.ts +1 -1
  45. package/src/commands/config.ts +1 -1
  46. package/src/commands/init.ts +56 -17
  47. package/src/commands/play.ts +5 -5
  48. package/src/commands/spin.ts +2 -2
  49. package/src/commands/sync.ts +2 -2
  50. package/src/commands/test.ts +1 -1
  51. package/src/config.ts +22 -0
  52. package/src/index.ts +8 -8
  53. package/src/patterns.test.ts +1 -1
  54. package/tsconfig.json +2 -1
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { PatternResult } from '../patterns';
2
+ import { PatternResult } from '../patterns.js';
3
3
 
4
4
  const HEX_CHARS = '0123456789abcdef'.split('');
5
5
  const ANIMATION_SPEED = 50; // ms per frame
package/src/api.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { getApiUrl, getApiToken, isSyncEnabled } from './config';
1
+ import { getApiUrl, getApiToken, isSyncEnabled } from './config.js';
2
2
 
3
3
  // Fallback domains to try in order (if primary fails)
4
4
  const FALLBACK_DOMAINS = [
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk';
2
- import { createToken, logout as apiLogout, verifyToken } from '../api';
3
- import { setApiToken, clearApiToken, getApiToken, getApiUrl, setGitHubUsername } from '../config';
2
+ import { createToken, logout as apiLogout, verifyToken } from '../api.js';
3
+ import { setApiToken, clearApiToken, getApiToken, getApiUrl, setGitHubUsername } from '../config.js';
4
4
 
5
5
  export async function authLoginCommand(githubUsername: string): Promise<void> {
6
6
  try {
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getRepoStats } from '../balance';
2
+ import { getRepoStats } from '../balance.js';
3
3
 
4
4
  export function balanceCommand(): void {
5
5
  try {
@@ -5,7 +5,7 @@ import {
5
5
  isSyncEnabled,
6
6
  setSyncEnabled,
7
7
  getConfig
8
- } from '../config';
8
+ } from '../config.js';
9
9
 
10
10
  export async function configGetCommand(key: string): Promise<void> {
11
11
  try {
@@ -1,9 +1,10 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
+ import * as readline from 'readline';
3
4
  import chalk from 'chalk';
4
- import { isGitRepo } from '../utils/git';
5
- import { POST_COMMIT_HOOK } from '../templates/post-commit';
6
- import { getRepoInfo, setGitHubUsername, getGitHubUsername } from '../config';
5
+ import { isGitRepo } from '../utils/git.js';
6
+ import { POST_COMMIT_HOOK } from '../templates/post-commit.js';
7
+ import { getRepoInfo, setGitHubUsername, getGitHubUsername, setPrivateRepo } from '../config.js';
7
8
 
8
9
  async function isRepoPublic(owner: string, repo: string): Promise<boolean | null> {
9
10
  try {
@@ -27,6 +28,20 @@ async function isRepoPublic(owner: string, repo: string): Promise<boolean | null
27
28
  }
28
29
  }
29
30
 
31
+ function askQuestion(question: string): Promise<string> {
32
+ const rl = readline.createInterface({
33
+ input: process.stdin,
34
+ output: process.stdout
35
+ });
36
+
37
+ return new Promise((resolve) => {
38
+ rl.question(question, (answer) => {
39
+ rl.close();
40
+ resolve(answer.trim().toLowerCase());
41
+ });
42
+ });
43
+ }
44
+
30
45
  export async function initCommand(): Promise<void> {
31
46
  // Check if git repo
32
47
  if (!isGitRepo()) {
@@ -42,13 +57,11 @@ export async function initCommand(): Promise<void> {
42
57
  console.log();
43
58
  console.error(chalk.red('Error: No GitHub remote detected'));
44
59
  console.log();
45
- console.log(chalk.yellow('Git Slot Machine requires a public GitHub repository.'));
60
+ console.log(chalk.yellow('Git Slot Machine requires a GitHub repository.'));
46
61
  console.log();
47
62
  console.log(chalk.dim('Add a GitHub remote to this repo:'));
48
63
  console.log(chalk.cyan(' git remote add origin https://github.com/username/repo.git'));
49
64
  console.log();
50
- console.log(chalk.dim('This prevents farming points in private/local repos.'));
51
- console.log(chalk.dim('Your commits must be publicly verifiable.'));
52
65
  process.exit(1);
53
66
  }
54
67
 
@@ -62,23 +75,49 @@ export async function initCommand(): Promise<void> {
62
75
  console.log(chalk.dim('Checking repository visibility...'));
63
76
  const isPublic = await isRepoPublic(repoInfo.owner, repoInfo.name);
64
77
 
78
+ let usePrivacyMode = false;
79
+
65
80
  if (isPublic === false) {
81
+ console.log(chalk.yellow('⚠️ Private repository detected'));
66
82
  console.log();
67
- console.error(chalk.red('Error: Private repository detected'));
68
- console.log();
69
- console.log(chalk.yellow('Git Slot Machine only supports public repositories.'));
83
+ console.log(chalk.cyan('Privacy Mode Available'));
84
+ console.log(chalk.dim('You can still use Git Slot Machine with privacy mode enabled.'));
70
85
  console.log();
71
- console.log(chalk.dim('Why? Your commit hashes would be visible on the public'));
72
- console.log(chalk.dim('leaderboard, which could expose information about your'));
73
- console.log(chalk.dim('private repository.'));
86
+ console.log(chalk.yellow('What happens in privacy mode:'));
87
+ console.log(chalk.dim(' Repository name/org are NOT stored on the server'));
88
+ console.log(chalk.dim(' • Sent as "private/private" to the API'));
89
+ console.log(chalk.dim(' • Displayed as "*******/*******" on leaderboard'));
90
+ console.log(chalk.dim(' • Your GitHub username is still public'));
91
+ console.log(chalk.dim(' • All private repos share one balance'));
74
92
  console.log();
75
- console.log(chalk.dim('Please use git-slot-machine with a public repository.'));
76
- process.exit(1);
77
- }
78
93
 
79
- if (isPublic === null) {
94
+ const answer = await askQuestion(chalk.green('Enable privacy mode? (y/n): '));
95
+
96
+ if (answer === 'y' || answer === 'yes') {
97
+ usePrivacyMode = true;
98
+ setPrivateRepo(true);
99
+ console.log(chalk.green('✓ Privacy mode enabled'));
100
+ console.log(chalk.dim('Repository details will never be sent to the server.'));
101
+ } else {
102
+ console.log();
103
+ console.log(chalk.red('Cannot proceed without privacy mode for private repos.'));
104
+ console.log(chalk.dim('Please make the repository public or enable privacy mode.'));
105
+ process.exit(1);
106
+ }
107
+ } else if (isPublic === null) {
80
108
  console.log(chalk.yellow('⚠️ Could not verify repository visibility'));
81
- console.log(chalk.dim('Proceeding with installation...'));
109
+ console.log();
110
+
111
+ const answer = await askQuestion(chalk.green('Is this a private repository? (y/n): '));
112
+
113
+ if (answer === 'y' || answer === 'yes') {
114
+ usePrivacyMode = true;
115
+ setPrivateRepo(true);
116
+ console.log(chalk.green('✓ Privacy mode enabled'));
117
+ console.log(chalk.dim('Repository details will never be sent to the server.'));
118
+ } else {
119
+ console.log(chalk.dim('Proceeding with public repository mode...'));
120
+ }
82
121
  } else {
83
122
  console.log(chalk.green('✓ Public repository confirmed'));
84
123
  }
@@ -1,8 +1,8 @@
1
- import { detectPattern } from '../patterns';
2
- import { animateSlotMachine, animateSmallMode } from '../animation/slotMachine';
3
- import { getBalance, updateBalance, setBalance } from '../balance';
4
- import { sendPlayToAPI } from '../api';
5
- import { getRepoInfo, getGitHubUsername } from '../config';
1
+ import { detectPattern } from '../patterns.js';
2
+ import { animateSlotMachine, animateSmallMode } from '../animation/slotMachine.js';
3
+ import { getBalance, updateBalance, setBalance } from '../balance.js';
4
+ import { sendPlayToAPI } from '../api.js';
5
+ import { getRepoInfo, getGitHubUsername } from '../config.js';
6
6
  import chalk from 'chalk';
7
7
 
8
8
  interface PlayOptions {
@@ -1,5 +1,5 @@
1
- import { getCurrentCommitHash, getCurrentCommitFullHash } from '../utils/git';
2
- import { playCommand } from './play';
1
+ import { getCurrentCommitHash, getCurrentCommitFullHash } from '../utils/git.js';
2
+ import { playCommand } from './play.js';
3
3
 
4
4
  interface SpinOptions {
5
5
  small?: boolean;
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk';
2
- import { getBalance as getApiBalance } from '../api';
3
- import { getBalance as getLocalBalance } from '../balance';
2
+ import { getBalance as getApiBalance } from '../api.js';
3
+ import { getBalance as getLocalBalance } from '../balance.js';
4
4
 
5
5
  export async function syncCommand(): Promise<void> {
6
6
  try {
@@ -1,4 +1,4 @@
1
- import { playCommand } from './play';
1
+ import { playCommand } from './play.js';
2
2
 
3
3
  interface TestOptions {
4
4
  small?: boolean;
package/src/config.ts CHANGED
@@ -8,6 +8,7 @@ interface Config {
8
8
  apiUrl?: string;
9
9
  apiToken?: string;
10
10
  syncEnabled?: boolean;
11
+ privateRepo?: boolean;
11
12
  }
12
13
 
13
14
  // Get repo-specific config path
@@ -130,6 +131,17 @@ export function setSyncEnabled(enabled: boolean): void {
130
131
  saveGlobalConfig(config);
131
132
  }
132
133
 
134
+ export function isPrivateRepo(): boolean {
135
+ const config = getRepoConfig();
136
+ return config.privateRepo === true;
137
+ }
138
+
139
+ export function setPrivateRepo(isPrivate: boolean): void {
140
+ const config = getRepoConfig();
141
+ config.privateRepo = isPrivate;
142
+ saveRepoConfig(config);
143
+ }
144
+
133
145
  export function getRepoInfo(): { owner: string; name: string; url: string } | null {
134
146
  try {
135
147
  const remoteUrl = execSync('git config --get remote.origin.url', { encoding: 'utf-8' }).trim();
@@ -140,6 +152,16 @@ export function getRepoInfo(): { owner: string; name: string; url: string } | nu
140
152
  if (match) {
141
153
  const owner = match[1];
142
154
  const name = match[2];
155
+
156
+ // If privacy mode is enabled, return obfuscated info
157
+ if (isPrivateRepo()) {
158
+ return {
159
+ owner: 'private',
160
+ name: 'private',
161
+ url: 'private',
162
+ };
163
+ }
164
+
143
165
  return {
144
166
  owner,
145
167
  name,
package/src/index.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { Command } from 'commander';
4
- import { playCommand } from './commands/play';
5
- import { spinCommand } from './commands/spin';
6
- import { initCommand } from './commands/init';
7
- import { balanceCommand } from './commands/balance';
8
- import { testCommand } from './commands/test';
9
- import { authLoginCommand, authLogoutCommand, authStatusCommand } from './commands/auth';
10
- import { syncCommand } from './commands/sync';
11
- import { configGetCommand, configSetCommand } from './commands/config';
4
+ import { playCommand } from './commands/play.js';
5
+ import { spinCommand } from './commands/spin.js';
6
+ import { initCommand } from './commands/init.js';
7
+ import { balanceCommand } from './commands/balance.js';
8
+ import { testCommand } from './commands/test.js';
9
+ import { authLoginCommand, authLogoutCommand, authStatusCommand } from './commands/auth.js';
10
+ import { syncCommand } from './commands/sync.js';
11
+ import { configGetCommand, configSetCommand } from './commands/config.js';
12
12
 
13
13
  const program = new Command();
14
14
 
@@ -1,4 +1,4 @@
1
- import { detectPattern, PatternType } from './patterns';
1
+ import { detectPattern, PatternType } from './patterns.js';
2
2
 
3
3
  describe('Pattern Detection', () => {
4
4
  it('detects all same character', () => {
package/tsconfig.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2022",
4
- "module": "commonjs",
4
+ "module": "ES2022",
5
+ "moduleResolution": "node",
5
6
  "lib": ["ES2022"],
6
7
  "outDir": "./dist",
7
8
  "rootDir": "./src",