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.
@@ -0,0 +1,179 @@
1
+ /**
2
+ * bgit Token Manager
3
+ *
4
+ * Manages HandCash auth token lifecycle including validation and caching.
5
+ * Validates tokens against HandCash API with 1-hour cache to minimize API calls.
6
+ *
7
+ * Features:
8
+ * - Token validation via HandCash API
9
+ * - 1-hour validation cache (reduces API calls)
10
+ * - Automatic re-auth trigger on invalid/expired tokens
11
+ */
12
+
13
+ const { HandCashConnect } = require('@handcash/handcash-connect');
14
+ const { HANDCASH_APP_ID, HANDCASH_APP_SECRET, TOKEN_VALIDATION_CACHE_TTL_MS } = require('./constants');
15
+
16
+ // Validation cache: { token: { valid: boolean, timestamp: number } }
17
+ const validationCache = new Map();
18
+
19
+ /**
20
+ * Check if cached validation is still valid (within TTL)
21
+ *
22
+ * @param {string} authToken - Token to check cache for
23
+ * @returns {boolean|null} true if valid, false if invalid, null if no cache
24
+ */
25
+ function getCachedValidation(authToken) {
26
+ if (!validationCache.has(authToken)) {
27
+ return null;
28
+ }
29
+
30
+ const cached = validationCache.get(authToken);
31
+ const age = Date.now() - cached.timestamp;
32
+
33
+ if (age > TOKEN_VALIDATION_CACHE_TTL_MS) {
34
+ // Cache expired
35
+ validationCache.delete(authToken);
36
+ return null;
37
+ }
38
+
39
+ return cached.valid;
40
+ }
41
+
42
+ /**
43
+ * Cache token validation result
44
+ *
45
+ * @param {string} authToken - Token to cache
46
+ * @param {boolean} valid - Whether token is valid
47
+ */
48
+ function setCachedValidation(authToken, valid) {
49
+ validationCache.set(authToken, {
50
+ valid,
51
+ timestamp: Date.now()
52
+ });
53
+ }
54
+
55
+ /**
56
+ * Clear validation cache
57
+ * Useful after re-authentication
58
+ */
59
+ function clearValidationCache() {
60
+ validationCache.clear();
61
+ }
62
+
63
+ /**
64
+ * Validate auth token against HandCash API
65
+ * Uses cached result if available (1-hour TTL)
66
+ *
67
+ * @param {string} authToken - HandCash auth token to validate
68
+ * @returns {Promise<boolean>} true if valid, false otherwise
69
+ */
70
+ async function isTokenValid(authToken) {
71
+ if (!authToken || typeof authToken !== 'string') {
72
+ return false;
73
+ }
74
+
75
+ // Check cache first
76
+ const cached = getCachedValidation(authToken);
77
+ if (cached !== null) {
78
+ return cached;
79
+ }
80
+
81
+ try {
82
+ const handCashConnect = new HandCashConnect({
83
+ appId: HANDCASH_APP_ID,
84
+ appSecret: HANDCASH_APP_SECRET
85
+ });
86
+
87
+ const account = handCashConnect.getAccountFromAuthToken(authToken);
88
+
89
+ // Try to get profile - this validates the token
90
+ const profile = await account.profile.getCurrentProfile();
91
+
92
+ if (profile && profile.handle) {
93
+ // Token is valid
94
+ setCachedValidation(authToken, true);
95
+ return true;
96
+ } else {
97
+ // Unexpected response
98
+ setCachedValidation(authToken, false);
99
+ return false;
100
+ }
101
+ } catch (error) {
102
+ // Token is invalid or API error
103
+ console.error(`Token validation failed: ${error.message}`);
104
+ setCachedValidation(authToken, false);
105
+ return false;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Get HandCash account profile
111
+ * Used to display auth status
112
+ *
113
+ * @param {string} authToken - HandCash auth token
114
+ * @returns {Promise<Object|null>} Profile object or null if error
115
+ */
116
+ async function getProfile(authToken) {
117
+ try {
118
+ const handCashConnect = new HandCashConnect({
119
+ appId: HANDCASH_APP_ID,
120
+ appSecret: HANDCASH_APP_SECRET
121
+ });
122
+
123
+ const account = handCashConnect.getAccountFromAuthToken(authToken);
124
+ const profile = await account.profile.getCurrentProfile();
125
+
126
+ return profile;
127
+ } catch (error) {
128
+ console.error(`Failed to get profile: ${error.message}`);
129
+ return null;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Get HandCash account balance
135
+ * Used to check if user has sufficient funds
136
+ *
137
+ * @param {string} authToken - HandCash auth token
138
+ * @returns {Promise<Object|null>} Balance object or null if error
139
+ */
140
+ async function getBalance(authToken) {
141
+ try {
142
+ const handCashConnect = new HandCashConnect({
143
+ appId: HANDCASH_APP_ID,
144
+ appSecret: HANDCASH_APP_SECRET
145
+ });
146
+
147
+ const account = handCashConnect.getAccountFromAuthToken(authToken);
148
+ const spendableBalance = await account.wallet.getSpendableBalance();
149
+
150
+ return spendableBalance;
151
+ } catch (error) {
152
+ console.error(`Failed to get balance: ${error.message}`);
153
+ return null;
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Check if token should be refreshed
159
+ * HandCash tokens don't expire, but this provides a hook for future refresh logic
160
+ *
161
+ * @param {string} authToken - HandCash auth token
162
+ * @returns {Promise<boolean>} true if token should be refreshed
163
+ */
164
+ async function shouldRefresh(authToken) {
165
+ // HandCash Connect SDK doesn't currently support token refresh
166
+ // Tokens are long-lived and don't expire
167
+ // This function is a placeholder for future enhancement
168
+ return false;
169
+ }
170
+
171
+ module.exports = {
172
+ isTokenValid,
173
+ getProfile,
174
+ getBalance,
175
+ shouldRefresh,
176
+ clearValidationCache,
177
+ getCachedValidation,
178
+ setCachedValidation
179
+ };
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "bgit-cli",
3
+ "version": "2.0.0",
4
+ "description": "Bitcoin-enabled Git wrapper with HandCash OAuth - Timestamp your commits on BitcoinSV",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "bgit": "./index.js"
8
+ },
9
+ "preferGlobal": true,
10
+ "engines": {
11
+ "node": ">=16.0.0"
12
+ },
13
+ "scripts": {
14
+ "test": "echo \"Error: no test specified\" && exit 1",
15
+ "start": "node index.js"
16
+ },
17
+ "keywords": [
18
+ "bitcoin",
19
+ "git",
20
+ "bsv",
21
+ "bitcoinsv",
22
+ "handcash",
23
+ "blockchain",
24
+ "timestamp",
25
+ "commit",
26
+ "version-control"
27
+ ],
28
+ "author": "b0ase",
29
+ "license": "ISC",
30
+ "type": "commonjs",
31
+ "dependencies": {
32
+ "@handcash/handcash-connect": "^0.8.11",
33
+ "chalk": "^4.1.2",
34
+ "express": "^4.18.2",
35
+ "open": "^8.4.2"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/yourusername/bgit.git"
40
+ },
41
+ "bugs": {
42
+ "url": "https://github.com/yourusername/bgit/issues"
43
+ },
44
+ "homepage": "https://github.com/yourusername/bgit#readme"
45
+ }