dorky 2.3.2 → 2.3.4

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/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.4",
4
4
  "description": "DevOps Records Keeper.",
5
5
  "bin": {
6
6
  "dorky": "bin/index.js"
package/web-app/README.md DELETED
@@ -1,70 +0,0 @@
1
- # Getting Started with Create React App
2
-
3
- This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4
-
5
- ## Available Scripts
6
-
7
- In the project directory, you can run:
8
-
9
- ### `npm start`
10
-
11
- Runs the app in the development mode.\
12
- Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13
-
14
- The page will reload when you make changes.\
15
- You may also see any lint errors in the console.
16
-
17
- ### `npm test`
18
-
19
- Launches the test runner in the interactive watch mode.\
20
- See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21
-
22
- ### `npm run build`
23
-
24
- Builds the app for production to the `build` folder.\
25
- It correctly bundles React in production mode and optimizes the build for the best performance.
26
-
27
- The build is minified and the filenames include the hashes.\
28
- Your app is ready to be deployed!
29
-
30
- See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31
-
32
- ### `npm run eject`
33
-
34
- **Note: this is a one-way operation. Once you `eject`, you can't go back!**
35
-
36
- If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37
-
38
- Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
39
-
40
- You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
41
-
42
- ## Learn More
43
-
44
- You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45
-
46
- To learn React, check out the [React documentation](https://reactjs.org/).
47
-
48
- ### Code Splitting
49
-
50
- This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51
-
52
- ### Analyzing the Bundle Size
53
-
54
- This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55
-
56
- ### Making a Progressive Web App
57
-
58
- This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59
-
60
- ### Advanced Configuration
61
-
62
- This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63
-
64
- ### Deployment
65
-
66
- This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67
-
68
- ### `npm run build` fails to minify
69
-
70
- This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)