bgit-cli 2.0.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.
- package/.claude/settings.local.json +19 -0
- package/.env.local +2 -0
- package/CLAUDE_PLAN.md +621 -0
- package/IMPLEMENTATION_REPORT.md +1690 -0
- package/README.md +277 -0
- package/UNIVERSAL_PLAN.md +31 -0
- package/handcash.js +36 -0
- package/index.js +158 -0
- package/index.js.backup +69 -0
- package/lib/auth.js +273 -0
- package/lib/banner.js +17 -0
- package/lib/command-router.js +191 -0
- package/lib/commands.js +157 -0
- package/lib/config.js +438 -0
- package/lib/constants.js +57 -0
- package/lib/crypto.js +164 -0
- package/lib/oauth-server.js +300 -0
- package/lib/payment.js +287 -0
- package/lib/token-manager.js +179 -0
- package/package.json +45 -0
package/lib/auth.js
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bgit Authentication Manager
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates HandCash OAuth authentication flow.
|
|
5
|
+
* Manages token lifecycle and user authentication state.
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* 1. Check for existing token
|
|
9
|
+
* 2. If no token or invalid → trigger OAuth
|
|
10
|
+
* 3. Start local OAuth server
|
|
11
|
+
* 4. Open browser to HandCash
|
|
12
|
+
* 5. Capture callback with token
|
|
13
|
+
* 6. Encrypt and save token
|
|
14
|
+
* 7. Validate token
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const { HandCashConnect } = require('@handcash/handcash-connect');
|
|
18
|
+
const open = require('open');
|
|
19
|
+
const chalk = require('chalk');
|
|
20
|
+
const { loadToken, saveToken, deleteToken, hasToken } = require('./config');
|
|
21
|
+
const { isTokenValid, getProfile, getBalance, clearValidationCache } = require('./token-manager');
|
|
22
|
+
const { startOAuthServer, stopOAuthServer } = require('./oauth-server');
|
|
23
|
+
const { HANDCASH_APP_ID, HANDCASH_APP_SECRET } = require('./constants');
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Ensure user is authenticated
|
|
27
|
+
* Checks for existing valid token or triggers OAuth flow
|
|
28
|
+
*
|
|
29
|
+
* @param {boolean} silent - If true, don't show welcome messages
|
|
30
|
+
* @returns {Promise<string>} Valid auth token
|
|
31
|
+
* @throws {Error} If authentication fails
|
|
32
|
+
*/
|
|
33
|
+
async function ensureAuthenticated(silent = false) {
|
|
34
|
+
try {
|
|
35
|
+
// Check if token exists
|
|
36
|
+
if (hasToken()) {
|
|
37
|
+
const authToken = loadToken();
|
|
38
|
+
|
|
39
|
+
if (authToken) {
|
|
40
|
+
// Validate token
|
|
41
|
+
const valid = await isTokenValid(authToken);
|
|
42
|
+
|
|
43
|
+
if (valid) {
|
|
44
|
+
return authToken; // Token is valid, proceed
|
|
45
|
+
} else {
|
|
46
|
+
console.log(chalk.yellow('⚠️ Your authentication has expired.'));
|
|
47
|
+
console.log(chalk.yellow('Re-authenticating...\n'));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// No token or invalid → trigger OAuth
|
|
53
|
+
if (!silent) {
|
|
54
|
+
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
55
|
+
console.log(chalk.blue.bold('🚀 Welcome to bgit!'));
|
|
56
|
+
console.log();
|
|
57
|
+
console.log('bgit timestamps your commits on BitcoinSV using HandCash.');
|
|
58
|
+
console.log('Let\'s set up your authentication...');
|
|
59
|
+
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const authToken = await initiateOAuthFlow();
|
|
63
|
+
return authToken;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
throw new Error(`Authentication failed: ${error.message}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Initiate full OAuth authentication flow
|
|
71
|
+
*
|
|
72
|
+
* @returns {Promise<string>} Valid auth token
|
|
73
|
+
* @throws {Error} If OAuth flow fails
|
|
74
|
+
*/
|
|
75
|
+
async function initiateOAuthFlow() {
|
|
76
|
+
let server = null;
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
console.log(chalk.cyan('Opening browser for HandCash authorization...'));
|
|
80
|
+
|
|
81
|
+
// 1. Start OAuth callback server
|
|
82
|
+
const serverPromise = startOAuthServer();
|
|
83
|
+
|
|
84
|
+
// 2. Get HandCash redirect URL
|
|
85
|
+
const handCashConnect = new HandCashConnect({
|
|
86
|
+
appId: HANDCASH_APP_ID,
|
|
87
|
+
appSecret: HANDCASH_APP_SECRET
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const redirectUrl = handCashConnect.getRedirectionUrl();
|
|
91
|
+
|
|
92
|
+
// 3. Open browser
|
|
93
|
+
try {
|
|
94
|
+
await open(redirectUrl);
|
|
95
|
+
console.log(chalk.green('✓ Browser opened'));
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.log(chalk.yellow('\n⚠️ Unable to open browser automatically'));
|
|
98
|
+
console.log(chalk.yellow('Please visit this URL to authorize:\n'));
|
|
99
|
+
console.log(chalk.cyan(redirectUrl));
|
|
100
|
+
console.log();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log(chalk.cyan('Waiting for authorization... ⏳\n'));
|
|
104
|
+
|
|
105
|
+
// 4. Wait for callback
|
|
106
|
+
const result = await serverPromise;
|
|
107
|
+
const { authToken, server: srv } = result;
|
|
108
|
+
server = srv;
|
|
109
|
+
|
|
110
|
+
// 5. Validate token
|
|
111
|
+
console.log(chalk.cyan('Validating token...'));
|
|
112
|
+
const valid = await isTokenValid(authToken);
|
|
113
|
+
|
|
114
|
+
if (!valid) {
|
|
115
|
+
throw new Error('Received invalid token from HandCash');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 6. Save encrypted token
|
|
119
|
+
saveToken(authToken);
|
|
120
|
+
clearValidationCache(); // Clear cache to force fresh validation next time
|
|
121
|
+
|
|
122
|
+
// 7. Stop server
|
|
123
|
+
await stopOAuthServer(server);
|
|
124
|
+
|
|
125
|
+
console.log(chalk.green('✓ Authentication successful!'));
|
|
126
|
+
console.log(chalk.green('✓ Credentials saved securely\n'));
|
|
127
|
+
|
|
128
|
+
return authToken;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
// Clean up server on error
|
|
131
|
+
if (server) {
|
|
132
|
+
try {
|
|
133
|
+
await stopOAuthServer(server);
|
|
134
|
+
} catch (stopError) {
|
|
135
|
+
// Ignore cleanup errors
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Handle `bgit auth login` command
|
|
145
|
+
* Force re-authentication even if token exists
|
|
146
|
+
*
|
|
147
|
+
* @returns {Promise<void>}
|
|
148
|
+
*/
|
|
149
|
+
async function loginCommand() {
|
|
150
|
+
try {
|
|
151
|
+
console.log(chalk.blue.bold('\n🔐 bgit Authentication\n'));
|
|
152
|
+
|
|
153
|
+
// Delete existing token
|
|
154
|
+
if (hasToken()) {
|
|
155
|
+
deleteToken();
|
|
156
|
+
clearValidationCache();
|
|
157
|
+
console.log(chalk.yellow('Cleared existing credentials'));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Trigger OAuth
|
|
161
|
+
await initiateOAuthFlow();
|
|
162
|
+
|
|
163
|
+
console.log(chalk.green.bold('✓ Login successful!\n'));
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error(chalk.red(`\n❌ Login failed: ${error.message}\n`));
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Handle `bgit auth logout` command
|
|
172
|
+
* Delete saved token
|
|
173
|
+
*
|
|
174
|
+
* @returns {Promise<void>}
|
|
175
|
+
*/
|
|
176
|
+
async function logoutCommand() {
|
|
177
|
+
try {
|
|
178
|
+
console.log(chalk.blue.bold('\n🔓 bgit Logout\n'));
|
|
179
|
+
|
|
180
|
+
if (!hasToken()) {
|
|
181
|
+
console.log(chalk.yellow('You are not currently logged in'));
|
|
182
|
+
console.log(chalk.gray('Run: bgit auth login\n'));
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
deleteToken();
|
|
187
|
+
clearValidationCache();
|
|
188
|
+
|
|
189
|
+
console.log(chalk.green('✓ Logged out successfully'));
|
|
190
|
+
console.log(chalk.gray('Your commits are safe, but timestamping is now disabled'));
|
|
191
|
+
console.log(chalk.gray('Run: bgit auth login\n'));
|
|
192
|
+
} catch (error) {
|
|
193
|
+
console.error(chalk.red(`\n❌ Logout failed: ${error.message}\n`));
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Handle `bgit auth status` command
|
|
200
|
+
* Show authentication status and account info
|
|
201
|
+
*
|
|
202
|
+
* @returns {Promise<void>}
|
|
203
|
+
*/
|
|
204
|
+
async function statusCommand() {
|
|
205
|
+
try {
|
|
206
|
+
console.log(chalk.blue.bold('\n🔍 bgit Authentication Status\n'));
|
|
207
|
+
|
|
208
|
+
if (!hasToken()) {
|
|
209
|
+
console.log(chalk.yellow('Status: Not authenticated'));
|
|
210
|
+
console.log(chalk.gray('Run: bgit auth login\n'));
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const authToken = loadToken();
|
|
215
|
+
console.log(chalk.cyan('Validating token...'));
|
|
216
|
+
|
|
217
|
+
const valid = await isTokenValid(authToken);
|
|
218
|
+
|
|
219
|
+
if (!valid) {
|
|
220
|
+
console.log(chalk.red('Status: Invalid/expired token'));
|
|
221
|
+
console.log(chalk.gray('Run: bgit auth login\n'));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
console.log(chalk.green('✓ Status: Authenticated\n'));
|
|
226
|
+
|
|
227
|
+
// Get profile info
|
|
228
|
+
const profile = await getProfile(authToken);
|
|
229
|
+
|
|
230
|
+
if (profile) {
|
|
231
|
+
console.log(chalk.bold('Account Information:'));
|
|
232
|
+
console.log(` Handle: ${chalk.cyan('@' + profile.handle)}`);
|
|
233
|
+
console.log(` Name: ${profile.publicProfile?.displayName || 'N/A'}`);
|
|
234
|
+
|
|
235
|
+
if (profile.publicProfile?.avatarUrl) {
|
|
236
|
+
console.log(` Avatar: ${profile.publicProfile.avatarUrl}`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
console.log();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Get balance
|
|
243
|
+
const balance = await getBalance(authToken);
|
|
244
|
+
|
|
245
|
+
if (balance) {
|
|
246
|
+
console.log(chalk.bold('Wallet Balance:'));
|
|
247
|
+
|
|
248
|
+
// HandCash returns balance per currency
|
|
249
|
+
if (balance.bsv) {
|
|
250
|
+
console.log(` BSV: ${chalk.green(balance.bsv.toFixed(6))} BSV`);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (balance.usd) {
|
|
254
|
+
console.log(` USD: ${chalk.green('$' + balance.usd.toFixed(2))}`);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
console.log();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
console.log(chalk.gray('Token is valid and ready for use\n'));
|
|
261
|
+
} catch (error) {
|
|
262
|
+
console.error(chalk.red(`\n❌ Status check failed: ${error.message}\n`));
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
module.exports = {
|
|
268
|
+
ensureAuthenticated,
|
|
269
|
+
initiateOAuthFlow,
|
|
270
|
+
loginCommand,
|
|
271
|
+
logoutCommand,
|
|
272
|
+
statusCommand
|
|
273
|
+
};
|
package/lib/banner.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bgit Banner
|
|
3
|
+
* Displays the CLI ASCII art
|
|
4
|
+
*/
|
|
5
|
+
module.exports = function showBanner() {
|
|
6
|
+
console.log(`
|
|
7
|
+
\x1b[36m██████╗\x1b[0m \x1b[33m██████╗\x1b[0m \x1b[36m██╗████████╗\x1b[0m
|
|
8
|
+
\x1b[36m██╔══██╗\x1b[0m \x1b[33m██╔════╝\x1b[0m \x1b[36m██║╚══██╔══╝\x1b[0m
|
|
9
|
+
\x1b[36m██████╔╝\x1b[0m \x1b[33m██║ ███╗\x1b[0m \x1b[36m██║ ██║\x1b[0m
|
|
10
|
+
\x1b[36m██╔══██╗\x1b[0m \x1b[33m██║ ██║\x1b[0m \x1b[36m██║ ██║\x1b[0m
|
|
11
|
+
\x1b[36m██████╔╝\x1b[0m \x1b[35m██╗\x1b[0m \x1b[33m╚██████╔╝\x1b[0m \x1b[36m██║ ██║\x1b[0m
|
|
12
|
+
\x1b[36m╚═════╝\x1b[0m \x1b[35m╚═╝\x1b[0m \x1b[33m╚═════╝\x1b[0m \x1b[36m╚═╝ ╚═╝\x1b[0m
|
|
13
|
+
|
|
14
|
+
\x1b[90m> Bitcoin-Native Git Wrapper\x1b[0m
|
|
15
|
+
\x1b[90m> Pay-to-Operate • Universal History\x1b[0m
|
|
16
|
+
`);
|
|
17
|
+
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bgit Command Router
|
|
3
|
+
*
|
|
4
|
+
* Routes git commands to appropriate execution handlers:
|
|
5
|
+
* - Payment-gated commands: commit, push
|
|
6
|
+
* - Pass-through commands: all others (status, log, diff, etc.)
|
|
7
|
+
*
|
|
8
|
+
* Payment Logic:
|
|
9
|
+
* - commit: Git commit FIRST, then timestamp hash on-chain
|
|
10
|
+
* - push: Payment FIRST (gatekeeper), then git push
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const { spawn, execSync } = require('child_process');
|
|
14
|
+
const chalk = require('chalk');
|
|
15
|
+
const { executePayment, formatCommitNote, formatPushNote, softFailPayment } = require('./payment');
|
|
16
|
+
const { PAYMENT_AMOUNTS } = require('./constants');
|
|
17
|
+
const { getPaymentGatedCommands } = require('./config');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Check if command requires payment
|
|
21
|
+
* Uses configurable payment mode from config
|
|
22
|
+
*
|
|
23
|
+
* @param {string} command - Git command (e.g., "commit", "push", "status")
|
|
24
|
+
* @returns {boolean} true if command requires payment
|
|
25
|
+
*/
|
|
26
|
+
function isPaymentGated(command) {
|
|
27
|
+
const gatedCommands = getPaymentGatedCommands();
|
|
28
|
+
return gatedCommands.includes(command);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Execute git command directly (pass-through)
|
|
33
|
+
*
|
|
34
|
+
* @param {string[]} args - Git command arguments (excluding 'git')
|
|
35
|
+
* @returns {Promise<number>} Exit code
|
|
36
|
+
*/
|
|
37
|
+
function executeGitCommand(args) {
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
const gitProcess = spawn('git', args, { stdio: 'inherit' });
|
|
40
|
+
|
|
41
|
+
gitProcess.on('close', (code) => {
|
|
42
|
+
resolve(code);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
gitProcess.on('error', (error) => {
|
|
46
|
+
console.error(chalk.red(`Failed to execute git: ${error.message}`));
|
|
47
|
+
resolve(1);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Execute git commit with on-chain timestamp
|
|
54
|
+
* Flow: git commit → get hash → pay for timestamp
|
|
55
|
+
*
|
|
56
|
+
* @param {string[]} args - Git command arguments
|
|
57
|
+
* @param {string} authToken - HandCash auth token
|
|
58
|
+
* @returns {Promise<number>} Exit code
|
|
59
|
+
*/
|
|
60
|
+
async function executeCommit(args, authToken) {
|
|
61
|
+
// 1. Execute git commit first
|
|
62
|
+
const exitCode = await executeGitCommand(args);
|
|
63
|
+
|
|
64
|
+
if (exitCode !== 0) {
|
|
65
|
+
// Commit failed, don't try to pay
|
|
66
|
+
return exitCode;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 2. Get the new commit hash
|
|
70
|
+
let commitHash;
|
|
71
|
+
try {
|
|
72
|
+
commitHash = execSync('git rev-parse HEAD').toString().trim();
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error(chalk.red(`Failed to get commit hash: ${error.message}`));
|
|
75
|
+
return 0; // Commit succeeded, hash retrieval failed
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log(chalk.blue(`\n🔗 Capturing commit hash: ${chalk.bold(commitHash)}`));
|
|
79
|
+
console.log(chalk.blue('💰 Timestamping this commit on-chain...\n'));
|
|
80
|
+
|
|
81
|
+
// 3. Pay for timestamp (soft fail - don't block if payment fails)
|
|
82
|
+
await softFailPayment(
|
|
83
|
+
async () => {
|
|
84
|
+
await executePayment(
|
|
85
|
+
PAYMENT_AMOUNTS.commit,
|
|
86
|
+
formatCommitNote(commitHash),
|
|
87
|
+
authToken
|
|
88
|
+
);
|
|
89
|
+
console.log(chalk.green.bold('✓ Commit timestamped on BitcoinSV!'));
|
|
90
|
+
},
|
|
91
|
+
'Commit'
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
return 0; // Commit succeeded
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Execute git push with payment gatekeeper
|
|
99
|
+
* Flow: pay first → then git push
|
|
100
|
+
*
|
|
101
|
+
* @param {string[]} args - Git command arguments
|
|
102
|
+
* @param {string} authToken - HandCash auth token
|
|
103
|
+
* @returns {Promise<number>} Exit code
|
|
104
|
+
*/
|
|
105
|
+
async function executePush(args, authToken) {
|
|
106
|
+
// Extract remote and branch from args if available
|
|
107
|
+
let remote = 'origin';
|
|
108
|
+
let branch = 'main';
|
|
109
|
+
|
|
110
|
+
// args might be ['push', 'origin', 'main'] or just ['push']
|
|
111
|
+
if (args.length > 1) {
|
|
112
|
+
remote = args[1];
|
|
113
|
+
}
|
|
114
|
+
if (args.length > 2) {
|
|
115
|
+
branch = args[2];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(chalk.blue(`\n💰 Payment required to push to ${remote}/${branch}...`));
|
|
119
|
+
|
|
120
|
+
// 1. Pay first (gatekeeper)
|
|
121
|
+
try {
|
|
122
|
+
await executePayment(
|
|
123
|
+
PAYMENT_AMOUNTS.push,
|
|
124
|
+
formatPushNote(remote, branch),
|
|
125
|
+
authToken
|
|
126
|
+
);
|
|
127
|
+
console.log(chalk.green('✓ Payment successful! Executing push...\n'));
|
|
128
|
+
} catch (error) {
|
|
129
|
+
// Payment failed - block the push
|
|
130
|
+
console.error(chalk.red(`\n❌ Payment failed: ${error.message}`));
|
|
131
|
+
console.error(chalk.red('Push cancelled. Please resolve the issue and try again.\n'));
|
|
132
|
+
return 1;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 2. Execute git push
|
|
136
|
+
const exitCode = await executeGitCommand(args);
|
|
137
|
+
|
|
138
|
+
if (exitCode === 0) {
|
|
139
|
+
console.log(chalk.green.bold('\n✓ Push completed and payment recorded on BitcoinSV!'));
|
|
140
|
+
} else {
|
|
141
|
+
console.warn(chalk.yellow('\n⚠️ Push failed, but payment was already processed.'));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return exitCode;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Route command to appropriate handler
|
|
149
|
+
*
|
|
150
|
+
* @param {string[]} args - Git command arguments (e.g., ['commit', '-m', 'message'])
|
|
151
|
+
* @param {string} authToken - HandCash auth token (required for payment-gated commands)
|
|
152
|
+
* @returns {Promise<number>} Exit code
|
|
153
|
+
*/
|
|
154
|
+
async function routeCommand(args, authToken) {
|
|
155
|
+
if (!args || args.length === 0) {
|
|
156
|
+
console.error(chalk.red('No git command specified'));
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const command = args[0];
|
|
161
|
+
|
|
162
|
+
// Route to appropriate handler
|
|
163
|
+
if (command === 'commit') {
|
|
164
|
+
return await executeCommit(args, authToken);
|
|
165
|
+
} else if (command === 'push') {
|
|
166
|
+
return await executePush(args, authToken);
|
|
167
|
+
} else {
|
|
168
|
+
// Pass through to git
|
|
169
|
+
return await executeGitCommand(args);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Check if command needs authentication
|
|
175
|
+
* Only payment-gated commands need auth
|
|
176
|
+
*
|
|
177
|
+
* @param {string} command - Git command
|
|
178
|
+
* @returns {boolean} true if auth is required
|
|
179
|
+
*/
|
|
180
|
+
function needsAuthentication(command) {
|
|
181
|
+
return isPaymentGated(command);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
module.exports = {
|
|
185
|
+
isPaymentGated,
|
|
186
|
+
needsAuthentication,
|
|
187
|
+
routeCommand,
|
|
188
|
+
executeGitCommand,
|
|
189
|
+
executeCommit,
|
|
190
|
+
executePush
|
|
191
|
+
};
|
package/lib/commands.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
module.exports = [
|
|
2
|
+
"add",
|
|
3
|
+
"am",
|
|
4
|
+
"annotate",
|
|
5
|
+
"apply",
|
|
6
|
+
"archimport",
|
|
7
|
+
"archive",
|
|
8
|
+
"backfill",
|
|
9
|
+
"bisect",
|
|
10
|
+
"blame",
|
|
11
|
+
"branch",
|
|
12
|
+
"bugreport",
|
|
13
|
+
"bundle",
|
|
14
|
+
"cat-file",
|
|
15
|
+
"check-attr",
|
|
16
|
+
"check-ignore",
|
|
17
|
+
"check-mailmap",
|
|
18
|
+
"check-ref-format",
|
|
19
|
+
"checkout",
|
|
20
|
+
"checkout-index",
|
|
21
|
+
"cherry",
|
|
22
|
+
"cherry-pick",
|
|
23
|
+
"citool",
|
|
24
|
+
"clean",
|
|
25
|
+
"clone",
|
|
26
|
+
"column",
|
|
27
|
+
"commit",
|
|
28
|
+
"commit-graph",
|
|
29
|
+
"commit-tree",
|
|
30
|
+
"config",
|
|
31
|
+
"count-objects",
|
|
32
|
+
"credential",
|
|
33
|
+
"credential-cache",
|
|
34
|
+
"credential-store",
|
|
35
|
+
"cvsexportcommit",
|
|
36
|
+
"cvsimport",
|
|
37
|
+
"cvsserver",
|
|
38
|
+
"daemon",
|
|
39
|
+
"describe",
|
|
40
|
+
"diagnose",
|
|
41
|
+
"diff",
|
|
42
|
+
"diff-files",
|
|
43
|
+
"diff-index",
|
|
44
|
+
"diff-pairs",
|
|
45
|
+
"diff-tree",
|
|
46
|
+
"difftool",
|
|
47
|
+
"fast-export",
|
|
48
|
+
"fast-import",
|
|
49
|
+
"fetch",
|
|
50
|
+
"fetch-pack",
|
|
51
|
+
"filter-branch",
|
|
52
|
+
"fmt-merge-msg",
|
|
53
|
+
"for-each-ref",
|
|
54
|
+
"for-each-repo",
|
|
55
|
+
"format-patch",
|
|
56
|
+
"fsck",
|
|
57
|
+
"gc",
|
|
58
|
+
"get-tar-commit-id",
|
|
59
|
+
"grep",
|
|
60
|
+
"gui",
|
|
61
|
+
"hash-object",
|
|
62
|
+
"help",
|
|
63
|
+
"hook",
|
|
64
|
+
"http-backend",
|
|
65
|
+
"http-fetch",
|
|
66
|
+
"http-push",
|
|
67
|
+
"imap-send",
|
|
68
|
+
"index-pack",
|
|
69
|
+
"init",
|
|
70
|
+
"instaweb",
|
|
71
|
+
"interpret-trailers",
|
|
72
|
+
"last-modified",
|
|
73
|
+
"log",
|
|
74
|
+
"ls-files",
|
|
75
|
+
"ls-remote",
|
|
76
|
+
"ls-tree",
|
|
77
|
+
"mailinfo",
|
|
78
|
+
"mailsplit",
|
|
79
|
+
"maintenance",
|
|
80
|
+
"merge",
|
|
81
|
+
"merge-base",
|
|
82
|
+
"merge-file",
|
|
83
|
+
"merge-index",
|
|
84
|
+
"merge-one-file",
|
|
85
|
+
"merge-tree",
|
|
86
|
+
"mergetool",
|
|
87
|
+
"mktag",
|
|
88
|
+
"mktree",
|
|
89
|
+
"multi-pack-index",
|
|
90
|
+
"mv",
|
|
91
|
+
"name-rev",
|
|
92
|
+
"notes",
|
|
93
|
+
"p4",
|
|
94
|
+
"pack-objects",
|
|
95
|
+
"pack-redundant",
|
|
96
|
+
"pack-refs",
|
|
97
|
+
"patch-id",
|
|
98
|
+
"prune",
|
|
99
|
+
"prune-packed",
|
|
100
|
+
"pull",
|
|
101
|
+
"push",
|
|
102
|
+
"quiltimport",
|
|
103
|
+
"range-diff",
|
|
104
|
+
"read-tree",
|
|
105
|
+
"rebase",
|
|
106
|
+
"receive-pack",
|
|
107
|
+
"reflog",
|
|
108
|
+
"refs",
|
|
109
|
+
"remote",
|
|
110
|
+
"repack",
|
|
111
|
+
"replace",
|
|
112
|
+
"replay",
|
|
113
|
+
"repo",
|
|
114
|
+
"request-pull",
|
|
115
|
+
"rerere",
|
|
116
|
+
"reset",
|
|
117
|
+
"restore",
|
|
118
|
+
"rev-list",
|
|
119
|
+
"rev-parse",
|
|
120
|
+
"revert",
|
|
121
|
+
"rm",
|
|
122
|
+
"send-email",
|
|
123
|
+
"send-pack",
|
|
124
|
+
"sh-i18n",
|
|
125
|
+
"sh-setup",
|
|
126
|
+
"shell",
|
|
127
|
+
"shortlog",
|
|
128
|
+
"show",
|
|
129
|
+
"show-branch",
|
|
130
|
+
"show-index",
|
|
131
|
+
"show-ref",
|
|
132
|
+
"sparse-checkout",
|
|
133
|
+
"stage",
|
|
134
|
+
"stash",
|
|
135
|
+
"status",
|
|
136
|
+
"stripspace",
|
|
137
|
+
"submodule",
|
|
138
|
+
"svn",
|
|
139
|
+
"switch",
|
|
140
|
+
"symbolic-ref",
|
|
141
|
+
"tag",
|
|
142
|
+
"unpack-file",
|
|
143
|
+
"unpack-objects",
|
|
144
|
+
"update-index",
|
|
145
|
+
"update-ref",
|
|
146
|
+
"update-server-info",
|
|
147
|
+
"upload-archive",
|
|
148
|
+
"upload-pack",
|
|
149
|
+
"var",
|
|
150
|
+
"verify-commit",
|
|
151
|
+
"verify-pack",
|
|
152
|
+
"verify-tag",
|
|
153
|
+
"version",
|
|
154
|
+
"whatchanged",
|
|
155
|
+
"worktree",
|
|
156
|
+
"write-tree"
|
|
157
|
+
];
|