@mcpher/gas-fakes 2.5.2 → 2.5.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 +17 -3
- package/package.json +1 -1
- package/pngs/srv.jpg +0 -0
- package/src/cli/app.js +1 -0
- package/src/cli/togas.js +23 -14
- package/src/index.js +1 -0
- package/src/services/advslides/fakeadvslides.js +11 -5
- package/src/services/base/app.js +9 -0
- package/src/services/base/fakebase.js +28 -0
- package/src/services/common/fakeadvresource.js +3 -2
- package/src/services/content/contentservice.js +3 -2
- package/src/services/enums/baseenums.js +47 -0
- package/src/services/enums/contentenums.js +1 -3
- package/src/services/enums/scriptenums.js +31 -4
- package/src/services/enums/slidesenums.js +3 -1
- package/src/services/enums/xmlenums.js +14 -0
- package/src/services/html/serverworker.js +1 -1
- package/src/services/scriptapp/app.js +14 -7
- package/src/services/scriptapp/fakeauthorizationinfo.js +4 -4
- package/src/services/slidesapp/app.js +5 -0
- package/src/services/slidesapp/fakeautofit.js +1 -1
- package/src/services/slidesapp/fakeborder.js +106 -0
- package/src/services/slidesapp/fakecolorscheme.js +1 -1
- package/src/services/slidesapp/fakefill.js +216 -0
- package/src/services/slidesapp/fakegroup.js +35 -0
- package/src/services/slidesapp/fakeimage.js +118 -0
- package/src/services/slidesapp/fakelayout.js +351 -0
- package/src/services/slidesapp/fakeline.js +2 -2
- package/src/services/slidesapp/fakelinefill.js +15 -16
- package/src/services/slidesapp/fakelink.js +20 -3
- package/src/services/slidesapp/fakelist.js +36 -0
- package/src/services/slidesapp/fakeliststyle.js +105 -0
- package/src/services/slidesapp/fakemaster.js +358 -0
- package/src/services/slidesapp/fakenotesmaster.js +125 -0
- package/src/services/slidesapp/fakenotespage.js +102 -2
- package/src/services/slidesapp/fakepagebackground.js +109 -1
- package/src/services/slidesapp/fakepageelement.js +157 -18
- package/src/services/slidesapp/fakepageelementrange.js +28 -0
- package/src/services/slidesapp/fakepagerange.js +28 -0
- package/src/services/slidesapp/fakeparagraphstyle.js +139 -0
- package/src/services/slidesapp/fakepicturefill.js +32 -0
- package/src/services/slidesapp/fakepresentation.js +126 -2
- package/src/services/slidesapp/fakeshape.js +9 -0
- package/src/services/slidesapp/fakeslide.js +216 -24
- package/src/services/slidesapp/fakesolidfill.js +45 -0
- package/src/services/slidesapp/fakespeakerspotlight.js +18 -0
- package/src/services/slidesapp/faketable.js +55 -9
- package/src/services/slidesapp/faketablecell.js +141 -12
- package/src/services/slidesapp/faketablecellrange.js +28 -0
- package/src/services/slidesapp/faketablecolumn.js +72 -0
- package/src/services/slidesapp/faketablerow.js +31 -0
- package/src/services/slidesapp/faketextrange.js +179 -135
- package/src/services/slidesapp/faketextstyle.js +158 -0
- package/src/services/slidesapp/fakevideo.js +35 -0
- package/src/services/slidesapp/fakewordart.js +22 -0
- package/src/services/slidesapp/pageelementfactory.js +24 -1
- package/src/services/spreadsheetapp/fakeembeddedchartbuilder.js +92 -12
- package/src/services/spreadsheetapp/fakespreadsheet.js +360 -62
- package/src/services/spreadsheetapp/fakespreadsheettheme.js +53 -0
- package/src/services/urlfetchapp/app.js +216 -175
- package/src/services/xmlservice/app.js +3 -78
- package/src/services/xmlservice/fakeattribute.js +15 -0
- package/src/services/xmlservice/fakecdata.js +40 -0
- package/src/services/xmlservice/fakecomment.js +34 -0
- package/src/services/xmlservice/fakecontent.js +51 -0
- package/src/services/xmlservice/fakedoctype.js +68 -0
- package/src/services/xmlservice/fakedocument.js +110 -13
- package/src/services/xmlservice/fakeelement.js +297 -82
- package/src/services/xmlservice/fakeentityref.js +54 -0
- package/src/services/xmlservice/fakeformat.js +67 -22
- package/src/services/xmlservice/fakeprocessinginstruction.js +44 -0
- package/src/services/xmlservice/faketext.js +39 -0
- package/src/services/xmlservice/fakexmlservice.js +118 -0
- package/src/support/sxfetch.js +60 -0
- package/tools/omlx.env.example +6 -0
- package/tools/omlx_mcp_server.cjs +157 -0
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ npm i @mcpher/gas-fakes
|
|
|
16
16
|
|
|
17
17
|
For a complete guide on how to set up your local environment for authentication and development, please see the consolidated guide: [Getting Started with `gas-fakes`](GETTING_STARTED.md)
|
|
18
18
|
|
|
19
|
-
Collaborators should fork the repo and use the local versions of these files - see collaborators info.
|
|
19
|
+
Collaborators should fork the repo and use the local versions of these files - see [collaborators info](./notes/contributing.md)
|
|
20
20
|
|
|
21
21
|
### Use exactly the same code as in Apps Script
|
|
22
22
|
## Usage
|
|
@@ -159,25 +159,39 @@ As I mentioned earlier, to take this further, I'm going to need a lot of help to
|
|
|
159
159
|
|
|
160
160
|
## <img src="../pngs/logo.png" alt="gas-fakes logo" width="50" align="top"> Further Reading
|
|
161
161
|
|
|
162
|
+
|
|
163
|
+
|
|
162
164
|
## Watch the gas-fakes intro video
|
|
163
165
|
|
|
164
166
|
[](https://youtu.be/oEjpIrkYpEM)
|
|
165
167
|
|
|
168
|
+
## Watch the explainer about delegating work to local LLMs to save token costs
|
|
169
|
+
|
|
170
|
+
[](https://youtu.be/tcvU2NLEaNE)
|
|
171
|
+
|
|
166
172
|
## Watch the gf_agent video on natural language automation
|
|
167
173
|
|
|
168
174
|
[](https://youtu.be/lujByoX71HU)
|
|
169
175
|
|
|
176
|
+
## Watch the local webapps and addons development video
|
|
177
|
+
|
|
178
|
+
[](https://youtu.be/vH9wl7QloZ4)
|
|
179
|
+
|
|
170
180
|
## Read more docs
|
|
171
181
|
|
|
172
182
|
- [release notes](versionnotes/)
|
|
173
183
|
- [gas fakes intro video](https://youtu.be/oEjpIrkYpEM)
|
|
174
184
|
- [getting started](GETTING_STARTED.md) - how to handle authentication for Workspace scopes.
|
|
175
185
|
- [readme](README.md)
|
|
186
|
+
- [apps script parity](notes/parity.md)
|
|
187
|
+
- [omlx setup](notes/omlx-setup.md)
|
|
176
188
|
- [Natural Language Automation with Gemini Skills & MCP Server](notes/gemini-skills-mcp.md) - new skills-based agent approach.
|
|
177
189
|
- [Add agent skills to gf_agent](https://ramblings.mcpher.com/add-skills-gf_agent/)
|
|
178
190
|
- [gf_agent documentation](../gf_agent/README.md) - instructions for the Gemini CLI automation agent and MCP server.
|
|
179
191
|
- [gas fakes cli](notes/gas-fakes-cli.md)
|
|
180
|
-
-[local add-on and webapp development with gas-fakes](notes/local-web-development.md)
|
|
192
|
+
- [local add-on and webapp development with gas-fakes](notes/local-web-development.md)
|
|
193
|
+
- [Bringing the webapp home](https://ramblings.mcpher.com/local-apps-script-webapp-and-ui-emulation/)
|
|
194
|
+
- [Local development example code](https://github.com/brucemcpherson/gf-serve)
|
|
181
195
|
- [github actions using adc](https://github.com/brucemcpherson/gas-fakes-actions-adc)
|
|
182
196
|
- [github actions using dwd and wif](https://github.com/brucemcpherson/gas-fakes-actions-dwd)
|
|
183
197
|
- [ksuite as a back end](notes/ksuite_poc.md)
|
|
@@ -195,7 +209,7 @@ As I mentioned earlier, to take this further, I'm going to need a lot of help to
|
|
|
195
209
|
- [jdbc notes](notes/jdbc-notes.md)
|
|
196
210
|
- [Yes – you can run native apps script code on Azure ACA as well!](https://ramblings.mcpher.com/yes-you-can-run-native-apps-script-code-on-azure-aca-as-well/)
|
|
197
211
|
- [Yes – you can run native apps script code on AWS Lambda!](https://ramblings.mcpher.com/apps-script-on-aws-lambda/)
|
|
198
|
-
- [initial idea and thoughts](https://ramblings.mcpher.com/a-proof-of-concept-implementation-of-apps-script-environment-on-node/)
|
|
212
|
+
- [initial idea and thoughts - how it all started](https://ramblings.mcpher.com/a-proof-of-concept-implementation-of-apps-script-environment-on-node/)
|
|
199
213
|
- [Inside the volatile world of a Google Document](https://ramblings.mcpher.com/inside-the-volatile-world-of-a-google-document/)
|
|
200
214
|
- [Apps Script Services on Node – using apps script libraries](https://ramblings.mcpher.com/apps-script-services-on-node-using-apps-script-libraries/)
|
|
201
215
|
- [Apps Script environment on Node – more services](https://ramblings.mcpher.com/apps-script-environment-on-node-more-services/)
|
package/package.json
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"name": "@mcpher/gas-fakes",
|
|
41
41
|
"author": "bruce mcpherson",
|
|
42
|
-
"version": "2.5.
|
|
42
|
+
"version": "2.5.4",
|
|
43
43
|
"license": "MIT",
|
|
44
44
|
"main": "main.js",
|
|
45
45
|
"description": "An implementation of the Google Workspace Apps Script runtime: Run native App Script Code on Node and Cloud Run",
|
package/pngs/srv.jpg
ADDED
|
Binary file
|
package/src/cli/app.js
CHANGED
|
@@ -219,6 +219,7 @@ export async function main() {
|
|
|
219
219
|
.option("-s, --source <string>", "Source directory (default: ./ )")
|
|
220
220
|
.option("-e, --env <path>", "Path to a custom .env file.", "./.env")
|
|
221
221
|
.option("--scriptId <string>", "Script ID for the target clasp project.")
|
|
222
|
+
.option("-q, --quiet", "Automatically accept all prompts.")
|
|
222
223
|
.action(togas);
|
|
223
224
|
|
|
224
225
|
program.showHelpAfterError("(add --help for additional information)");
|
package/src/cli/togas.js
CHANGED
|
@@ -20,6 +20,7 @@ export async function togas(options) {
|
|
|
20
20
|
const scriptId = options.scriptId || process.env.TOGAS_SCRIPT_ID || process.env.GF_SCRIPT_ID;
|
|
21
21
|
const pattern = options.pattern || process.env.TOGAS_PATTERN || "*";
|
|
22
22
|
const source = options.source || "./";
|
|
23
|
+
const autoAccept = !!options.quiet;
|
|
23
24
|
|
|
24
25
|
if (!target) {
|
|
25
26
|
console.error("Error: TOGAS_TARGET is not set. Please run 'gas-fakes init' or provide --target.");
|
|
@@ -41,14 +42,18 @@ export async function togas(options) {
|
|
|
41
42
|
|
|
42
43
|
const claspJsonPath = path.join(absoluteTarget, ".clasp.json");
|
|
43
44
|
if (!fs.existsSync(claspJsonPath)) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
let create = autoAccept;
|
|
46
|
+
if (!create) {
|
|
47
|
+
const response = await prompts({
|
|
48
|
+
type: "confirm",
|
|
49
|
+
name: "create",
|
|
50
|
+
message: `No .clasp.json found in ${target}. Create one?`,
|
|
51
|
+
initial: true
|
|
52
|
+
});
|
|
53
|
+
create = response.create;
|
|
54
|
+
}
|
|
50
55
|
|
|
51
|
-
if (
|
|
56
|
+
if (create) {
|
|
52
57
|
if (!scriptId) {
|
|
53
58
|
console.error("Error: No Script ID found. Please provide one with --scriptId or in .env.");
|
|
54
59
|
process.exit(1);
|
|
@@ -157,14 +162,18 @@ export async function togas(options) {
|
|
|
157
162
|
console.log(`Ready for clasp push in ${target}.`);
|
|
158
163
|
|
|
159
164
|
// 5. Clasp push
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
let push = autoAccept;
|
|
166
|
+
if (!push) {
|
|
167
|
+
const response = await prompts({
|
|
168
|
+
type: "confirm",
|
|
169
|
+
name: "push",
|
|
170
|
+
message: "Push to Apps Script using clasp now?",
|
|
171
|
+
initial: true
|
|
172
|
+
});
|
|
173
|
+
push = response.push;
|
|
174
|
+
}
|
|
166
175
|
|
|
167
|
-
if (
|
|
176
|
+
if (push) {
|
|
168
177
|
console.log("Running clasp push...");
|
|
169
178
|
try {
|
|
170
179
|
execSync("clasp push", { cwd: absoluteTarget, stdio: "inherit" });
|
package/src/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import './services/gmailapp/app.js'
|
|
|
11
11
|
import './services/calendarapp/app.js'
|
|
12
12
|
import './services/chartsapp/app.js'
|
|
13
13
|
import './services/session/app.js'
|
|
14
|
+
import './services/base/app.js'
|
|
14
15
|
import './services/advdrive/app.js'
|
|
15
16
|
import './services/advsheets/app.js'
|
|
16
17
|
import './services/advdocs/app.js'
|
|
@@ -16,15 +16,15 @@ class FakeAdvSlidesPresentations extends FakeAdvResource {
|
|
|
16
16
|
// Override 'get' to use the caching-enabled function fxSlidesGet.
|
|
17
17
|
get(presentationId, options) {
|
|
18
18
|
ScriptApp.__behavior.isAccessible(presentationId, 'Slides', 'read');
|
|
19
|
-
const { response, data } = this._call('get', { presentationId, ...options }, Syncit.fxSlidesGet);
|
|
19
|
+
const { response, data } = this._call('get', { presentationId, ...options }, {}, null, Syncit.fxSlidesGet);
|
|
20
20
|
gError(response, 'slides.presentations', 'get');
|
|
21
21
|
return data;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
// Signature matches Apps Script advanced service.
|
|
25
25
|
create(presentation) {
|
|
26
|
-
// The underlying API wants the resource in a '
|
|
27
|
-
const result = this._call('create', {
|
|
26
|
+
// The underlying API wants the resource in a 'requestBody' property for Node.js.
|
|
27
|
+
const result = this._call('create', { requestBody: presentation });
|
|
28
28
|
if (result.data) {
|
|
29
29
|
this.slides.__addAllowed(result.data.presentationId);
|
|
30
30
|
}
|
|
@@ -32,12 +32,18 @@ class FakeAdvSlidesPresentations extends FakeAdvResource {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// Signature matches Apps Script advanced service.
|
|
35
|
-
|
|
35
|
+
// Robustly handle both resource object and raw requests array.
|
|
36
|
+
batchUpdate(resource, presentationId) {
|
|
36
37
|
// for slides, any batch update is a write
|
|
37
38
|
ScriptApp.__behavior.isAccessible(presentationId, 'Slides', 'write');
|
|
39
|
+
|
|
40
|
+
const requestBody = Array.isArray(resource)
|
|
41
|
+
? { requests: resource }
|
|
42
|
+
: resource;
|
|
43
|
+
|
|
38
44
|
const result = this._call('batchUpdate', {
|
|
39
45
|
presentationId,
|
|
40
|
-
|
|
46
|
+
requestBody,
|
|
41
47
|
});
|
|
42
48
|
gError(result.response, 'slides.presentations', 'batchUpdate');
|
|
43
49
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* the idea here is to create an empty global entry for the singleton
|
|
3
|
+
* but only load it when it is actually used.
|
|
4
|
+
*/
|
|
5
|
+
import { lazyLoaderApp } from '../common/lazyloader.js'
|
|
6
|
+
import { newFakeBase as maker } from './fakebase.js';
|
|
7
|
+
|
|
8
|
+
let _app = null;
|
|
9
|
+
_app = lazyLoaderApp(_app, 'Base', maker);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import * as BaseEnums from '../enums/baseenums.js';
|
|
3
|
+
import { newFakeMimeType } from '../mimetype/fakemimetype.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @class FakeBase
|
|
7
|
+
* @description The Base service in Google Apps Script.
|
|
8
|
+
* @see https://developers.google.com/apps-script/reference/base
|
|
9
|
+
*/
|
|
10
|
+
export class FakeBase {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.Button = BaseEnums.Button;
|
|
13
|
+
this.ButtonSet = BaseEnums.ButtonSet;
|
|
14
|
+
this.ColorType = BaseEnums.ColorType;
|
|
15
|
+
this.MimeType = newFakeMimeType();
|
|
16
|
+
this.Month = BaseEnums.Month;
|
|
17
|
+
this.Weekday = BaseEnums.Weekday;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
toString() {
|
|
21
|
+
return 'Base';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @returns {FakeBase}
|
|
27
|
+
*/
|
|
28
|
+
export const newFakeBase = () => Proxies.guard(new FakeBase());
|
|
@@ -14,7 +14,7 @@ export class FakeAdvResource {
|
|
|
14
14
|
this.__syncitMethod = syncitMethod; // e.g., Syncit.fxDocs or Syncit.fxSheets
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
_call(method, params, options, subProp = null) {
|
|
17
|
+
_call(method, params, options, subProp = null, syncMethodOverride = null) {
|
|
18
18
|
const pack = {
|
|
19
19
|
prop: this.__serviceName,
|
|
20
20
|
subProp,
|
|
@@ -22,7 +22,8 @@ export class FakeAdvResource {
|
|
|
22
22
|
params,
|
|
23
23
|
options
|
|
24
24
|
};
|
|
25
|
-
const
|
|
25
|
+
const syncMethod = syncMethodOverride || this.__syncitMethod;
|
|
26
|
+
const result = syncMethod(pack);
|
|
26
27
|
if (!result || !result.response) {
|
|
27
28
|
// Simulate an error response if the worker didn't provide one.
|
|
28
29
|
return {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { FakeTextOutput } from "./textoutput.js";
|
|
2
|
-
|
|
2
|
+
// just avoid conflict with global MimeType
|
|
3
|
+
import { MimeType as mt } from "../enums/contentenums.js";
|
|
3
4
|
|
|
4
5
|
export class FakeContentService {
|
|
5
6
|
constructor() {
|
|
6
|
-
this.MimeType =
|
|
7
|
+
this.MimeType = mt;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
createTextOutput(content = "") {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { newFakeGasenum } from "@mcpher/fake-gasenum";
|
|
2
|
+
|
|
3
|
+
export const Button = newFakeGasenum([
|
|
4
|
+
"CANCEL",
|
|
5
|
+
"CLOSE",
|
|
6
|
+
"NO",
|
|
7
|
+
"OK",
|
|
8
|
+
"YES"
|
|
9
|
+
])
|
|
10
|
+
|
|
11
|
+
export const ButtonSet = newFakeGasenum([
|
|
12
|
+
"OK",
|
|
13
|
+
"OK_CANCEL",
|
|
14
|
+
"YES_NO",
|
|
15
|
+
"YES_NO_CANCEL"
|
|
16
|
+
])
|
|
17
|
+
|
|
18
|
+
export const ColorType = newFakeGasenum([
|
|
19
|
+
"RGB",
|
|
20
|
+
"THEME",
|
|
21
|
+
"UNSUPPORTED"
|
|
22
|
+
])
|
|
23
|
+
|
|
24
|
+
export const Month = newFakeGasenum([
|
|
25
|
+
"JANUARY",
|
|
26
|
+
"FEBRUARY",
|
|
27
|
+
"MARCH",
|
|
28
|
+
"APRIL",
|
|
29
|
+
"MAY",
|
|
30
|
+
"JUNE",
|
|
31
|
+
"JULY",
|
|
32
|
+
"AUGUST",
|
|
33
|
+
"SEPTEMBER",
|
|
34
|
+
"OCTOBER",
|
|
35
|
+
"NOVEMBER",
|
|
36
|
+
"DECEMBER"
|
|
37
|
+
])
|
|
38
|
+
|
|
39
|
+
export const Weekday = newFakeGasenum([
|
|
40
|
+
"SUNDAY",
|
|
41
|
+
"MONDAY",
|
|
42
|
+
"TUESDAY",
|
|
43
|
+
"WEDNESDAY",
|
|
44
|
+
"THURSDAY",
|
|
45
|
+
"FRIDAY",
|
|
46
|
+
"SATURDAY"
|
|
47
|
+
])
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { newFakeGasenum } from "@mcpher/fake-gasenum";
|
|
2
2
|
|
|
3
|
-
export const
|
|
4
|
-
MimeType: newFakeGasenum([
|
|
3
|
+
export const MimeType = newFakeGasenum([
|
|
5
4
|
"ATOM",
|
|
6
5
|
"CSV",
|
|
7
6
|
"ICAL",
|
|
@@ -12,4 +11,3 @@ export const ContentEnums = {
|
|
|
12
11
|
"VCARD",
|
|
13
12
|
"XML"
|
|
14
13
|
])
|
|
15
|
-
}
|
|
@@ -1,6 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { newFakeGasenum } from "@mcpher/fake-gasenum";
|
|
2
|
+
|
|
3
|
+
export const AuthorizationStatus = newFakeGasenum({
|
|
3
4
|
REQUIRED: 'REQUIRED',
|
|
4
5
|
NOT_REQUIRED: 'NOT_REQUIRED'
|
|
5
|
-
}
|
|
6
|
-
|
|
6
|
+
})
|
|
7
|
+
export const TriggerSource = newFakeGasenum( {
|
|
8
|
+
CALENDAR: 'CALENDAR',
|
|
9
|
+
CLOCK: 'CLOCK',
|
|
10
|
+
DOCUMENTS: 'DOCUMENTS',
|
|
11
|
+
FORMS: 'FORMS',
|
|
12
|
+
SPREADSHEETS: 'SPREADSHEETS'
|
|
13
|
+
})
|
|
14
|
+
export const AuthMode = newFakeGasenum( {
|
|
15
|
+
NONE: 'NONE',
|
|
16
|
+
CUSTOM_FUNCTION: 'CUSTOM_FUNCTION',
|
|
17
|
+
LIMITED: 'LIMITED',
|
|
18
|
+
FULL: 'FULL'
|
|
19
|
+
})
|
|
20
|
+
export const EventType = newFakeGasenum( {
|
|
21
|
+
CLOCK: 'CLOCK',
|
|
22
|
+
ON_OPEN: 'ON_OPEN',
|
|
23
|
+
ON_EDIT: 'ON_EDIT',
|
|
24
|
+
ON_FORM_SUBMIT: 'ON_FORM_SUBMIT',
|
|
25
|
+
ON_CHANGE: 'ON_CHANGE',
|
|
26
|
+
ON_EVENT_UPDATED: 'ON_EVENT_UPDATED'
|
|
27
|
+
})
|
|
28
|
+
export const InstallationSource = newFakeGasenum({
|
|
29
|
+
APPS_MARKETPLACE_DOMAIN_ADD_ON: 'APPS_MARKETPLACE_DOMAIN_ADD_ON',
|
|
30
|
+
NONE: 'NONE',
|
|
31
|
+
WEB_STORE_ADD_ON: 'WEB_STORE_ADD_ON'
|
|
32
|
+
})
|
|
33
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { newFakeGasenum } from "@mcpher/fake-gasenum";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Enum representing the possible content types found in XML.
|
|
5
|
+
*/
|
|
6
|
+
export const ContentTypes = newFakeGasenum([
|
|
7
|
+
"CDATA",
|
|
8
|
+
"COMMENT",
|
|
9
|
+
"DOCTYPE",
|
|
10
|
+
"ELEMENT",
|
|
11
|
+
"ENTITYREF",
|
|
12
|
+
"PROCESSINGINSTRUCTION",
|
|
13
|
+
"TEXT"
|
|
14
|
+
]);
|
|
@@ -60,7 +60,7 @@ export class ServerWorkerContext {
|
|
|
60
60
|
mainScriptPath: globalThis.__gasFakesMainScriptPath || this._mainScriptPath,
|
|
61
61
|
controlBuf: this._controlBuf,
|
|
62
62
|
dataBuf: this._dataBuf,
|
|
63
|
-
env: process.env // Pass current environment
|
|
63
|
+
env: { ...process.env, GAS_FAKES_WORKER: 'true' } // Pass current environment and mark as worker
|
|
64
64
|
},
|
|
65
65
|
stdout: true,
|
|
66
66
|
stderr: true
|
|
@@ -7,7 +7,13 @@ import { Auth } from '../../support/auth.js'
|
|
|
7
7
|
import { Proxies } from '../../support/proxies.js'
|
|
8
8
|
import { newFakeBehavior } from './behavior.js'
|
|
9
9
|
import { newFakeAuthorizationInfo } from './fakeauthorizationinfo.js'
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
AuthMode,
|
|
12
|
+
AuthorizationStatus,
|
|
13
|
+
TriggerSource,
|
|
14
|
+
EventType,
|
|
15
|
+
InstallationSource
|
|
16
|
+
} from '../enums/scriptenums.js'
|
|
11
17
|
import { newCacheDropin } from '@mcpher/gas-flex-cache'
|
|
12
18
|
import { slogger } from "../../support/slogger.js";
|
|
13
19
|
import fs from 'fs';
|
|
@@ -48,8 +54,8 @@ const getSourceOAuthToken = () => {
|
|
|
48
54
|
|
|
49
55
|
|
|
50
56
|
const limitMode = (mode) => {
|
|
51
|
-
if (mode !== ScriptApp.AuthMode.FULL) {
|
|
52
|
-
throw new Error(`only ${ScriptApp.AuthMode.FULL} is supported as mode for now`)
|
|
57
|
+
if (mode !== ScriptApp.AuthMode.FULL.toString()) {
|
|
58
|
+
throw new Error(`only ${ScriptApp.AuthMode.FULL.toString()} is supported as mode for now`)
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
return mode
|
|
@@ -234,10 +240,11 @@ if (typeof globalThis[name] === typeof undefined) {
|
|
|
234
240
|
ensureInit()
|
|
235
241
|
return Auth.getActiveUser()?.id
|
|
236
242
|
},
|
|
237
|
-
AuthMode
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
243
|
+
AuthMode,
|
|
244
|
+
AuthorizationStatus,
|
|
245
|
+
TriggerSource,
|
|
246
|
+
EventType,
|
|
247
|
+
InstallationSource,
|
|
241
248
|
getAuthorizationInfo: (authMode) => {
|
|
242
249
|
ensureInit();
|
|
243
250
|
return newFakeAuthorizationInfo(authMode);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AuthorizationStatus } from '../enums/scriptenums.js';
|
|
2
2
|
|
|
3
3
|
export class FakeAuthorizationInfo {
|
|
4
4
|
constructor(authMode) {
|
|
@@ -8,12 +8,12 @@ export class FakeAuthorizationInfo {
|
|
|
8
8
|
getAuthorizationStatus() {
|
|
9
9
|
// gas-fakes always handles auth out-of-band via CLI,
|
|
10
10
|
// so during script execution, we assume auth is not required.
|
|
11
|
-
return
|
|
11
|
+
return AuthorizationStatus.NOT_REQUIRED;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
getAuthorizationUrl() {
|
|
15
|
-
// Return
|
|
16
|
-
return
|
|
15
|
+
// Return empty string since we don't require inline authorization, matching live Apps Script parity
|
|
16
|
+
return "";
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -5,5 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
import { lazyLoaderApp } from '../common/lazyloader.js'
|
|
7
7
|
import { newFakeSlidesApp as maker} from './fakeslidesapp.js';
|
|
8
|
+
import './pageelementfactory.js';
|
|
9
|
+
export { newFakePageElementRange } from './fakepageelementrange.js';
|
|
10
|
+
export { newFakePageRange } from './fakepagerange.js';
|
|
11
|
+
export { newFakeTableCellRange } from './faketablecellrange.js';
|
|
12
|
+
export { newFakeTableColumn } from './faketablecolumn.js';
|
|
8
13
|
let _app = null;
|
|
9
14
|
_app = lazyLoaderApp(_app, 'SlidesApp', maker)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Proxies } from '../../support/proxies.js';
|
|
2
|
+
import { newFakeLineFill } from './fakelinefill.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Represents the Border properties of a Slides element.
|
|
6
|
+
* Emulates the Slides API resource structure.
|
|
7
|
+
*/
|
|
8
|
+
export const newFakeBorder = (...args) => {
|
|
9
|
+
return Proxies.guard(new FakeBorder(...args));
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export class FakeBorder {
|
|
13
|
+
/**
|
|
14
|
+
* @param {FakePageElement} parent - The element this border belongs to.
|
|
15
|
+
*/
|
|
16
|
+
constructor(parent) {
|
|
17
|
+
this._parent = parent;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get __resource() {
|
|
21
|
+
// Border properties are typically in imageProperties.outline or shapeProperties.outline
|
|
22
|
+
const res = this._parent.__resource;
|
|
23
|
+
return res.image?.imageProperties?.outline || res.shape?.shapeProperties?.outline;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getLineFill() {
|
|
27
|
+
return newFakeLineFill(this._parent);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
isVisible() {
|
|
31
|
+
const weight = this.getWeight();
|
|
32
|
+
return weight !== null && weight > 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setDashStyle(style) {
|
|
36
|
+
this.__update({ dashStyle: style.toString() }, 'dashStyle');
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
setTransparent() {
|
|
41
|
+
this.__update({ propertyState: 'NOT_RENDERED' }, 'propertyState');
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setWeight(weight) {
|
|
46
|
+
this.__update({ weight: { magnitude: weight, unit: 'PT' }, propertyState: 'RENDERED' }, 'weight,propertyState');
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
__update(props, fields) {
|
|
51
|
+
const presentationId = this._parent.__presentation?.getId() || this._parent.__page?.__presentation?.getId();
|
|
52
|
+
const type = this._parent.getPageElementType().toString();
|
|
53
|
+
const objectId = this._parent.getObjectId();
|
|
54
|
+
|
|
55
|
+
let request = null;
|
|
56
|
+
if (type === 'SHAPE') {
|
|
57
|
+
request = {
|
|
58
|
+
updateShapeProperties: {
|
|
59
|
+
objectId,
|
|
60
|
+
shapeProperties: { outline: props },
|
|
61
|
+
fields: fields ? fields.split(',').map(f => `outline.${f}`).join(',') : 'outline'
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
} else if (type === 'IMAGE') {
|
|
65
|
+
request = {
|
|
66
|
+
updateImageProperties: {
|
|
67
|
+
objectId,
|
|
68
|
+
imageProperties: { outline: props },
|
|
69
|
+
fields: fields ? fields.split(',').map(f => `outline.${f}`).join(',') : 'outline'
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (request) {
|
|
75
|
+
Slides.Presentations.batchUpdate({ requests: [request] }, presentationId);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Retrieves the weight of the border in Points (PT).
|
|
81
|
+
* @returns {number | null} The border weight in PT, or null if not defined/rendered.
|
|
82
|
+
*/
|
|
83
|
+
getWeight() {
|
|
84
|
+
const outline = this.__resource;
|
|
85
|
+
if (!outline || outline.propertyState === 'NOT_RENDERED' || outline.weight === undefined) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return this._parent.__normalize(outline.weight);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Gets the DashStyle of the border.
|
|
93
|
+
* @returns {string} The dash style.
|
|
94
|
+
*/
|
|
95
|
+
getDashStyle() {
|
|
96
|
+
const outline = this.__resource;
|
|
97
|
+
if (!outline || outline.propertyState === 'NOT_RENDERED' || !outline.dashStyle) {
|
|
98
|
+
return 'SOLID';
|
|
99
|
+
}
|
|
100
|
+
return outline.dashStyle;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
toString() {
|
|
104
|
+
return 'Border';
|
|
105
|
+
}
|
|
106
|
+
}
|