dorky 2.2.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.
- package/README.md +11 -6
- package/bin/index.js +121 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -87,10 +87,15 @@ Anyhow, we shall store it on a private storage, using **dorky**, that stores it
|
|
|
87
87
|
[*] List remote files in dorky bucket.
|
|
88
88
|
[*] Auto detect .env and .config files.
|
|
89
89
|
[*] Update node version to latest LTS.
|
|
90
|
-
[
|
|
91
|
-
[
|
|
92
|
-
[
|
|
93
|
-
[ ]
|
|
94
|
-
[ ]
|
|
95
|
-
[ ]
|
|
90
|
+
[*] Ignore dorky files in dorky itself.
|
|
91
|
+
[*] Update .gitignore automatically, to ignore .dorky/credentials.json.
|
|
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)
|
|
96
101
|
|
package/bin/index.js
CHANGED
|
@@ -86,24 +86,114 @@ function setupFilesAndFolders(metaData, credentials) {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
function updateGitIgnore() {
|
|
90
|
+
let gitignoreContent = "";
|
|
91
|
+
if (existsSync(".gitignore")) {
|
|
92
|
+
gitignoreContent = fs.readFileSync(".gitignore").toString();
|
|
93
|
+
}
|
|
94
|
+
const dorkyIgnoreEntry = ".dorky/credentials.json";
|
|
95
|
+
if (!gitignoreContent.includes(dorkyIgnoreEntry)) {
|
|
96
|
+
gitignoreContent += EOL + dorkyIgnoreEntry + EOL;
|
|
97
|
+
fs.writeFileSync(".gitignore", gitignoreContent);
|
|
98
|
+
console.log(`${chalk.bgGreen("Updated .gitignore to ignore .dorky/credentials.json.")} ${chalk.red("⚠️ This is done to protect your credentials.")}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function authorizeGoogleDriveClient(forceReauth = false) {
|
|
90
103
|
async function loadSavedCredentialsIfExist() {
|
|
91
104
|
try {
|
|
92
105
|
const content = await fs.readFileSync(TOKEN_PATH);
|
|
93
|
-
const
|
|
94
|
-
|
|
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;
|
|
95
127
|
} catch (err) {
|
|
96
128
|
return null;
|
|
97
129
|
}
|
|
98
130
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
+
}
|
|
102
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
|
|
103
183
|
client = await authenticate({
|
|
104
184
|
scopes: SCOPES,
|
|
105
185
|
keyfilePath: CREDENTIALS_PATH,
|
|
106
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
|
+
|
|
107
197
|
return client;
|
|
108
198
|
}
|
|
109
199
|
|
|
@@ -116,7 +206,7 @@ async function init(storage) {
|
|
|
116
206
|
setupFilesAndFolders(metaData, credentials);
|
|
117
207
|
break;
|
|
118
208
|
case "google-drive":
|
|
119
|
-
const client = await authorizeGoogleDriveClient();
|
|
209
|
+
const client = await authorizeGoogleDriveClient(true); // Force reauth on init
|
|
120
210
|
credentials = { storage: "google-drive", ...client.credentials };
|
|
121
211
|
setupFilesAndFolders(metaData, credentials);
|
|
122
212
|
break;
|
|
@@ -124,6 +214,7 @@ async function init(storage) {
|
|
|
124
214
|
console.log("Please provide a valid storage option <aws|google-drive>");
|
|
125
215
|
break;
|
|
126
216
|
}
|
|
217
|
+
updateGitIgnore();
|
|
127
218
|
}
|
|
128
219
|
|
|
129
220
|
async function list(type) {
|
|
@@ -149,6 +240,9 @@ async function list(type) {
|
|
|
149
240
|
for (let i = 0; i < exclusions.length; i++) {
|
|
150
241
|
if (file.includes(exclusions[i])) return false;
|
|
151
242
|
}
|
|
243
|
+
if (file.includes(".dorky/")) return false;
|
|
244
|
+
if (file.endsWith(".dorky") && fs.lstatSync(file).isDirectory()) return false;
|
|
245
|
+
if (file.endsWith(".dorkyignore")) return false;
|
|
152
246
|
return true;
|
|
153
247
|
});
|
|
154
248
|
filteredFiles.forEach((file) => {
|
|
@@ -225,7 +319,7 @@ async function checkCredentials() {
|
|
|
225
319
|
} else {
|
|
226
320
|
try {
|
|
227
321
|
let credentials;
|
|
228
|
-
const client = await authorizeGoogleDriveClient();
|
|
322
|
+
const client = await authorizeGoogleDriveClient(true); // Force reauth when creating new credentials
|
|
229
323
|
credentials = { storage: "google-drive", ...client.credentials };
|
|
230
324
|
fs.writeFileSync(".dorky/credentials.json", JSON.stringify(credentials, null, 2));
|
|
231
325
|
console.log(chalk.green("Credentials saved in .dorky/credentials.json"));
|
|
@@ -281,7 +375,7 @@ async function push() {
|
|
|
281
375
|
}
|
|
282
376
|
metaData["uploaded-files"] = metaData["stage-1-files"];
|
|
283
377
|
fs.writeFileSync(".dorky/metadata.json", JSON.stringify(metaData, null, 2));
|
|
284
|
-
console.log(chalk.green("Pushed files to storage"));
|
|
378
|
+
console.log(chalk.green("Pushed the following files to storage:"));
|
|
285
379
|
}
|
|
286
380
|
|
|
287
381
|
function pushToS3(files, credentials) {
|
|
@@ -336,7 +430,15 @@ async function pushToGoogleDrive(files) {
|
|
|
336
430
|
return parentId;
|
|
337
431
|
}
|
|
338
432
|
console.log("Uploading to google drive");
|
|
339
|
-
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
|
+
|
|
340
442
|
const drive = google.drive({ version: 'v3', auth: client });
|
|
341
443
|
for (const file of files) {
|
|
342
444
|
const rootFolder = path.basename(process.cwd());
|
|
@@ -419,7 +521,15 @@ async function pullFromGoogleDrive(files) {
|
|
|
419
521
|
return { name: file, ...files[file] };
|
|
420
522
|
});
|
|
421
523
|
|
|
422
|
-
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
|
+
|
|
423
533
|
const drive = google.drive({ version: "v3", auth: client });
|
|
424
534
|
try {
|
|
425
535
|
files.map(async (file) => {
|