@mcpher/gas-fakes 1.0.19 → 1.0.21

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 (72) hide show
  1. package/README.md +63 -30
  2. package/gasmess/bruce/pbx.js +53 -2
  3. package/gprompts/gas-inventory.js +92 -0
  4. package/gprompts/gas-inventory.json +176 -0
  5. package/gprompts/inventory-list.json +1 -0
  6. package/gprompts/model.json +34 -0
  7. package/gprompts/package-lock.json +1103 -0
  8. package/gprompts/package.json +18 -0
  9. package/gprompts/temp_fetch.mjs +9 -0
  10. package/gprompts/update-progress.js +142 -0
  11. package/package.json +6 -2
  12. package/setup.sh +147 -0
  13. package/src/index.js +9 -2
  14. package/src/services/advdocs/app.js +4 -23
  15. package/src/services/advdrive/app.js +6 -28
  16. package/src/services/advforms/app.js +6 -25
  17. package/src/services/advgmail/app.js +11 -0
  18. package/src/services/advgmail/fakeadvgmail.js +39 -0
  19. package/src/services/advgmail/fakeadvgmaillabels.js +119 -0
  20. package/src/services/advgmail/fakeadvgmailusers.js +23 -0
  21. package/src/services/advgmail/gmailapis.js +15 -0
  22. package/src/services/advsheets/app.js +6 -26
  23. package/src/services/advslides/app.js +6 -28
  24. package/src/services/common/lazyloader.js +22 -0
  25. package/src/services/documentapp/app.js +8 -42
  26. package/src/services/documentapp/appenderhelpers.js +21 -23
  27. package/src/services/documentapp/elementhelpers.js +0 -1
  28. package/src/services/documentapp/elementoptions.js +22 -32
  29. package/src/services/documentapp/fakeelement.js +20 -3
  30. package/src/services/documentapp/fakelistitem.js +177 -28
  31. package/src/services/documentapp/fakeparagraph.js +194 -7
  32. package/src/services/documentapp/faketable.js +16 -0
  33. package/src/services/documentapp/faketablerow.js +15 -0
  34. package/src/services/documentapp/nrhelpers.js +1 -0
  35. package/src/services/documentapp/shadowdocument.js +10 -0
  36. package/src/services/driveapp/app.js +6 -28
  37. package/src/services/enums/gmailenums.js +8 -0
  38. package/src/services/formapp/app.js +5 -40
  39. package/src/services/gmailapp/app.js +11 -0
  40. package/src/services/gmailapp/fakegmailapp.js +35 -0
  41. package/src/services/gmailapp/fakegmaillabel.js +44 -0
  42. package/src/services/logger/app.js +8 -0
  43. package/src/services/logger/fakelogger.js +162 -0
  44. package/src/services/scriptapp/app.js +7 -1
  45. package/src/services/scriptapp/behavior.js +1 -1
  46. package/src/services/session/app.js +10 -0
  47. package/src/services/slidesapp/app.js +5 -40
  48. package/src/services/spreadsheetapp/app.js +6 -50
  49. package/src/services/spreadsheetapp/fakeprotection.js +6 -7
  50. package/src/services/spreadsheetapp/fakesheet.js +3 -4
  51. package/src/services/stores/app.js +0 -1
  52. package/src/services/urlfetchapp/app.js +0 -1
  53. package/src/services/utilities/app.js +6 -20
  54. package/src/support/gmailcacher.js +7 -0
  55. package/src/support/helpers.js +2 -2
  56. package/src/support/proxies.js +20 -1
  57. package/src/support/sxgmail.js +55 -0
  58. package/src/support/syncit.js +5 -2
  59. package/src/support/utils.js +46 -15
  60. package/src/support/workersync/sxfunctions.js +5 -10
  61. package/togas.bash +18 -5
  62. package/ghissues/image-size-inconsistency-issue.sh +0 -46
  63. package/ghissues/issue-formapp-create-title-inconsistency.sh +0 -51
  64. package/ghissues/issue-positioned-image.sh +0 -25
  65. package/ghissues/post-issue.sh +0 -53
  66. package/ghissues/protection-editors-issue.sh +0 -33
  67. package/ghissues/review-sandbox-listing-issue.sh +0 -45
  68. package/ghissues/sandbox-issue.sh +0 -31
  69. package/ghissues/setup-under-construction.sh +0 -107
  70. package/src/services/base/app.js +0 -33
  71. /package/{regenerate-progress-reports.sh → gprompts/regenerate-progress-reports.sh} +0 -0
  72. /package/src/services/{base → session}/fakesession.js +0 -0
@@ -3,6 +3,7 @@
3
3
  import is from '@sindresorhus/is';
4
4
  import { assert } from '@sindresorhus/is'
5
5
 
6
+
6
7
  const isNU = (item) => is.null(item) || is.undefined(item)
7
8
 
8
9
  const arrify = (item) => is.array(item)
@@ -128,7 +129,7 @@ export const mergeParamStrings = (...args) => {
128
129
  }
129
130
  const [_, key, items] = match
130
131
  if (!itemMap.has(key)) itemMap.set(key, new Set())
131
- const item = itemMap.get(key)
132
+ const item = itemMap.get(key)
132
133
  assert.set(item)
133
134
  items.split(",").forEach(f => itemMap.get(key).add(f))
134
135
  })
@@ -376,29 +377,59 @@ const deepEqual = (obj1, obj2) => {
376
377
  }
377
378
 
378
379
  return true;
379
- };
380
+ }
381
+
382
+
383
+ function stringCircular(obj, space = null) {
384
+ // First pass: remove circular references
385
+ const withoutCircular = removeCircularReferences(obj);
380
386
 
381
- // The custom replacer function
382
- const getCircularReplacer = () => {
383
- const seen = new WeakSet(); // Use WeakSet to avoid memory leaks
384
- return (key, value) => {
385
- // If the value is an object and not null
386
- if (typeof value === "object" && value !== null) {
387
- // If we have already seen this object, it's a circular reference
387
+ // Second pass: stabilize key order
388
+ const stabilized = stabilizeKeyOrder(withoutCircular);
389
+
390
+ return JSON.stringify(stabilized, null, space);
391
+ }
392
+
393
+ function removeCircularReferences(obj) {
394
+ const seen = new WeakSet();
395
+
396
+ return JSON.parse(JSON.stringify(obj, (key, value) => {
397
+ if (typeof value === 'object' && value !== null) {
388
398
  if (seen.has(value)) {
389
- return "[Circular]"; // Replace it with a placeholder
399
+ return '[Circular]';
390
400
  }
391
- // If it's a new object, add it to our cache
392
401
  seen.add(value);
393
402
  }
394
- // Return the value to be serialized
395
403
  return value;
396
- };
397
- };
404
+ }));
405
+ }
406
+
407
+ function stabilizeKeyOrder(obj) {
408
+ if (obj === null || typeof obj !== 'object') {
409
+ return obj;
410
+ }
411
+
412
+ if (Array.isArray(obj)) {
413
+ return obj.map(stabilizeKeyOrder);
414
+ }
415
+
416
+ const sortedKeys = Object.keys(obj).sort();
417
+ const result = {};
398
418
 
399
- const stringCircular = (ob) => JSON.stringify(ob, getCircularReplacer());
419
+ for (const key of sortedKeys) {
420
+ result[key] = stabilizeKeyOrder(obj[key]);
421
+ }
400
422
 
423
+ return result;
424
+ }
425
+ const lobify = (ob, mess = '') => {
426
+ let lob = ob
427
+ if (is.object(lob)) lob = stringCircular(lob)
428
+ console.log(mess, lob)
429
+ return ob
430
+ }
401
431
  export const Utils = {
432
+ lobify,
402
433
  stringCircular,
403
434
  hexToRgb,
404
435
  stringToBytes,
@@ -1,15 +1,10 @@
1
- /**
2
- * This file aggregates and exports all the asynchronous functions
3
- * that can be called by the main thread via the synchronizer.
4
- * The worker thread imports this single file to get access to all
5
- * sx* functions.
6
- */
7
- export * from '../sxauth.js';
8
1
  export * from '../sxdrive.js';
9
2
  export * from '../sxsheets.js';
10
3
  export * from '../sxdocs.js';
11
- export * from '../sxforms.js';
12
4
  export * from '../sxslides.js';
13
- export * from '../sxzip.js';
5
+ export * from '../sxforms.js';
14
6
  export * from '../sxfetch.js';
15
- export * from '../sxstore.js';
7
+ export * from '../sxstore.js';
8
+ export * from '../sxzip.js';
9
+ export * from '../sxauth.js';
10
+ export * from '../sxgmail.js';
package/togas.bash CHANGED
@@ -25,15 +25,26 @@ cp ${SOURCE}/test*.js ${TARGET}/test
25
25
 
26
26
  # find all the copied files and comment/fixes out import and export statements
27
27
  # note - this simple version naively expects that to be on 1 line
28
- find "${TARGET}" -name "${EXT}" -type f -exec perl -i -pe 'if (/^import\b/) { $in_import=1 } if ($in_import) { s/^/\/\//; if (/['\''"][^'\''"]*['\''"];?\s*$/) { $in_import=0 } }' {} +
28
+ # version below only works on linux - the perl version should work on both mac and linux
29
+ #find "${TARGET}" -name "${EXT}" -type f -exec perl -i -pe 'if (/^import\b/) { $in_import=1 } if ($in_import) { s/^/\/\//; if (/['\''"][^'\''"]*['\''"];?\s*$/) { $in_import=0 } }' {} +
29
30
  # sed -i 's/^import\s\s*/\/\/import /g' $(find "${TARGET}" -name "${EXT}" -type f)
30
- sed -i 's/^\s*export\s\s*//g' $(find "${TARGET}" -name "${EXT}" -type f)
31
+ #sed -i 's/^\s*export\s\s*//g' $(find "${TARGET}" -name "${EXT}" -type f)
32
+
31
33
 
34
+ # Perl works consistently across platforms
35
+ find "${TARGET}" -name "${EXT}" -type f -exec perl -i -pe 's/^\s*export\s\s*//g' {} \;
36
+ find "${TARGET}" -name "${EXT}" -type f -exec perl -i -pe 'if (/^import\b/) { $in_import=1 } if ($in_import) { s/^/\/\//; if (/['\''"][^'\''"]*['\''"];?\s*$/) { $in_import=0 } }' {} +
37
+ # sed -i 's/^import\s\s*/\/\/import /g' $(find "${TARGET}" -name "${EXT}" -type f)
32
38
  # replace all process.env.VAR_NAME occurrences with actual value
33
39
  # process.env is not usable in apps script
34
- for var in $(grep -oP 'process\.env\.\K\w+' "${TARGET}/test/testinit.js"); do
35
- value=$(printenv "$var") # Get the environment variable value
40
+ #for var in $(grep -oP 'process\.env\.\K\w+' "${TARGET}/test/testinit.js"); do
41
+
42
+ # Use macos + linux version
43
+ vars=($(grep -oE 'process\.env\.\w+' "${TARGET}/test/testinit.js" | sed 's/process\.env\.//'))
36
44
 
45
+ for var in "${vars[@]}"; do
46
+
47
+ value=$(printenv "$var") # Get the environment variable value
37
48
 
38
49
  # Escape characters for sed, e.g. \n becomes \\n, & becomes \&
39
50
  value=$(printf '%q' "$value")
@@ -44,7 +55,9 @@ for var in $(grep -oP 'process\.env\.\K\w+' "${TARGET}/test/testinit.js"); do
44
55
  fi
45
56
 
46
57
  # Replace process.env.VARIABLE_NAME with the actual value
47
- sed -i "s|process.env.$var|$value|g" ${TARGET}/test/testinit.js
58
+ #sed -i "s|process.env.$var|$value|g" ${TARGET}/test/testinit.js
59
+ #macos + linux
60
+ sed -i "" "s|process.env.$var|$value|g" "${TARGET}/test/testinit.js"
48
61
  done
49
62
 
50
63
  # now go to the target and push and open if required
@@ -1,46 +0,0 @@
1
- #!/bin/bash
2
-
3
- # A shell script to create a GitHub issue for the image sizing inconsistency.
4
-
5
- # Issue title
6
- TITLE="Investigate and Align Image Insertion Sizing Behavior"
7
-
8
- # Issue body in markdown
9
- BODY=$(cat <<'EOF'
10
- ## Summary
11
-
12
- There is a significant and inconsistent discrepancy in how the live `DocumentApp` service and the `gas-fakes` emulation (via the Docs API) handle the dimensions of an image when it is inserted using `body.insertImage(image.copy())` or `body.appendImage(image.copy())`.
13
-
14
- The `testdocsimages.js` test suite has repeatedly failed and required adjustments because the expected dimensions of the inserted image are unpredictable in the live environment.
15
-
16
- ## Observed Behaviors in Live Apps Script
17
-
18
- Our testing has revealed several conflicting behaviors from the live API:
19
-
20
- 1. **Intrinsic Size:** Sometimes, the API ignores the dimensions of the copied `InlineImage` object and re-fetches the image from its source URI, using its original intrinsic dimensions (e.g., `544x184` for the Google logo).
21
- 2. **Copied Object Size:** At other times, the API correctly respects the dimensions of the copied `InlineImage` object (e.g., `61x181` in our tests).
22
- 3. **Default/Fixed Size:** On at least one occasion, the API appeared to resize the image to a seemingly arbitrary fixed size (e.g., `240x80`).
23
- 4. **State-Dependent:** The behavior seems to be dependent on the state of the document. A brand-new document might exhibit one behavior, while a reused document (even after `doc.clear()`) exhibits another.
24
-
25
- ## Current Workaround
26
-
27
- The current test (`insertImage behavior on new documents` in `testdocsimages.js`) has been made more robust by:
28
- - Forcing the creation of a new document for the test using `maketdoc(..., { forceNew: true })`.
29
- - Abandoning exact dimension checks in the live environment and instead verifying the image's **aspect ratio** within a tolerance.
30
-
31
- While this makes the test pass, it highlights a core emulation inaccuracy.
32
-
33
- ## TODO
34
-
35
- 1. **Investigate Further:** Conduct a definitive set of tests to determine if there is *any* predictable pattern to the live API's behavior.
36
- 2. **Decide on Emulation Strategy:**
37
- - Should `gas-fakes` emulate the most common or most "correct" behavior (i.e., respecting the copied object's dimensions)?
38
- - Or should it attempt to mimic the most recently observed "new document" behavior (using intrinsic size)?
39
- 3. **Document the Oddity:** Regardless of the chosen strategy, this inconsistency is a significant "oddity" and should be thoroughly documented in `oddities.md` to inform users who might encounter similar issues when working with images in `DocumentApp`.
40
-
41
- This will improve the accuracy of the fake environment and provide valuable documentation for the community.
42
- EOF
43
- )
44
-
45
- # Create the issue using GitHub CLI
46
- gh issue create --title "$TITLE" --body "$BODY" --label "bug" --label "emulation-accuracy" --label "document-app"
@@ -1,51 +0,0 @@
1
- #!/bin/bash
2
-
3
- # A shell script to create a GitHub issue for the FormApp.create() title inconsistency.
4
-
5
- # Issue title
6
- TITLE="Discrepancy between FormApp.create(title) and Forms API behavior regarding form title and file name"
7
-
8
- # Issue body in markdown
9
- BODY=$(cat <<'EOF'
10
- ### Summary
11
-
12
- There is a significant and counter-intuitive discrepancy between the documented behavior of `FormApp.create(title)` in Google Apps Script and the constraints of the underlying Google Forms API. `FormApp.create(title)` sets the Google Drive *file name* to the provided `title`, but leaves the form's internal title (retrieved by `form.getTitle()`) blank.
13
-
14
- This makes it impossible to accurately emulate the Apps Script behavior using the public Forms API, as the API requires a non-empty title for both creation and updates.
15
-
16
- ### Live Apps Script Behavior
17
-
18
- When the following Apps Script code is executed:
19
-
20
- ```javascript
21
- function testFormCreation() {
22
- const formName = "foo-form";
23
- const form = FormApp.create(formName);
24
- const id = form.getId();
25
-
26
- console.log('Internal form title:', form.getTitle()); // Logs: "" (an empty string)
27
-
28
- const file = DriveApp.getFileById(id);
29
- console.log('Drive file name:', file.getName()); // Logs: "foo-form"
30
-
31
- // cleanup
32
- file.setTrashed(true);
33
- }
34
- ```
35
-
36
- The output demonstrates that `FormApp.create()` uses the argument to set the Drive file name, but the form's own title property remains empty.
37
-
38
- ### The Problem with API Emulation
39
-
40
- This behavior is problematic to replicate with the v1 Google Forms API because the `forms.create` method requires a non-empty `info.title`. Attempting to then `batchUpdate` the title to an empty string also fails, as the API rejects an empty title on update.
41
-
42
- ### Conclusion
43
-
44
- This disconnect means it's impossible for developers using the public Forms API to programmatically create a form that exactly matches the state of one created by `FormApp.create()`. This poses a significant challenge for testing and emulation frameworks.
45
-
46
- The expected behavior would be for `FormApp.create(title)` to set both the Drive file name and the internal form title, or for the API to allow setting the title to an empty string via an update.
47
- EOF
48
- )
49
-
50
- # Create the issue using GitHub CLI
51
- gh issue create --title "$TITLE" --body "$BODY" --label "bug" --label "emulation-accuracy" --label "form-app"
@@ -1,25 +0,0 @@
1
- #!/bin/bash
2
-
3
- # A script to create a GitHub issue for the PositionedImage API limitation.
4
-
5
- # Issue details
6
- TITLE="Cannot emulate Paragraph.addPositionedImage() due to missing public API"
7
- BODY=$(cat <<'EOF'
8
- The `DocumentApp.Paragraph.addPositionedImage()` method exists in the live Google Apps Script environment, allowing for the creation of positioned images anchored to a paragraph.
9
-
10
- However, as of May 2024, there is no corresponding public endpoint in the Google Docs API v1 to programmatically create a `PositionedObject`. The `createPositionedObject` request does not exist in the public API.
11
-
12
- This has been a requested feature, but it appears that the Apps Script service uses a private, non-public API to achieve this functionality.
13
-
14
- Because `gas-fakes` relies exclusively on the public Google Workspace APIs, it is not possible to emulate this method. Tests that use `addPositionedImage` are skipped when run in the fake environment.
15
-
16
- This issue is to track this limitation and can be closed if Google exposes a public API for this feature.
17
-
18
- See this related issue tracker for the API feature request: https://issuetracker.google.com/issues/183845501 (Note: This is a guess at a relevant issue, a real one might need to be found or created).
19
- EOF
20
- )
21
- LABELS="emulation-accuracy,document-app"
22
-
23
- # Create the issue using the GitHub CLI
24
- gh issue create --title "$TITLE" --body "$BODY" --label "$LABELS"
25
-
@@ -1,53 +0,0 @@
1
- #!/bin/bash
2
-
3
- # A shell script to post a markdown file from ./ghissues as a GitHub issue.
4
- # It automatically extracts the title, labels, and body from the file.
5
- #
6
- # Usage: ./ghissues/post-issue.sh <filename>
7
- # Example: ./ghissues/post-issue.sh document-clear-behavior.md
8
-
9
- set -e
10
-
11
- # The directory where issue files are stored, relative to the script's location.
12
- SCRIPT_DIR=$(dirname "$0")
13
-
14
- # Check for filename argument
15
- if [ -z "$1" ]; then
16
- echo "Usage: $0 <filename_in_ghissues_dir>"
17
- echo "Example: $0 document-clear-behavior.md"
18
- exit 1
19
- fi
20
-
21
- ISSUE_FILE="$SCRIPT_DIR/$1"
22
-
23
- # Check if file exists
24
- if [ ! -f "$ISSUE_FILE" ]; then
25
- echo "Error: Issue file not found at $ISSUE_FILE"
26
- exit 1
27
- fi
28
-
29
- echo "Reading issue from $ISSUE_FILE..."
30
-
31
- # Extract the title (first line, remove markdown heading)
32
- TITLE=$(head -n 1 "$ISSUE_FILE" | sed 's/^# //')
33
-
34
- # Extract labels from the second line (e.g., **Labels**: `label1`, `label2`)
35
- LABELS_LINE=$(sed -n '2p' "$ISSUE_FILE")
36
- LABELS_STRING=$(echo "$LABELS_LINE" | grep -o '`.*`' | sed 's/`//g' || echo "")
37
-
38
- LABEL_ARGS=()
39
- if [ -n "$LABELS_STRING" ]; then
40
- IFS=',' read -ra ADDR <<< "$LABELS_STRING"
41
- for label in "${ADDR[@]}"; do
42
- trimmed_label=$(echo "$label" | xargs) # trim whitespace
43
- if [ -n "$trimmed_label" ]; then
44
- LABEL_ARGS+=("--label" "$trimmed_label")
45
- fi
46
- done
47
- fi
48
-
49
- # Use the rest of the file (from line 3) as the body
50
- gh issue create --title "$TITLE" --body-file <(tail -n +3 "$ISSUE_FILE") "${LABEL_ARGS[@]}"
51
-
52
- echo "Issue '$TITLE' created successfully."
53
-
@@ -1,33 +0,0 @@
1
- #!/bin/bash
2
-
3
- # A shell script to create a GitHub issue for the Protection.getEditors() behavior.
4
-
5
- # Issue title
6
- TITLE="Align Protection.getEditors() behavior with Live Apps Script"
7
-
8
- # Issue body in markdown
9
- BODY=$(cat <<'EOF'
10
- ## Summary
11
-
12
- There is a discrepancy between the live Google Apps Script environment and the `gas-fakes` emulation regarding the return value of `Protection.getEditors()` on a newly created protection.
13
-
14
- - **Live Apps Script:** `protection.getEditors().length` returns `0`.
15
- - **`gas-fakes` (current):** `protection.getEditors().length` incorrectly returns `1`.
16
-
17
- ## Live Behavior Details
18
-
19
- In the live environment, the owner of a spreadsheet can always edit a protected range or sheet (`protection.canEdit()` returns `true`). However, the owner is **not** automatically included in the explicit list of editors returned by `getEditors()`. This is confirmed by live testing.
20
-
21
- ## `gas-fakes` Behavior
22
-
23
- The `gas-fakes` implementation in `fakeprotection.js` was incorrectly adding the current user (as the owner) to the list of editors upon creation of a new `Protection` object.
24
-
25
- ## TODO
26
-
27
- 1. Modify `fakeprotection.js` to no longer automatically add the owner to the `editors` list when a new protection is created. The `canEdit()` method should still return `true` for the owner.
28
- 2. Run the full test suite to ensure this change doesn't have unintended side effects and that the `Protection` tests now pass in both environments.
29
- EOF
30
- )
31
-
32
- # Create the issue using GitHub CLI
33
- gh issue create --title "$TITLE" --body "$BODY" --label "bug" --label "emulation-accuracy" --label "spreadsheet-app"
@@ -1,45 +0,0 @@
1
- #!/bin/bash
2
-
3
- # A shell script to create a GitHub issue for reviewing sandbox listing behavior.
4
-
5
- # Issue title
6
- TITLE="Review Sandbox Strategy for File Listing Operations"
7
-
8
- # Issue body in markdown
9
- BODY=$(cat <<'EOF'
10
- ## Summary
11
-
12
- Currently, tests that perform broad file/folder listing operations (e.g., `DriveApp.getFiles()`, `someFolder.getFolders()`) fail when `strictSandbox` is `true`. This is because the underlying iterators may need to access metadata of parent folders that are not explicitly whitelisted, causing the sandbox to correctly deny access.
13
-
14
- The current workaround, as implemented in `testdrive.js`, is to temporarily disable `strictSandbox` for the duration of these tests:
15
-
16
- ```javascript
17
- const wasStrict = behavior.strictSandbox;
18
- behavior.strictSandbox = false;
19
- try {
20
- // ... listing operations ...
21
- } finally {
22
- behavior.strictSandbox = wasStrict;
23
- }
24
- ```
25
-
26
- While this works, it feels like a patch rather than a fundamental solution. We should review if there's a more robust and elegant way to handle this.
27
-
28
- ## TODO
29
-
30
- Investigate and decide on the best long-term strategy for handling file listings in strict sandbox mode.
31
-
32
- ### Options to Consider:
33
-
34
- 1. **Implicit Parent Whitelisting:** Could the file/folder iterators be enhanced to automatically (and temporarily) whitelist parent folders as they are encountered? This would keep the sandbox strict for all other operations but allow listings to complete. This seems like the most robust solution if feasible.
35
-
36
- 2. **Refined Iterator Logic:** Can the iterators be modified to avoid the specific checks that cause the failure when in strict mode? This might involve fetching less metadata for items outside the session/whitelist scope.
37
-
38
- 3. **Accept and Document:** If the current `try...finally` workaround is deemed the most practical approach, we should formally document it in `sandbox.md` as the recommended pattern for this scenario.
39
-
40
- This review will help ensure the sandbox feature is both as secure and as user-friendly as possible.
41
- EOF
42
- )
43
-
44
- # Create the issue using GitHub CLI
45
- gh issue create --title "$TITLE" --body "$BODY" --label "enhancement"
@@ -1,31 +0,0 @@
1
- #!/bin/bash
2
-
3
- # A shell script to create a GitHub issue for the sandbox feature.
4
-
5
- # Issue title
6
- TITLE="Improve Sandbox Mode to fully emulate drive.file scope"
7
-
8
- # Issue body in markdown
9
- BODY=$(cat <<'EOF'
10
- ## Summary
11
-
12
- The current implementation of `gas-fakes` requires the full `https://www.googleapis.com/auth/drive` scope for initialization, primarily to access metadata about the root Drive folder. This is a stumbling block for users who want to run tests in a more restrictive environment using only the `drive.file` scope.
13
-
14
- The `ScriptApp.__behavior.sandBoxMode` was introduced as a clever workaround to *emulate* the `drive.file` scope during test execution, but it doesn't solve the initial authorization requirement.
15
-
16
- For more details on the current sandbox implementation, see sandbox.md.
17
-
18
- ## TODO
19
-
20
- We need to investigate ways to remove the dependency on root folder access during the `FakeDriveApp` initialization. This would allow `gas-fakes` to operate with only the `drive.file` scope, making the sandbox feature a true end-to-end emulation.
21
-
22
- Possible areas to explore:
23
- - Can we mock or bypass the root folder check during initialization if a specific `drive.file` mode is detected?
24
- - Can we lazy-initialize parts of `FakeDriveApp` that require root access, and only fail if those specific methods (like `getRootFolder()`) are called without sufficient permissions?
25
-
26
- This would be a significant improvement for security-conscious development and testing workflows.
27
- EOF
28
- )
29
-
30
- # Create the issue using GitHub CLI
31
- gh issue create --title "$TITLE" --body "$BODY" --label "enhancement" --label "help wanted"
@@ -1,107 +0,0 @@
1
- #!/bin/bash
2
-
3
- echo "Welcome to the gas-fakes configuration tool!"
4
- echo "This script will help you set up your .env and gasfakes.json files."
5
-
6
- # --- Check for existing .env file ---
7
- if [ -f ".env" ]; then
8
- echo ""
9
- echo "An existing .env file was found. We will update the values."
10
- UPDATE_MODE=true
11
- else
12
- echo ""
13
- echo "No .env file found. We will create a new one."
14
- UPDATE_MODE=false
15
- fi
16
-
17
- # --- Get .env file details ---
18
- echo ""
19
- echo "First, let's configure your .env file for Application Default Credentials (ADC)."
20
- echo "These are necessary for gas-fakes to access Google Workspace APIs on your behalf."
21
-
22
- read -p "Enter your Google Cloud Project ID: " gcp_project_id
23
- read -p "Enter the ID of a Google Drive file you have access to: " drive_test_file_id
24
- read -p "Enter the default scopes (e.g., \"https://www.googleapis.com/auth/userinfo.email,openid,https://www.googleapis.com/auth/cloud-platform\"): " default_scopes
25
- read -p "Enter any EXTRA_SCOPES (e.g., ,https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/spreadsheets): " extra_scopes
26
-
27
- # --- Update or create .env file ---
28
- if [ "$UPDATE_MODE" = true ]; then
29
- # Use sed to replace the values in the existing file
30
- sed -i "s|^GCP_PROJECT_ID=.*|GCP_PROJECT_ID=$gcp_project_id|" .env
31
- sed -i "s|^DRIVE_TEST_FILE_ID=.*|DRIVE_TEST_FILE_ID=$drive_test_file_id|" .env
32
- sed -i "s|^DEFAULT_SCOPES=.*|DEFAULT_SCOPES=\"$default_scopes\"|" .env
33
- sed -i "s|^EXTRA_SCOPES=.*|EXTRA_SCOPES=\"$extra_scopes\"|" .env
34
- echo ""
35
- echo "Successfully updated the .env file."
36
- else
37
- # Write a new .env file
38
- cat <<EOF > .env
39
- # Required for gas-fakes to use Application Default Credentials
40
- GCP_PROJECT_ID="$gcp_project_id"
41
- DRIVE_TEST_FILE_ID="$drive_test_file_id"
42
-
43
- # This should generally be left as default for ADC
44
- AC=default
45
-
46
- # These are the scopes set by default - customize as needed
47
- DEFAULT_SCOPES="$default_scopes"
48
-
49
- # Add additional scopes here
50
- EXTRA_SCOPES="$extra_scopes"
51
- EOF
52
- echo ""
53
- echo "Successfully created the .env file."
54
- fi
55
-
56
- # --- Get gasfakes.json details ---
57
- echo ""
58
- echo "Next, let's configure your gasfakes.json file."
59
- echo "This file informs gas-fakes about your local environment."
60
-
61
- # Using default values as suggested by the repository
62
- DEFAULT_MANIFEST="./appsscript.json"
63
- DEFAULT_CLASP="./.clasp.json"
64
- DEFAULT_CACHE="/tmp/gas-fakes/cache"
65
- DEFAULT_PROPERTIES="/tmp/gas-fakes/properties"
66
- DEFAULT_SCRIPT_ID=$(uuidgen) # A fake script ID if clasp file is not used
67
-
68
- read -p "Enter the path to your manifest file (default: $DEFAULT_MANIFEST): " manifest_path
69
- manifest_path=${manifest_path:-$DEFAULT_MANIFEST}
70
-
71
- read -p "Enter the path to your clasp file (default: $DEFAULT_CLASP): " clasp_path
72
- clasp_path=${clasp_path:-$DEFAULT_CLASP}
73
-
74
- read -p "Enter a bound document ID if applicable (leave blank for none): " document_id
75
- if [ -z "$document_id" ]; then
76
- document_id="null"
77
- else
78
- document_id="\"$document_id\""
79
- fi
80
-
81
- read -p "Enter the local cache directory (default: $DEFAULT_CACHE): " cache_path
82
- cache_path=${cache_path:-$DEFAULT_CACHE}
83
-
84
- read -p "Enter the local properties directory (default: $DEFAULT_PROPERTIES): " properties_path
85
- properties_path=${properties_path:-$DEFAULT_PROPERTIES}
86
-
87
- read -p "Enter the script ID (default: a new random ID will be created): " script_id
88
- script_id=${script_id:-$DEFAULT_SCRIPT_ID}
89
-
90
- # --- Write gasfakes.json file ---
91
- cat <<EOF > gasfakes.json
92
- {
93
- "manifest": "$manifest_path",
94
- "clasp": "$clasp_path",
95
- "documentId": $document_id,
96
- "cache": "$cache_path",
97
- "properties": "$properties_path",
98
- "scriptId": "$script_id"
99
- }
100
- EOF
101
-
102
- echo ""
103
- echo "Successfully created the gasfakes.json file."
104
-
105
- echo ""
106
- echo "Setup complete! You can now run your gas-fakes project locally."
107
- echo "Be sure to follow the remaining setup instructions in the gas-fakes repository."
@@ -1,33 +0,0 @@
1
-
2
- /**
3
- * fake Apps Script Session
4
- * the idea here is to create a global entry for the singleton
5
- * before we actually have everything we need to create it.
6
- * We do this by using a proxy, intercepting calls to the
7
- * initial sigleton and diverting them to a completed one
8
- */
9
-
10
- import { Proxies } from '../../support/proxies.js'
11
- import { newFakeSession } from './fakesession.js'
12
-
13
- let _app = null
14
-
15
- /**
16
- * adds to global space to mimic Apps Script behavior
17
- */
18
- const name = "Session"
19
- if (typeof globalThis[name] === typeof undefined) {
20
-
21
- const getApp = () => {
22
- // if it hasn't been intialized yet then do that
23
- if (!_app) {
24
- console.log('...activating proxy for', name)
25
- _app = newFakeSession()
26
- }
27
- // this is the actual driveApp we'll return from the proxy
28
- return _app
29
- }
30
-
31
- Proxies.registerProxy(name, getApp)
32
-
33
- }
File without changes