dorky 2.3.2 → 2.3.3

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 (3) hide show
  1. package/README.md +9 -6
  2. package/bin/index.js +104 -11
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -89,10 +89,13 @@ Anyhow, we shall store it on a private storage, using **dorky**, that stores it
89
89
  [*] Update node version to latest LTS.
90
90
  [*] Ignore dorky files in dorky itself.
91
91
  [*] Update .gitignore automatically, to ignore .dorky/credentials.json.
92
- [ ] Handle reauthentication loop for google-drive.
93
- [ ] Extension for VS Code to list and highlight them like git.
94
- [ ] Unintialize dorky setup.
95
- [ ] MCP server.
96
- [ ] Encryption of files.
97
- [ ] Add stages for variables.
92
+ [*] Handle reauthentication loop for google-drive. (Bug fix release)
93
+ [ ] Fix error while adding a file that does not exist, it does give an error but still prints that an entry is added.
94
+ [ ] Fix issue when the file is added again with the same contents, it still adds it, not checks it with the hash.
95
+ [ ] Handle invalid access token for google-drive.
96
+ [ ] Extension for VS Code to list and highlight them like git. (Major release)
97
+ [ ] Unintialize dorky setup. (Bug fix release)
98
+ [ ] MCP server. (Minor release)
99
+ [ ] Encryption of files. (Minor release)
100
+ [ ] Add stages for variables. (Major release)
98
101
 
package/bin/index.js CHANGED
@@ -99,24 +99,101 @@ function updateGitIgnore() {
99
99
  }
100
100
  }
101
101
 
102
- async function authorizeGoogleDriveClient() {
102
+ async function authorizeGoogleDriveClient(forceReauth = false) {
103
103
  async function loadSavedCredentialsIfExist() {
104
104
  try {
105
105
  const content = await fs.readFileSync(TOKEN_PATH);
106
- const credentials = JSON.parse(content);
107
- return google.auth.fromJSON(credentials);
106
+ const savedCredentials = JSON.parse(content);
107
+
108
+ // Check if this is OAuth2 credentials (has access_token, refresh_token, etc.)
109
+ if (!savedCredentials.access_token && !savedCredentials.refresh_token) {
110
+ return null;
111
+ }
112
+
113
+ // Load the client secrets to create an OAuth2 client
114
+ const keys = JSON.parse(fs.readFileSync(CREDENTIALS_PATH));
115
+ const key = keys.installed || keys.web;
116
+ const oAuth2Client = new google.auth.OAuth2(
117
+ key.client_id,
118
+ key.client_secret,
119
+ key.redirect_uris[0]
120
+ );
121
+
122
+ // Remove the 'storage' field and set credentials
123
+ const { storage, ...authCredentials } = savedCredentials;
124
+ oAuth2Client.setCredentials(authCredentials);
125
+
126
+ return oAuth2Client;
108
127
  } catch (err) {
109
128
  return null;
110
129
  }
111
130
  }
112
- let client = await loadSavedCredentialsIfExist();
113
- if (client) {
114
- return client;
131
+
132
+ async function isTokenExpired(credentials) {
133
+ if (!credentials.expiry_date) {
134
+ return true;
135
+ }
136
+ // Both Date.now() and expiry_date are in milliseconds since Unix epoch (UTC)
137
+ // Check if token expires in less than 5 minutes (300000 ms)
138
+ const expiryBuffer = 300000;
139
+ const currentTimeUTC = Date.now();
140
+ const expiryTimeUTC = credentials.expiry_date;
141
+
142
+ // Token is expired if current time is past (expiry time - buffer)
143
+ return currentTimeUTC >= (expiryTimeUTC - expiryBuffer);
144
+ }
145
+
146
+ async function refreshAndSaveToken(client) {
147
+ try {
148
+ await client.getAccessToken();
149
+ const newCredentials = client.credentials;
150
+ const credentialsToSave = {
151
+ storage: "google-drive",
152
+ ...newCredentials
153
+ };
154
+ fs.writeFileSync(TOKEN_PATH, JSON.stringify(credentialsToSave, null, 2));
155
+ return client;
156
+ } catch (err) {
157
+ return null;
158
+ }
115
159
  }
160
+
161
+ // If not forcing reauth, try to load existing credentials
162
+ if (!forceReauth) {
163
+ let client = await loadSavedCredentialsIfExist();
164
+ if (client) {
165
+ const credentials = JSON.parse(fs.readFileSync(TOKEN_PATH));
166
+
167
+ // Ensure we're using the client's credentials which may have been updated
168
+ const clientCredentials = client.credentials || credentials;
169
+
170
+ if (await isTokenExpired(clientCredentials)) {
171
+ client = await refreshAndSaveToken(client);
172
+ if (client) {
173
+ return client;
174
+ }
175
+ // If refresh failed, fall through to full reauth
176
+ } else {
177
+ return client;
178
+ }
179
+ }
180
+ }
181
+
182
+ // Perform full authentication
116
183
  client = await authenticate({
117
184
  scopes: SCOPES,
118
185
  keyfilePath: CREDENTIALS_PATH,
119
186
  });
187
+
188
+ // Save credentials after full authentication
189
+ if (client && client.credentials) {
190
+ const credentialsToSave = {
191
+ storage: "google-drive",
192
+ ...client.credentials
193
+ };
194
+ fs.writeFileSync(TOKEN_PATH, JSON.stringify(credentialsToSave, null, 2));
195
+ }
196
+
120
197
  return client;
121
198
  }
122
199
 
@@ -129,7 +206,7 @@ async function init(storage) {
129
206
  setupFilesAndFolders(metaData, credentials);
130
207
  break;
131
208
  case "google-drive":
132
- const client = await authorizeGoogleDriveClient();
209
+ const client = await authorizeGoogleDriveClient(true); // Force reauth on init
133
210
  credentials = { storage: "google-drive", ...client.credentials };
134
211
  setupFilesAndFolders(metaData, credentials);
135
212
  break;
@@ -242,7 +319,7 @@ async function checkCredentials() {
242
319
  } else {
243
320
  try {
244
321
  let credentials;
245
- const client = await authorizeGoogleDriveClient();
322
+ const client = await authorizeGoogleDriveClient(true); // Force reauth when creating new credentials
246
323
  credentials = { storage: "google-drive", ...client.credentials };
247
324
  fs.writeFileSync(".dorky/credentials.json", JSON.stringify(credentials, null, 2));
248
325
  console.log(chalk.green("Credentials saved in .dorky/credentials.json"));
@@ -298,7 +375,7 @@ async function push() {
298
375
  }
299
376
  metaData["uploaded-files"] = metaData["stage-1-files"];
300
377
  fs.writeFileSync(".dorky/metadata.json", JSON.stringify(metaData, null, 2));
301
- console.log(chalk.green("Pushed files to storage"));
378
+ console.log(chalk.green("Pushed the following files to storage:"));
302
379
  }
303
380
 
304
381
  function pushToS3(files, credentials) {
@@ -353,7 +430,15 @@ async function pushToGoogleDrive(files) {
353
430
  return parentId;
354
431
  }
355
432
  console.log("Uploading to google drive");
356
- const client = await authorizeGoogleDriveClient();
433
+ const client = await authorizeGoogleDriveClient(false); // Use existing token if valid
434
+
435
+ // Update credentials file with potentially refreshed token
436
+ const credentialsToSave = {
437
+ storage: "google-drive",
438
+ ...client.credentials
439
+ };
440
+ fs.writeFileSync(TOKEN_PATH, JSON.stringify(credentialsToSave, null, 2));
441
+
357
442
  const drive = google.drive({ version: 'v3', auth: client });
358
443
  for (const file of files) {
359
444
  const rootFolder = path.basename(process.cwd());
@@ -436,7 +521,15 @@ async function pullFromGoogleDrive(files) {
436
521
  return { name: file, ...files[file] };
437
522
  });
438
523
 
439
- const client = await authorizeGoogleDriveClient();
524
+ const client = await authorizeGoogleDriveClient(false); // Use existing token if valid
525
+
526
+ // Update credentials file with potentially refreshed token
527
+ const credentialsToSave = {
528
+ storage: "google-drive",
529
+ ...client.credentials
530
+ };
531
+ fs.writeFileSync(TOKEN_PATH, JSON.stringify(credentialsToSave, null, 2));
532
+
440
533
  const drive = google.drive({ version: "v3", auth: client });
441
534
  try {
442
535
  files.map(async (file) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dorky",
3
- "version": "2.3.2",
3
+ "version": "2.3.3",
4
4
  "description": "DevOps Records Keeper.",
5
5
  "bin": {
6
6
  "dorky": "bin/index.js"