@mcpher/gas-fakes 1.2.17 → 1.2.18
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/gas-fakes.js +17 -2
- package/package.json +1 -1
- package/setup.js +151 -45
package/gas-fakes.js
CHANGED
|
@@ -31,7 +31,7 @@ const VERSION = pjson.version;
|
|
|
31
31
|
// CONSTANTS & UTILITIES
|
|
32
32
|
// -----------------------------------------------------------------------------
|
|
33
33
|
|
|
34
|
-
const CLI_VERSION = "0.0.
|
|
34
|
+
const CLI_VERSION = "0.0.11";
|
|
35
35
|
const MCP_VERSION = "0.0.3";
|
|
36
36
|
const execAsync = promisify(exec);
|
|
37
37
|
|
|
@@ -538,7 +538,22 @@ async function main() {
|
|
|
538
538
|
|
|
539
539
|
program
|
|
540
540
|
.command("enableAPIs")
|
|
541
|
-
.description(
|
|
541
|
+
.description(
|
|
542
|
+
"Enables or disables required Google Cloud APIs for the project."
|
|
543
|
+
)
|
|
544
|
+
.option("--all", "Enable all default Google Cloud APIs.")
|
|
545
|
+
.option("--edrive", "Enable drive.googleapis.com")
|
|
546
|
+
.option("--ddrive", "Disable drive.googleapis.com")
|
|
547
|
+
.option("--esheets", "Enable sheets.googleapis.com")
|
|
548
|
+
.option("--dsheets", "Disable sheets.googleapis.com")
|
|
549
|
+
.option("--eforms", "Enable forms.googleapis.com")
|
|
550
|
+
.option("--dforms", "Disable forms.googleapis.com")
|
|
551
|
+
.option("--edocs", "Enable docs.googleapis.com")
|
|
552
|
+
.option("--ddocs", "Disable docs.googleapis.com")
|
|
553
|
+
.option("--egmail", "Enable gmail.googleapis.com")
|
|
554
|
+
.option("--dgmail", "Disable gmail.googleapis.com")
|
|
555
|
+
.option("--elogging", "Enable logging.googleapis.com")
|
|
556
|
+
.option("--dlogging", "Disable logging.googleapis.com")
|
|
542
557
|
.action(enableGoogleAPIs);
|
|
543
558
|
|
|
544
559
|
// MCP server command
|
package/package.json
CHANGED
package/setup.js
CHANGED
|
@@ -2,13 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
import prompts from "prompts";
|
|
4
4
|
import dotenv from "dotenv";
|
|
5
|
-
import fs from "fs";
|
|
5
|
+
import fs from "fs/promises";
|
|
6
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
6
7
|
import path from "path";
|
|
7
8
|
import os from "os";
|
|
8
9
|
import { execSync } from "child_process";
|
|
9
10
|
|
|
10
11
|
// --- Utility Functions ---
|
|
11
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Search .env file
|
|
15
|
+
* @param {string} dir - Start directory
|
|
16
|
+
* @returns {Promise<string[]>}
|
|
17
|
+
*/
|
|
18
|
+
async function findEnvFiles(dir) {
|
|
19
|
+
try {
|
|
20
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
21
|
+
const promises = entries.map((entry) => {
|
|
22
|
+
const fullPath = path.join(dir, entry.name);
|
|
23
|
+
if (entry.isDirectory()) {
|
|
24
|
+
if (entry.name === "node_modules") {
|
|
25
|
+
return Promise.resolve([]);
|
|
26
|
+
}
|
|
27
|
+
return findEnvFiles(fullPath);
|
|
28
|
+
} else if (entry.isFile() && entry.name === ".env") {
|
|
29
|
+
return Promise.resolve(fullPath);
|
|
30
|
+
}
|
|
31
|
+
return Promise.resolve([]);
|
|
32
|
+
});
|
|
33
|
+
const results = await Promise.all(promises);
|
|
34
|
+
return results.flat();
|
|
35
|
+
} catch (err) {
|
|
36
|
+
console.error(`No directory: ${dir}`);
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
12
41
|
/**
|
|
13
42
|
* Checks if the gcloud CLI is installed and available in the system's PATH.
|
|
14
43
|
* If not, it prints an informative message and exits the script.
|
|
@@ -51,16 +80,26 @@ function runCommand(command) {
|
|
|
51
80
|
* Handles the 'init' command to configure the .env file.
|
|
52
81
|
*/
|
|
53
82
|
export async function initializeConfiguration() {
|
|
54
|
-
|
|
55
|
-
const
|
|
83
|
+
let envPath = path.join(process.cwd(), ".env");
|
|
84
|
+
const searchPath = process.cwd(); // or process.env.HOME
|
|
85
|
+
const absoluteSearchPath = path.resolve(searchPath);
|
|
86
|
+
const foundFiles = await findEnvFiles(absoluteSearchPath);
|
|
87
|
+
if (foundFiles.length > 0) {
|
|
88
|
+
// Check .env on the top directory.
|
|
89
|
+
const results = foundFiles
|
|
90
|
+
.map((file) => file.split("/"))
|
|
91
|
+
.sort((a, b) => (a.length > b.length ? 1 : -1));
|
|
92
|
+
envPath = results[0].join("/");
|
|
93
|
+
}
|
|
94
|
+
|
|
56
95
|
let existingConfig = {};
|
|
57
96
|
|
|
58
|
-
//
|
|
59
|
-
if (
|
|
97
|
+
// Load existing values from .env file if it exists to use as defaults for prompts.
|
|
98
|
+
if (existsSync(envPath)) {
|
|
60
99
|
console.log(
|
|
61
100
|
"Found existing .env file. Loading current values as defaults."
|
|
62
101
|
);
|
|
63
|
-
existingConfig = dotenv.
|
|
102
|
+
existingConfig = dotenv.parse(readFileSync(envPath));
|
|
64
103
|
}
|
|
65
104
|
|
|
66
105
|
console.log("--------------------------------------------------");
|
|
@@ -140,6 +179,13 @@ export async function initializeConfiguration() {
|
|
|
140
179
|
|
|
141
180
|
const responses = await prompts(questions);
|
|
142
181
|
|
|
182
|
+
// If the user cancels (e.g., Ctrl+C), prompts returns undefined for the keys.
|
|
183
|
+
if (typeof responses.GCP_PROJECT_ID === "undefined") {
|
|
184
|
+
console.log("Initialization cancelled.");
|
|
185
|
+
return; // Exit the function without writing to file.
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// If Upstash is selected, ask for its credentials.
|
|
143
189
|
if (responses.STORE_TYPE === "UPSTASH") {
|
|
144
190
|
console.log(
|
|
145
191
|
"Upstash storage selected. Please provide your Redis credentials."
|
|
@@ -159,50 +205,72 @@ export async function initializeConfiguration() {
|
|
|
159
205
|
},
|
|
160
206
|
];
|
|
161
207
|
const upstashResponses = await prompts(upstashQuestions);
|
|
208
|
+
|
|
209
|
+
if (typeof upstashResponses.UPSTASH_REDIS_REST_URL === "undefined") {
|
|
210
|
+
console.log("Initialization cancelled during Upstash configuration.");
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
162
213
|
Object.assign(responses, upstashResponses);
|
|
163
214
|
}
|
|
164
215
|
|
|
165
|
-
const finalConfig = { ...existingConfig, ...responses };
|
|
166
|
-
|
|
167
216
|
console.log("--------------------------------------------------");
|
|
168
217
|
console.log(`Writing configuration to ${envPath}...`);
|
|
169
218
|
|
|
170
|
-
|
|
219
|
+
if (!existsSync(envPath)) {
|
|
220
|
+
// --- Create a new .env file from a template ---
|
|
221
|
+
let envContent = `
|
|
171
222
|
# Google Cloud Project ID (required)
|
|
172
|
-
GCP_PROJECT_ID="${
|
|
223
|
+
GCP_PROJECT_ID="${responses.GCP_PROJECT_ID || ""}"
|
|
173
224
|
|
|
174
225
|
# Path to OAuth client credentials for restricted scopes (optional)
|
|
175
|
-
CLIENT_CREDENTIAL_FILE="${
|
|
226
|
+
CLIENT_CREDENTIAL_FILE="${responses.CLIENT_CREDENTIAL_FILE || ""}"
|
|
176
227
|
|
|
177
228
|
# A test file ID for checking authentication (optional)
|
|
178
|
-
DRIVE_TEST_FILE_ID="${
|
|
229
|
+
DRIVE_TEST_FILE_ID="${responses.DRIVE_TEST_FILE_ID || ""}"
|
|
179
230
|
|
|
180
231
|
# Storage configuration for PropertiesService and CacheService ('FILE' or 'UPSTASH')
|
|
181
|
-
STORE_TYPE="${
|
|
232
|
+
STORE_TYPE="${responses.STORE_TYPE || "FILE"}"
|
|
182
233
|
|
|
183
234
|
# Logging destination for Logger.log() ('CONSOLE', 'CLOUD', 'BOTH', 'NONE')
|
|
184
|
-
LOG_DESTINATION="${
|
|
235
|
+
LOG_DESTINATION="${responses.LOG_DESTINATION || "CONSOLE"}"
|
|
185
236
|
|
|
186
237
|
# Scopes for authentication
|
|
187
238
|
# these are the scopes set by default - take some of these out if you want to minimize access
|
|
188
|
-
DEFAULT_SCOPES="${
|
|
189
|
-
EXTRA_SCOPES="${
|
|
239
|
+
DEFAULT_SCOPES="${responses.DEFAULT_SCOPES || ""}"
|
|
240
|
+
EXTRA_SCOPES="${responses.EXTRA_SCOPES || ""}"
|
|
190
241
|
`.trim();
|
|
191
242
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
finalConfig.UPSTASH_REDIS_REST_TOKEN
|
|
195
|
-
) {
|
|
196
|
-
envContent += `
|
|
243
|
+
if (responses.STORE_TYPE === "UPSTASH") {
|
|
244
|
+
envContent += `
|
|
197
245
|
|
|
198
246
|
# Upstash credentials (only used if STORE_TYPE is 'UPSTASH')
|
|
199
|
-
UPSTASH_REDIS_REST_URL="${
|
|
200
|
-
UPSTASH_REDIS_REST_TOKEN="${
|
|
247
|
+
UPSTASH_REDIS_REST_URL="${responses.UPSTASH_REDIS_REST_URL || ""}"
|
|
248
|
+
UPSTASH_REDIS_REST_TOKEN="${responses.UPSTASH_REDIS_REST_TOKEN || ""}"
|
|
201
249
|
`;
|
|
250
|
+
}
|
|
251
|
+
writeFileSync(envPath, envContent, "utf8");
|
|
252
|
+
} else {
|
|
253
|
+
// --- Update the existing .env file ---
|
|
254
|
+
let envContent = readFileSync(envPath, "utf8");
|
|
255
|
+
|
|
256
|
+
const configToUpdate = { ...responses };
|
|
257
|
+
|
|
258
|
+
for (const key of Object.keys(configToUpdate)) {
|
|
259
|
+
const value = configToUpdate[key] || "";
|
|
260
|
+
const keyRegex = new RegExp(`^\\s*${key}\\s*=.*$`, "m");
|
|
261
|
+
|
|
262
|
+
if (keyRegex.test(envContent)) {
|
|
263
|
+
envContent = envContent.replace(keyRegex, `${key}="${value}"`);
|
|
264
|
+
} else {
|
|
265
|
+
if (envContent.length > 0 && !envContent.endsWith("\n")) {
|
|
266
|
+
envContent += "\n";
|
|
267
|
+
}
|
|
268
|
+
envContent += `${key}="${value}"\n`;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
writeFileSync(envPath, envContent, "utf8");
|
|
202
272
|
}
|
|
203
273
|
|
|
204
|
-
fs.writeFileSync(envPath, envContent);
|
|
205
|
-
|
|
206
274
|
console.log("Setup complete. Your .env file has been updated.");
|
|
207
275
|
console.log("--------------------------------------------------");
|
|
208
276
|
}
|
|
@@ -217,13 +285,13 @@ export function authenticateUser() {
|
|
|
217
285
|
const rootDirectory = process.cwd();
|
|
218
286
|
const envPath = path.join(rootDirectory, ".env");
|
|
219
287
|
|
|
220
|
-
if (!
|
|
288
|
+
if (!existsSync(envPath)) {
|
|
221
289
|
console.error(`Error: .env file not found at '${envPath}'`);
|
|
222
290
|
console.error("Please run './gas-fakes.js init' first.");
|
|
223
291
|
process.exit(1);
|
|
224
292
|
}
|
|
225
293
|
|
|
226
|
-
dotenv.config({ path: envPath });
|
|
294
|
+
dotenv.config({ path: envPath, quiet: true });
|
|
227
295
|
|
|
228
296
|
const {
|
|
229
297
|
GCP_PROJECT_ID,
|
|
@@ -263,7 +331,7 @@ export function authenticateUser() {
|
|
|
263
331
|
clientPath = path.join(rootDirectory, clientPath);
|
|
264
332
|
}
|
|
265
333
|
|
|
266
|
-
if (
|
|
334
|
+
if (existsSync(clientPath)) {
|
|
267
335
|
clientFlag = `--client-id-file="${clientPath}"`;
|
|
268
336
|
} else {
|
|
269
337
|
console.error(
|
|
@@ -335,8 +403,8 @@ export function authenticateUser() {
|
|
|
335
403
|
const activeConfigPath = path.join(gcloudConfigDir, "active_config");
|
|
336
404
|
|
|
337
405
|
let currentConfig = "unknown";
|
|
338
|
-
if (
|
|
339
|
-
currentConfig =
|
|
406
|
+
if (existsSync(activeConfigPath)) {
|
|
407
|
+
currentConfig = readFileSync(activeConfigPath, "utf8").trim();
|
|
340
408
|
} else {
|
|
341
409
|
console.warn(
|
|
342
410
|
`Warning: Could not find active_config file at ${activeConfigPath}`
|
|
@@ -373,22 +441,60 @@ export function authenticateUser() {
|
|
|
373
441
|
}
|
|
374
442
|
|
|
375
443
|
/**
|
|
376
|
-
* Handles the 'enableAPIs' command to enable necessary Google Cloud services.
|
|
444
|
+
* Handles the 'enableAPIs' command to enable or disable necessary Google Cloud services based on options.
|
|
445
|
+
* @param {object} options Options object provided by commander.js.
|
|
377
446
|
*/
|
|
378
|
-
export function enableGoogleAPIs() {
|
|
379
|
-
// First, check if gcloud CLI is available.
|
|
447
|
+
export function enableGoogleAPIs(options) {
|
|
380
448
|
checkForGcloudCli();
|
|
381
449
|
|
|
382
|
-
const
|
|
383
|
-
"drive.googleapis.com",
|
|
384
|
-
"sheets.googleapis.com",
|
|
385
|
-
"forms.googleapis.com",
|
|
386
|
-
"docs.googleapis.com",
|
|
387
|
-
"gmail.googleapis.com",
|
|
388
|
-
"logging.googleapis.com",
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
450
|
+
const API_SERVICES = {
|
|
451
|
+
drive: "drive.googleapis.com",
|
|
452
|
+
sheets: "sheets.googleapis.com",
|
|
453
|
+
forms: "forms.googleapis.com",
|
|
454
|
+
docs: "docs.googleapis.com",
|
|
455
|
+
gmail: "gmail.googleapis.com",
|
|
456
|
+
logging: "logging.googleapis.com",
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
const servicesToEnable = new Set();
|
|
460
|
+
const servicesToDisable = new Set();
|
|
461
|
+
if (options.all || Object.keys(options).length === 0) {
|
|
462
|
+
Object.values(API_SERVICES).forEach((service) =>
|
|
463
|
+
servicesToEnable.add(service)
|
|
464
|
+
);
|
|
465
|
+
} else {
|
|
466
|
+
for (const key in API_SERVICES) {
|
|
467
|
+
if (options[`e${key}`]) {
|
|
468
|
+
servicesToEnable.add(API_SERVICES[key]);
|
|
469
|
+
}
|
|
470
|
+
if (options[`d${key}`]) {
|
|
471
|
+
servicesToDisable.add(API_SERVICES[key]);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
if (servicesToEnable.size > 0) {
|
|
476
|
+
const enableList = Array.from(servicesToEnable);
|
|
477
|
+
console.log(`Enabling Google Cloud services: ${enableList.join(", ")}...`);
|
|
478
|
+
runCommand(`gcloud services enable ${enableList.join(" ")}`);
|
|
479
|
+
console.log("Services enabled successfully.");
|
|
480
|
+
}
|
|
481
|
+
if (servicesToDisable.size > 0) {
|
|
482
|
+
const disableList = Array.from(servicesToDisable);
|
|
483
|
+
console.log(
|
|
484
|
+
`Disabling Google Cloud services: ${disableList.join(", ")}...`
|
|
485
|
+
);
|
|
486
|
+
runCommand(`gcloud services disable ${disableList.join(" ")}`);
|
|
487
|
+
console.log("Services disabled successfully.");
|
|
488
|
+
}
|
|
489
|
+
if (
|
|
490
|
+
servicesToEnable.size === 0 &&
|
|
491
|
+
servicesToDisable.size === 0 &&
|
|
492
|
+
Object.keys(options).length > 0 &&
|
|
493
|
+
!options.all
|
|
494
|
+
) {
|
|
495
|
+
console.log("No specific APIs were selected to enable or disable.");
|
|
496
|
+
console.log(
|
|
497
|
+
"Use '--all' to enable all default APIs, or specify flags like '--edrive' or '--ddrive'."
|
|
498
|
+
);
|
|
499
|
+
}
|
|
394
500
|
}
|