@mcpher/gas-fakes 1.0.21 → 1.0.23

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.
@@ -1,49 +1,54 @@
1
1
  // this one is locally patched for now
2
2
  // import makeSynchronous from 'make-synchronous';
3
- import path from 'path'
4
- import { Auth } from "./auth.js"
5
- import { randomUUID } from 'node:crypto'
6
- import mime from 'mime';
7
- import { minFields } from './helpers.js'
8
- import { mergeParamStrings } from './utils.js'
9
- import { improveFileCache, checkResponse, getFromFileCache } from "./filecache.js"
10
- import { checkResponseCacher } from './fetchcacher.js';
11
- import { docsCacher } from "./docscacher.js"
12
- import { gmailCacher } from './gmailcacher.js';
13
- import { formsCacher } from './formscacher.js';
14
- import { slidesCacher } from './slidescacher.js';
15
- import { sheetsCacher } from './sheetscacher.js';
16
- import is from '@sindresorhus/is';
17
- import { callSync } from './workersync/synchronizer.js';
18
-
19
-
20
- const manifestDefaultPath = './appsscript.json'
21
- const claspDefaultPath = "./.clasp.json"
22
- const settingsDefaultPath = "./gasfakes.json"
23
- const propertiesDefaultPath = "/tmp/gas-fakes/properties"
24
- const cacheDefaultPath = "/tmp/gas-fakes/cache"
3
+ import path from "path";
4
+ import { Auth } from "./auth.js";
5
+ import { randomUUID } from "node:crypto";
6
+ import mime from "mime";
7
+ import { minFields } from "./helpers.js";
8
+ import { mergeParamStrings } from "./utils.js";
9
+ import {
10
+ improveFileCache,
11
+ checkResponse,
12
+ getFromFileCache,
13
+ } from "./filecache.js";
14
+ import { checkResponseCacher } from "./fetchcacher.js";
15
+ import { docsCacher } from "./docscacher.js";
16
+ import { gmailCacher } from "./gmailcacher.js";
17
+ import { formsCacher } from "./formscacher.js";
18
+ import { slidesCacher } from "./slidescacher.js";
19
+ import { sheetsCacher } from "./sheetscacher.js";
20
+ import is from "@sindresorhus/is";
21
+ import { callSync } from "./workersync/synchronizer.js";
22
+
23
+ const manifestDefaultPath = "./appsscript.json";
24
+ const claspDefaultPath = "./.clasp.json";
25
+ const settingsDefaultPath = "./gasfakes.json";
26
+ const propertiesDefaultPath = "/tmp/gas-fakes/properties";
27
+ const cacheDefaultPath = "/tmp/gas-fakes/cache";
25
28
  // note that functions like Sheets.newGridRange() etc create objects that contain get and set functions
26
29
  // the makesynchronous functions need data that can be serialized. so we need to string/parse to normlaize them
27
- const normalizeSerialization = (ob) => is.nullOrUndefined(ob) || !is.object(ob) ? ob : JSON.parse(JSON.stringify(ob))
28
-
30
+ const normalizeSerialization = (ob) =>
31
+ is.nullOrUndefined(ob) || !is.object(ob)
32
+ ? ob
33
+ : JSON.parse(JSON.stringify(ob));
29
34
 
30
35
  /**
31
36
  * check and register a result in cache
32
37
  * @param {import('./sxdrive.js').SxResult} the result of a sync api call
33
- * @return {import('./sxdrive.js').SxResult}
38
+ * @return {import('./sxdrive.js').SxResult}
34
39
  */
35
40
  const registerSx = (result, allow404 = false, fields) => {
36
- const { data, response } = result
37
- checkResponse(data?.id, response, allow404)
41
+ const { data, response } = result;
42
+ checkResponse(data?.id, response, allow404);
38
43
  if (data?.id) {
39
44
  return {
40
45
  ...result,
41
- data: improveFileCache(data.id, data, fields)
42
- }
46
+ data: improveFileCache(data.id, data, fields),
47
+ };
43
48
  } else {
44
- return result
49
+ return result;
45
50
  }
46
- }
51
+ };
47
52
 
48
53
  const register = (id, cacher, result, allow404 = false, params) => {
49
54
  const { data, response } = result;
@@ -56,8 +61,7 @@ const register = (id, cacher, result, allow404 = false, params) => {
56
61
  } else {
57
62
  return result;
58
63
  }
59
- }
60
-
64
+ };
61
65
 
62
66
  /**
63
67
  * sync a call to Drive api to stream a download
@@ -71,21 +75,28 @@ const register = (id, cacher, result, allow404 = false, params) => {
71
75
  * @param {object} [p.params] any extra params
72
76
  * @return {import('./sxdrive.js').SxResult} from the drive api
73
77
  */
74
- const fxStreamUpMedia = ({ file = {}, blob, fields = "", method = "create", fileId, params = {} }) => {
78
+ const fxStreamUpMedia = ({
79
+ file = {},
80
+ blob,
81
+ fields = "",
82
+ method = "create",
83
+ fileId,
84
+ params = {},
85
+ }) => {
75
86
  // merge the required fields with the minimum
76
- fields = mergeParamStrings(minFields, fields)
77
- const result = callSync('sxStreamUpMedia', {
87
+ fields = mergeParamStrings(minFields, fields);
88
+ const result = callSync("sxStreamUpMedia", {
78
89
  resource: file,
79
90
  bytes: blob ? blob.getBytes() : null,
80
91
  fields,
81
92
  method,
82
93
  mimeType: file.mimeType || blob?.getContentType(),
83
94
  fileId,
84
- params
85
- })
95
+ params,
96
+ });
86
97
  // check result and register in cache
87
- return registerSx(result, false, fields)
88
- }
98
+ return registerSx(result, false, fields);
99
+ };
89
100
 
90
101
  /**
91
102
  * sync a call to Drive api
@@ -96,29 +107,37 @@ const fxStreamUpMedia = ({ file = {}, blob, fields = "", method = "create", file
96
107
  * @return {DriveResponse} from the drive api
97
108
  */
98
109
  const fxDrive = ({ prop, method, params, options }) => {
99
- return callSync('sxDrive', {
110
+ return callSync("sxDrive", {
100
111
  prop,
101
112
  method,
102
113
  params: normalizeSerialization(params),
103
- options: normalizeSerialization(options)
114
+ options: normalizeSerialization(options),
104
115
  });
105
- }
116
+ };
106
117
 
107
- const fxGeneric = ({ serviceName, prop, subProp, method, params, options, cacher, idField }) => {
118
+ const fxGeneric = ({
119
+ serviceName,
120
+ prop,
121
+ subProp,
122
+ method,
123
+ params,
124
+ options,
125
+ cacher,
126
+ idField,
127
+ }) => {
108
128
  const { [idField]: resourceId, ...otherParams } = params;
109
129
 
110
- if (method === 'get') {
130
+ if (method === "get") {
111
131
  const data = cacher.getEntry(resourceId, otherParams);
112
132
  if (data) {
113
133
  return {
114
134
  data,
115
135
  response: {
116
136
  status: 200,
117
- fromCache: true
118
- }
119
- }
137
+ fromCache: true,
138
+ },
139
+ };
120
140
  }
121
-
122
141
  }
123
142
 
124
143
  const result = callSync(`sx${serviceName}`, {
@@ -126,20 +145,18 @@ const fxGeneric = ({ serviceName, prop, subProp, method, params, options, cacher
126
145
  prop,
127
146
  method,
128
147
  params: normalizeSerialization(params),
129
- options: normalizeSerialization(options)
130
- })
148
+ options: normalizeSerialization(options),
149
+ });
131
150
 
132
- if (method === 'get') {
133
- return register(resourceId, cacher, result, false, otherParams)
151
+ if (method === "get") {
152
+ return register(resourceId, cacher, result, false, otherParams);
134
153
  }
135
154
 
136
155
  if (resourceId) {
137
- cacher.clear(resourceId)
156
+ cacher.clear(resourceId);
138
157
  }
139
- return result
140
- }
141
-
142
-
158
+ return result;
159
+ };
143
160
 
144
161
  /**
145
162
  * sync a call to Drive api get
@@ -150,38 +167,43 @@ const fxGeneric = ({ serviceName, prop, subProp, method, params, options, cacher
150
167
  * @param {object} p.params the params to add to the request
151
168
  * @return {DriveResponse} from the drive api
152
169
  */
153
- const fxDriveGet = ({ id, params, allow404 = false, allowCache = true, options }) => {
154
-
170
+ const fxDriveGet = ({
171
+ id,
172
+ params,
173
+ allow404 = false,
174
+ allowCache = true,
175
+ options,
176
+ }) => {
155
177
  // fixup the fields param
156
178
  // we'll fiddle with the scopes to populate cache
157
- params.fields = mergeParamStrings(minFields, params.fields || "")
158
- params.fileId = id
179
+ params.fields = mergeParamStrings(minFields, params.fields || "");
180
+ params.fileId = id;
159
181
 
160
182
  // now we check if it's in cache and already has the necessary fields
161
183
  // the cache will check the fields it already has against those requested
162
184
  if (allowCache) {
163
- const { cachedFile, good } = getFromFileCache(id, params.fields)
164
- if (good) return {
165
-
166
- data: cachedFile,
167
- // fake a good sxresponse
168
- response: {
169
- status: 200,
170
- fromCache: true
171
- }
172
- }
185
+ const { cachedFile, good } = getFromFileCache(id, params.fields);
186
+ if (good)
187
+ return {
188
+ data: cachedFile,
189
+ // fake a good sxresponse
190
+ response: {
191
+ status: 200,
192
+ fromCache: true,
193
+ },
194
+ };
173
195
  }
174
196
 
175
197
  // so we have to hit the API
176
- const result = callSync('sxDriveGet', {
198
+ const result = callSync("sxDriveGet", {
177
199
  id,
178
200
  params: normalizeSerialization(params),
179
- options: normalizeSerialization(options)
201
+ options: normalizeSerialization(options),
180
202
  });
181
203
 
182
204
  // check result and register in cache
183
- return registerSx(result, allow404, params.fields)
184
- }
205
+ return registerSx(result, allow404, params.fields);
206
+ };
185
207
 
186
208
  /**
187
209
  * zipper
@@ -190,26 +212,24 @@ const fxDriveGet = ({ id, params, allow404 = false, allowCache = true, options }
190
212
  * @returns {FakeBlob} a combined zip file
191
213
  */
192
214
  const fxZipper = ({ blobs }) => {
193
-
194
- const dupCheck = new Set()
215
+ const dupCheck = new Set();
195
216
  const blobsContent = blobs.map((f, i) => {
196
- const ext = mime.getExtension(f.getContentType())
197
- const name = f.getName() || `Untitled${i + 1}${ext ? "." + ext : ""}`
217
+ const ext = mime.getExtension(f.getContentType());
218
+ const name = f.getName() || `Untitled${i + 1}${ext ? "." + ext : ""}`;
198
219
  if (dupCheck.has(name)) {
199
- throw new Error(`Duplicate filename ${name} not allowed in zip`)
220
+ throw new Error(`Duplicate filename ${name} not allowed in zip`);
200
221
  }
201
- dupCheck.add(name)
222
+ dupCheck.add(name);
202
223
  return {
203
224
  name,
204
- bytes: f.getBytes()
205
- }
206
- })
207
-
208
- return callSync('sxZipper', {
209
- blobsContent
210
- })
225
+ bytes: f.getBytes(),
226
+ };
227
+ });
211
228
 
212
- }
229
+ return callSync("sxZipper", {
230
+ blobsContent,
231
+ });
232
+ };
213
233
 
214
234
  /**
215
235
  * Unzipper
@@ -218,16 +238,15 @@ const fxZipper = ({ blobs }) => {
218
238
  * @returns {FakeBlob[]} each of the files unzipped
219
239
  */
220
240
  const fxUnzipper = ({ blob }) => {
221
-
222
241
  const blobContent = {
223
242
  name: blob.getName(),
224
- bytes: blob.getBytes()
225
- }
243
+ bytes: blob.getBytes(),
244
+ };
226
245
 
227
- return callSync('sxUnzipper', {
228
- blobContent
229
- })
230
- }
246
+ return callSync("sxUnzipper", {
247
+ blobContent,
248
+ });
249
+ };
231
250
 
232
251
  /**
233
252
  * initialize all the stuff at the beginning such as manifest content and settings
@@ -238,29 +257,28 @@ const fxUnzipper = ({ blob }) => {
238
257
  * @param {string} p.settingsPath where to find the settings file
239
258
  * @param {string} p.cachePath the cache files
240
259
  * @param {string} p.propertiesPath the properties file location
241
- * @return {object} the finalized vesions of all the above
260
+ * @return {object} the finalized vesions of all the above
242
261
  */
243
262
  const fxInit = ({
244
263
  manifestPath = manifestDefaultPath,
245
264
  claspPath = claspDefaultPath,
246
265
  settingsPath = settingsDefaultPath,
247
266
  cachePath = cacheDefaultPath,
248
- propertiesPath = propertiesDefaultPath
267
+ propertiesPath = propertiesDefaultPath,
249
268
  } = {}) => {
250
-
251
269
  // this is the path of the runing main process
252
- const mainDir = path.dirname(process.argv[1])
270
+ const mainDir = path.dirname(process.argv[1]);
253
271
 
254
272
  // because this is all run in a synced subprocess it's not an async result
255
- const synced = callSync('sxInit', {
273
+ const synced = callSync("sxInit", {
256
274
  claspPath,
257
275
  settingsPath,
258
276
  manifestPath,
259
277
  mainDir,
260
278
  cachePath,
261
279
  propertiesPath,
262
- fakeId: randomUUID()
263
- })
280
+ fakeId: randomUUID(),
281
+ });
264
282
 
265
283
  const {
266
284
  scopes,
@@ -270,24 +288,20 @@ const fxInit = ({
270
288
  accessToken,
271
289
  settings,
272
290
  manifest,
273
- clasp
274
- } = synced
291
+ clasp,
292
+ } = synced;
275
293
 
276
294
  // set these values from the subprocess for the main project
277
- Auth.setProjectId(projectId)
295
+ Auth.setProjectId(projectId);
278
296
  //Auth.setAuth(scopes)
279
- Auth.setTokenInfo(tokenInfo)
297
+ Auth.setTokenInfo(tokenInfo);
280
298
  //Auth.setAdcPath(adcPath)
281
299
  //Auth.setAccessToken(accessToken)
282
- Auth.setSettings(settings)
283
- Auth.setClasp(clasp)
284
- Auth.setManifest(manifest)
285
- return synced
286
-
287
- }
288
-
289
-
290
-
300
+ Auth.setSettings(settings);
301
+ Auth.setClasp(clasp);
302
+ Auth.setManifest(manifest);
303
+ return synced;
304
+ };
291
305
 
292
306
  /**
293
307
  * because we're using a file backed cache we need to syncit
@@ -297,21 +311,17 @@ const fxInit = ({
297
311
  * @returns {*}
298
312
  */
299
313
  const fxStore = (storeArgs, method = "get", ...kvArgs) => {
300
-
301
- return callSync('sxStore', {
314
+ return callSync("sxStore", {
302
315
  method,
303
316
  kvArgs,
304
- storeArgs
305
- })
306
- }
307
-
317
+ storeArgs,
318
+ });
319
+ };
308
320
 
309
321
  const fxRefreshToken = () => {
310
-
311
- return callSync('sxRefreshToken');
322
+ return callSync("sxRefreshToken");
312
323
  };
313
324
 
314
-
315
325
  /**
316
326
  * sync a call to Drive api to stream a download
317
327
  * @param {object} p pargs
@@ -321,14 +331,10 @@ const fxRefreshToken = () => {
321
331
  * @return {DriveResponse} from the drive api
322
332
  */
323
333
  const fxDriveMedia = ({ id }) => {
324
-
325
- return callSync('sxDriveMedia', {
326
- id
334
+ return callSync("sxDriveMedia", {
335
+ id,
327
336
  });
328
- }
329
-
330
-
331
-
337
+ };
332
338
 
333
339
  /**
334
340
  * a sync version of fetching
@@ -338,15 +344,46 @@ const fxDriveMedia = ({ id }) => {
338
344
  * @returns {reponse} urlfetch style reponse
339
345
  */
340
346
  const fxFetch = (url, options, responseFields) => {
347
+ return callSync("sxFetch", url, options, responseFields);
348
+ };
341
349
 
342
- return callSync('sxFetch', url, options, responseFields);
343
- }
350
+ const fxSheets = (args) =>
351
+ fxGeneric({
352
+ ...args,
353
+ serviceName: "Sheets",
354
+ cacher: sheetsCacher,
355
+ idField: "spreadsheetId",
356
+ });
357
+ const fxSlides = (args) =>
358
+ fxGeneric({
359
+ ...args,
360
+ serviceName: "Slides",
361
+ cacher: slidesCacher,
362
+ idField: "presentationId",
363
+ });
364
+ const fxDocs = (args) =>
365
+ fxGeneric({
366
+ ...args,
367
+ serviceName: "Docs",
368
+ cacher: docsCacher,
369
+ idField: "documentId",
370
+ });
371
+ const fxForms = (args) =>
372
+ fxGeneric({
373
+ ...args,
374
+ serviceName: "Forms",
375
+ cacher: formsCacher,
376
+ idField: "formId",
377
+ });
378
+ const fxGmail = (args) =>
379
+ fxGeneric({
380
+ ...args,
381
+ serviceName: "Gmail",
382
+ cacher: gmailCacher,
383
+ idField: "id",
384
+ });
344
385
 
345
- const fxSheets = (args) => fxGeneric({ ...args, serviceName: 'Sheets', cacher: sheetsCacher, idField: 'spreadsheetId' });
346
- const fxSlides = (args) => fxGeneric({ ...args, serviceName: 'Slides', cacher: slidesCacher, idField: 'presentationId' });
347
- const fxDocs = (args) => fxGeneric({ ...args, serviceName: 'Docs', cacher: docsCacher, idField: 'documentId' });
348
- const fxForms = (args) => fxGeneric({ ...args, serviceName: 'Forms', cacher: formsCacher, idField: 'formId' });
349
- const fxGmail = (args) => fxGeneric({ ...args, serviceName: 'Gmail', cacher: gmailCacher, idField: 'id' });
386
+ const fxGetImagesFromXlsx = (args) => callSync("sxGetImagesFromXlsx", args);
350
387
 
351
388
  export const Syncit = {
352
389
  fxFetch,
@@ -364,4 +401,5 @@ export const Syncit = {
364
401
  fxDocs,
365
402
  fxForms,
366
403
  fxGmail,
367
- }
404
+ fxGetImagesFromXlsx,
405
+ };
@@ -1,10 +1,11 @@
1
- export * from '../sxdrive.js';
2
- export * from '../sxsheets.js';
3
- export * from '../sxdocs.js';
4
- export * from '../sxslides.js';
5
- export * from '../sxforms.js';
6
- export * from '../sxfetch.js';
7
- export * from '../sxstore.js';
8
- export * from '../sxzip.js';
9
- export * from '../sxauth.js';
10
- export * from '../sxgmail.js';
1
+ export * from "../sxdrive.js";
2
+ export * from "../sxsheets.js";
3
+ export * from "../sxdocs.js";
4
+ export * from "../sxslides.js";
5
+ export * from "../sxforms.js";
6
+ export * from "../sxfetch.js";
7
+ export * from "../sxstore.js";
8
+ export * from "../sxzip.js";
9
+ export * from "../sxauth.js";
10
+ export * from "../sxgmail.js";
11
+ export * from "../sxxlsx.js";
package/togas.bash CHANGED
@@ -24,41 +24,10 @@ cp ${SOURCE}/test*.js ${TARGET}/test
24
24
 
25
25
 
26
26
  # find all the copied files and comment/fixes out import and export statements
27
- # note - this simple version naively expects that to be on 1 line
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 } }' {} +
30
- # sed -i 's/^import\s\s*/\/\/import /g' $(find "${TARGET}" -name "${EXT}" -type f)
31
- #sed -i 's/^\s*export\s\s*//g' $(find "${TARGET}" -name "${EXT}" -type f)
32
-
33
-
34
- # Perl works consistently across platforms
27
+ # Perl should work across platforms
35
28
  find "${TARGET}" -name "${EXT}" -type f -exec perl -i -pe 's/^\s*export\s\s*//g' {} \;
36
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 } }' {} +
37
- # sed -i 's/^import\s\s*/\/\/import /g' $(find "${TARGET}" -name "${EXT}" -type f)
38
- # replace all process.env.VAR_NAME occurrences with actual value
39
- # process.env is not usable in apps script
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\.//'))
44
-
45
- for var in "${vars[@]}"; do
46
-
47
- value=$(printenv "$var") # Get the environment variable value
48
-
49
- # Escape characters for sed, e.g. \n becomes \\n, & becomes \&
50
- value=$(printf '%q' "$value")
51
-
52
- # Check if the value contains non-numeric characters (treat as a string)
53
- if [[ "$value" =~ [^0-9] ]]; then
54
- value="\"$value\"" # Add double quotes
55
- fi
56
30
 
57
- # Replace process.env.VARIABLE_NAME with the actual value
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"
61
- done
62
31
 
63
32
  # now go to the target and push and open if required
64
33
  if [ "$CLASP" = true ] ; then