@mcpher/gas-fakes 2.2.5 → 2.2.6
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/package.json +6 -2
- package/src/support/msgraph/msauth.js +63 -9
- package/exgcp.sh +0 -54
- package/introvideo.png +0 -0
- package/logo.png +0 -0
- package/plain-logo.png +0 -0
- package/testlib.sh +0 -2
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"dotenv": "^17.3.1",
|
|
16
16
|
"fast-xml-parser": "^5.4.2",
|
|
17
17
|
"get-stream": "^9.0.1",
|
|
18
|
+
"google-auth-library": "^10.6.2",
|
|
18
19
|
"googleapis": "^171.4.0",
|
|
19
20
|
"got": "^14.6.6",
|
|
20
21
|
"into-stream": "^9.1.0",
|
|
@@ -26,6 +27,9 @@
|
|
|
26
27
|
"unzipper": "^0.12.3",
|
|
27
28
|
"zod": "^4.3.6"
|
|
28
29
|
},
|
|
30
|
+
"overrides": {
|
|
31
|
+
"glob": "^13.0.6"
|
|
32
|
+
},
|
|
29
33
|
"type": "module",
|
|
30
34
|
"scripts": {
|
|
31
35
|
"pub": "npm publish --access public",
|
|
@@ -35,7 +39,7 @@
|
|
|
35
39
|
},
|
|
36
40
|
"name": "@mcpher/gas-fakes",
|
|
37
41
|
"author": "bruce mcpherson",
|
|
38
|
-
"version": "2.2.
|
|
42
|
+
"version": "2.2.6",
|
|
39
43
|
"license": "MIT",
|
|
40
44
|
"main": "main.js",
|
|
41
45
|
"description": "An implementation of the Google Workspace Apps Script runtime: Run native App Script Code on Node and Cloud Run",
|
|
@@ -44,4 +48,4 @@
|
|
|
44
48
|
"bin": {
|
|
45
49
|
"gas-fakes": "gas-fakes.js"
|
|
46
50
|
}
|
|
47
|
-
}
|
|
51
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
InteractiveBrowserCredential,
|
|
3
|
-
ClientSecretCredential
|
|
3
|
+
ClientSecretCredential,
|
|
4
|
+
useIdentityPlugin
|
|
4
5
|
} from "@azure/identity";
|
|
6
|
+
|
|
5
7
|
import { execSync } from 'node:child_process';
|
|
6
8
|
import { readFile, writeFile } from 'fs/promises';
|
|
7
9
|
import { existsSync } from 'fs';
|
|
@@ -40,20 +42,66 @@ function decodeJWT(token) {
|
|
|
40
42
|
return JSON.parse(Buffer.from(encodedPayload, 'base64url').toString('utf-8'));
|
|
41
43
|
}
|
|
42
44
|
|
|
45
|
+
const customCachePlugin = (options) => {
|
|
46
|
+
return {
|
|
47
|
+
beforeCacheAccess: async (cacheContext) => {
|
|
48
|
+
if (existsSync(TOKEN_CACHE_FILE)) {
|
|
49
|
+
try {
|
|
50
|
+
const data = await readFile(TOKEN_CACHE_FILE, 'utf-8');
|
|
51
|
+
let cache;
|
|
52
|
+
if (data.trim().startsWith('{')) {
|
|
53
|
+
cache = JSON.parse(data);
|
|
54
|
+
} else {
|
|
55
|
+
cache = decodeJWT(data.trim());
|
|
56
|
+
}
|
|
57
|
+
if (cache && cache.msalCache) {
|
|
58
|
+
cacheContext.tokenCache.deserialize(cache.msalCache);
|
|
59
|
+
}
|
|
60
|
+
} catch (e) {
|
|
61
|
+
console.warn(`...failed to load MS Graph token cache: ${e.message}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
afterCacheAccess: async (cacheContext) => {
|
|
66
|
+
if (cacheContext.cacheHasChanged) {
|
|
67
|
+
try {
|
|
68
|
+
const msalCache = cacheContext.tokenCache.serialize();
|
|
69
|
+
const cacheData = {
|
|
70
|
+
msalCache,
|
|
71
|
+
token: 'managed-by-msal',
|
|
72
|
+
expiresOn: new Date(Date.now() + 86400000 * 30).getTime() // Keep valid for 30 days
|
|
73
|
+
};
|
|
74
|
+
const jwtString = encodeJWT(cacheData);
|
|
75
|
+
await writeFile(TOKEN_CACHE_FILE, jwtString);
|
|
76
|
+
try {
|
|
77
|
+
chmodSync(TOKEN_CACHE_FILE, 0o600);
|
|
78
|
+
} catch (e) {}
|
|
79
|
+
} catch (e) {
|
|
80
|
+
console.warn(`...failed to save MS Graph token cache: ${e.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
useIdentityPlugin((context) => {
|
|
88
|
+
if (context.cachePluginControl) {
|
|
89
|
+
context.cachePluginControl.setPersistence(customCachePlugin);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
43
93
|
async function loadTokenCache() {
|
|
44
94
|
if (existsSync(TOKEN_CACHE_FILE)) {
|
|
45
95
|
try {
|
|
46
96
|
const data = await readFile(TOKEN_CACHE_FILE, 'utf-8');
|
|
47
97
|
|
|
48
98
|
let cache;
|
|
49
|
-
// Handle legacy plain-text JSON format gracefully
|
|
50
99
|
if (data.trim().startsWith('{')) {
|
|
51
100
|
cache = JSON.parse(data);
|
|
52
101
|
} else {
|
|
53
102
|
cache = decodeJWT(data.trim());
|
|
54
103
|
}
|
|
55
104
|
|
|
56
|
-
// Check if expired (buffer of 5 mins)
|
|
57
105
|
if (cache && cache.expiresOn && new Date(cache.expiresOn).getTime() > Date.now() + 300000) {
|
|
58
106
|
return cache.token;
|
|
59
107
|
}
|
|
@@ -70,10 +118,8 @@ async function saveTokenCache(token, expiresOn) {
|
|
|
70
118
|
const jwtString = encodeJWT(cacheData);
|
|
71
119
|
await writeFile(TOKEN_CACHE_FILE, jwtString);
|
|
72
120
|
try {
|
|
73
|
-
chmodSync(TOKEN_CACHE_FILE, 0o600);
|
|
74
|
-
} catch (e) {
|
|
75
|
-
// Ignore if chmod fails (e.g. on non-posix)
|
|
76
|
-
}
|
|
121
|
+
chmodSync(TOKEN_CACHE_FILE, 0o600);
|
|
122
|
+
} catch (e) {}
|
|
77
123
|
} catch (e) {
|
|
78
124
|
console.warn(`...failed to save MS Graph token cache: ${e.message}`);
|
|
79
125
|
}
|
|
@@ -230,7 +276,11 @@ export async function getMsGraphToken(scopes = ['User.Read']) {
|
|
|
230
276
|
const credentialSilent = new InteractiveBrowserCredential({
|
|
231
277
|
tenantId: (envTenant && envTenant !== 'common') ? envTenant : 'consumers',
|
|
232
278
|
clientId,
|
|
233
|
-
prompt: promptBehavior
|
|
279
|
+
prompt: promptBehavior,
|
|
280
|
+
tokenCachePersistenceOptions: {
|
|
281
|
+
enabled: true,
|
|
282
|
+
name: 'gas-fakes-msgraph-cache'
|
|
283
|
+
}
|
|
234
284
|
});
|
|
235
285
|
|
|
236
286
|
try {
|
|
@@ -244,7 +294,11 @@ export async function getMsGraphToken(scopes = ['User.Read']) {
|
|
|
244
294
|
const credentialInteractive = new InteractiveBrowserCredential({
|
|
245
295
|
tenantId: (envTenant && envTenant !== 'common') ? envTenant : 'consumers',
|
|
246
296
|
clientId,
|
|
247
|
-
prompt: 'select_account consent'
|
|
297
|
+
prompt: 'select_account consent',
|
|
298
|
+
tokenCachePersistenceOptions: {
|
|
299
|
+
enabled: true,
|
|
300
|
+
name: 'gas-fakes-msgraph-cache'
|
|
301
|
+
}
|
|
248
302
|
});
|
|
249
303
|
const tokenResponse = await credentialInteractive.getToken(msScopes);
|
|
250
304
|
syncLog('...retrieved MS Graph token via interactive login');
|
package/exgcp.sh
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# This script reads the GCP_PROJECT_ID from a .env file
|
|
4
|
-
# and exports it as GOOGLE_CLOUD_PROJECT for the current shell session.
|
|
5
|
-
#
|
|
6
|
-
# Usage: source . ./exgcp.sh
|
|
7
|
-
|
|
8
|
-
# Define the path to your .env file relative to the script's location
|
|
9
|
-
ENV_FILE="$(dirname "$0")/.env"
|
|
10
|
-
|
|
11
|
-
# Check if the .env file exists
|
|
12
|
-
|
|
13
|
-
if [ ! -f "$ENV_FILE" ]; then
|
|
14
|
-
echo "Error: .env file not found at path: $ENV_FILE"
|
|
15
|
-
# Use 'return' instead of 'exit' so it doesn't close the user's terminal when sourced
|
|
16
|
-
return 1
|
|
17
|
-
fi
|
|
18
|
-
|
|
19
|
-
# Read the GCP_PROJECT_ID, remove quotes, and handle potential carriage returns
|
|
20
|
-
GOOGLE_CLOUD_PROJECT_VALUE=$(grep -E '^GOOGLE_CLOUD_PROJECT=' "$ENV_FILE" | cut -d '=' -f2 | tr -d '"\r')
|
|
21
|
-
GEMINI_API_KEY_VALUE=$(grep -E '^GEMINI_API_KEY=' "$ENV_FILE" | cut -d '=' -f2 | tr -d '"\r')
|
|
22
|
-
GEMINI_MODEL_VALUE=$(grep -E '^GEMINI_MODEL=' "$ENV_FILE" | cut -d '=' -f2 | tr -d '"\r')
|
|
23
|
-
OMDB_API_KEY_VALUE=$(grep -E '^OMDB_API_KEY=' "$ENV_FILE" | cut -d '=' -f2 | tr -d '"\r')
|
|
24
|
-
# Check if a value was extracted
|
|
25
|
-
if [ -z "$GOOGLE_CLOUD_PROJECT_VALUE" ]; then
|
|
26
|
-
echo "Error: GOOGLE_CLOUD_PROJECT not found or is empty in $ENV_FILE."
|
|
27
|
-
return 1
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
if [ -z "GEMINI_API_KEY_VALUE" ]; then
|
|
31
|
-
echo "GEMINI_API_KEY not found or is empty in $ENV_FILE."
|
|
32
|
-
else
|
|
33
|
-
echo "exported: GEMINI_API_KEY"
|
|
34
|
-
export GEMINI_API_KEY="$GEMINI_API_KEY_VALUE"
|
|
35
|
-
fi
|
|
36
|
-
|
|
37
|
-
if [ -z "OMDB_API_KEY_VALUE" ]; then
|
|
38
|
-
echo "OMDB_API_KEY not found or is empty in $ENV_FILE."
|
|
39
|
-
else
|
|
40
|
-
echo "exported: OMDB_API_KEY"
|
|
41
|
-
export OMDB_API_KEY="$OMDB_API_KEY_VALUE"
|
|
42
|
-
fi
|
|
43
|
-
|
|
44
|
-
if [ -z "GEMINI_MODEL_VALUE" ]; then
|
|
45
|
-
echo "GEMINI_MODEL not found or is empty in $ENV_FILE."
|
|
46
|
-
else
|
|
47
|
-
echo "exported: GEMINI_MODEL=$GEMINI_MODEL_VALUE"
|
|
48
|
-
export GEMINI_MODEL="$GEMINI_MODEL_VALUE"
|
|
49
|
-
fi
|
|
50
|
-
|
|
51
|
-
# Export the variable for the current session
|
|
52
|
-
export GOOGLE_CLOUD_PROJECT="$GOOGLE_CLOUD_PROJECT_VALUE"
|
|
53
|
-
|
|
54
|
-
echo "exported: GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT"
|
package/introvideo.png
DELETED
|
Binary file
|
package/logo.png
DELETED
|
Binary file
|
package/plain-logo.png
DELETED
|
Binary file
|
package/testlib.sh
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
gas-fakes -l bmFiddler@13EWG4-lPrEf34itxQhAQ7b9JEbmCBfO8uE4Mhr99CHi3Pw65oxXtq-rU \
|
|
2
|
-
-s "const sheet=SpreadsheetApp.openById('1h9IGIShgVBVUrUjjawk5MaCEQte_7t32XeEP1Z5jXKQ').getSheets()[0];const fiddler = new bmFiddler.Fiddler(sheet);console.log (fiddler.getData().slice(0, 5));"
|