@google/clasp 2.5.0 → 3.0.0-alpha1

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 (149) hide show
  1. package/README.md +251 -196
  2. package/build/src/auth/auth.js +176 -0
  3. package/build/src/auth/auth_code_flow.js +36 -0
  4. package/build/src/auth/credential_store.js +1 -0
  5. package/build/src/auth/file_credential_store.js +82 -0
  6. package/build/src/auth/localhost_auth_code_flow.js +62 -0
  7. package/build/src/auth/serverless_auth_code_flow.js +32 -0
  8. package/build/src/commands/clone-script.js +71 -0
  9. package/build/src/commands/create-deployment.js +33 -0
  10. package/build/src/commands/create-script.js +75 -0
  11. package/build/src/commands/create-version.js +31 -0
  12. package/build/src/commands/delete-deployment.js +71 -0
  13. package/build/src/commands/disable-api.js +19 -0
  14. package/build/src/commands/enable-api.js +31 -0
  15. package/build/src/commands/list-apis.js +23 -0
  16. package/build/src/commands/list-deployments.js +30 -0
  17. package/build/src/commands/list-scripts.js +28 -0
  18. package/build/src/commands/list-versions.js +29 -0
  19. package/build/src/commands/login.js +53 -54
  20. package/build/src/commands/logout.js +15 -15
  21. package/build/src/commands/open-apis.js +11 -0
  22. package/build/src/commands/open-container.js +15 -0
  23. package/build/src/commands/open-credentials.js +11 -0
  24. package/build/src/commands/open-logs.js +11 -0
  25. package/build/src/commands/open-script.js +18 -0
  26. package/build/src/commands/open-webapp.js +56 -0
  27. package/build/src/commands/program.js +108 -0
  28. package/build/src/commands/pull.js +19 -18
  29. package/build/src/commands/push.js +64 -74
  30. package/build/src/commands/run-function.js +61 -0
  31. package/build/src/commands/setup-logs.js +12 -0
  32. package/build/src/commands/show-authorized-user.js +18 -0
  33. package/build/src/commands/show-file-status.js +34 -0
  34. package/build/src/commands/tail-logs.js +92 -0
  35. package/build/src/commands/utils.js +82 -0
  36. package/build/src/constants.js +0 -3
  37. package/build/src/{apis.js → core/apis.js} +90 -92
  38. package/build/src/core/clasp.js +171 -0
  39. package/build/src/core/files.js +359 -0
  40. package/build/src/core/functions.js +51 -0
  41. package/build/src/core/logs.js +41 -0
  42. package/build/src/core/manifest.js +1 -0
  43. package/build/src/core/project.js +313 -0
  44. package/build/src/core/services.js +179 -0
  45. package/build/src/core/utils.js +121 -0
  46. package/build/src/index.js +16 -355
  47. package/build/src/intl.js +34 -0
  48. package/docs/README.md +0 -5
  49. package/docs/config-files.md +0 -1
  50. package/docs/run.md +2 -2
  51. package/package.json +86 -51
  52. package/CHANGELOG.md +0 -79
  53. package/build/src/apis.d.ts +0 -34
  54. package/build/src/apis.js.map +0 -1
  55. package/build/src/apiutils.d.ts +0 -16
  56. package/build/src/apiutils.js +0 -81
  57. package/build/src/apiutils.js.map +0 -1
  58. package/build/src/auth.d.ts +0 -37
  59. package/build/src/auth.js +0 -310
  60. package/build/src/auth.js.map +0 -1
  61. package/build/src/clasp-error.d.ts +0 -3
  62. package/build/src/clasp-error.js +0 -10
  63. package/build/src/clasp-error.js.map +0 -1
  64. package/build/src/commands/apis.d.ts +0 -10
  65. package/build/src/commands/apis.js +0 -90
  66. package/build/src/commands/apis.js.map +0 -1
  67. package/build/src/commands/clone.d.ts +0 -13
  68. package/build/src/commands/clone.js +0 -60
  69. package/build/src/commands/clone.js.map +0 -1
  70. package/build/src/commands/create.d.ts +0 -16
  71. package/build/src/commands/create.js +0 -81
  72. package/build/src/commands/create.js.map +0 -1
  73. package/build/src/commands/default.d.ts +0 -8
  74. package/build/src/commands/default.js +0 -10
  75. package/build/src/commands/default.js.map +0 -1
  76. package/build/src/commands/deploy.d.ts +0 -13
  77. package/build/src/commands/deploy.js +0 -51
  78. package/build/src/commands/deploy.js.map +0 -1
  79. package/build/src/commands/deployments.d.ts +0 -5
  80. package/build/src/commands/deployments.js +0 -29
  81. package/build/src/commands/deployments.js.map +0 -1
  82. package/build/src/commands/list.d.ts +0 -9
  83. package/build/src/commands/list.js +0 -34
  84. package/build/src/commands/list.js.map +0 -1
  85. package/build/src/commands/login.d.ts +0 -15
  86. package/build/src/commands/login.js.map +0 -1
  87. package/build/src/commands/logout.d.ts +0 -5
  88. package/build/src/commands/logout.js.map +0 -1
  89. package/build/src/commands/logs.d.ts +0 -17
  90. package/build/src/commands/logs.js +0 -181
  91. package/build/src/commands/logs.js.map +0 -1
  92. package/build/src/commands/open.d.ts +0 -15
  93. package/build/src/commands/open.js +0 -89
  94. package/build/src/commands/open.js.map +0 -1
  95. package/build/src/commands/pull.d.ts +0 -10
  96. package/build/src/commands/pull.js.map +0 -1
  97. package/build/src/commands/push.d.ts +0 -11
  98. package/build/src/commands/push.js.map +0 -1
  99. package/build/src/commands/run.d.ts +0 -14
  100. package/build/src/commands/run.js +0 -130
  101. package/build/src/commands/run.js.map +0 -1
  102. package/build/src/commands/setting.d.ts +0 -8
  103. package/build/src/commands/setting.js +0 -53
  104. package/build/src/commands/setting.js.map +0 -1
  105. package/build/src/commands/status.d.ts +0 -9
  106. package/build/src/commands/status.js +0 -25
  107. package/build/src/commands/status.js.map +0 -1
  108. package/build/src/commands/undeploy.d.ts +0 -9
  109. package/build/src/commands/undeploy.js +0 -55
  110. package/build/src/commands/undeploy.js.map +0 -1
  111. package/build/src/commands/version.d.ts +0 -5
  112. package/build/src/commands/version.js +0 -22
  113. package/build/src/commands/version.js.map +0 -1
  114. package/build/src/commands/versions.d.ts +0 -5
  115. package/build/src/commands/versions.js +0 -41
  116. package/build/src/commands/versions.js.map +0 -1
  117. package/build/src/conf.d.ts +0 -40
  118. package/build/src/conf.js +0 -100
  119. package/build/src/conf.js.map +0 -1
  120. package/build/src/constants.d.ts +0 -6
  121. package/build/src/constants.js.map +0 -1
  122. package/build/src/dotfile.d.ts +0 -50
  123. package/build/src/dotfile.js +0 -71
  124. package/build/src/dotfile.js.map +0 -1
  125. package/build/src/files.d.ts +0 -70
  126. package/build/src/files.js +0 -364
  127. package/build/src/files.js.map +0 -1
  128. package/build/src/index.d.ts +0 -18
  129. package/build/src/index.js.map +0 -1
  130. package/build/src/inquirer.d.ts +0 -82
  131. package/build/src/inquirer.js +0 -111
  132. package/build/src/inquirer.js.map +0 -1
  133. package/build/src/manifest.d.ts +0 -123
  134. package/build/src/manifest.js +0 -142
  135. package/build/src/manifest.js.map +0 -1
  136. package/build/src/messages.d.ts +0 -110
  137. package/build/src/messages.js +0 -161
  138. package/build/src/messages.js.map +0 -1
  139. package/build/src/urls.d.ts +0 -21
  140. package/build/src/urls.js +0 -33
  141. package/build/src/urls.js.map +0 -1
  142. package/build/src/utils.d.ts +0 -102
  143. package/build/src/utils.js +0 -232
  144. package/build/src/utils.js.map +0 -1
  145. package/docs/develop.md +0 -94
  146. package/docs/esmodules.md +0 -81
  147. package/docs/running-locally.md +0 -31
  148. package/docs/settings.md +0 -56
  149. package/docs/typescript.md +0 -354
@@ -0,0 +1,359 @@
1
+ import path from 'path';
2
+ import chalk from 'chalk';
3
+ import chokidar from 'chokidar';
4
+ import Debug from 'debug';
5
+ import { fdir } from 'fdir';
6
+ import fs from 'fs/promises';
7
+ import { google } from 'googleapis';
8
+ import { GaxiosError } from 'googleapis-common';
9
+ import micromatch from 'micromatch';
10
+ import normalizePath from 'normalize-path';
11
+ import pMap from 'p-map';
12
+ import { assertAuthenticated, assertScriptConfigured, handleApiError } from './utils.js';
13
+ const debug = Debug('clasp:core');
14
+ function parentDirs(file) {
15
+ const parentDirs = [];
16
+ let currentDir = path.dirname(file);
17
+ while (currentDir !== '.') {
18
+ parentDirs.push(currentDir);
19
+ currentDir = path.dirname(currentDir);
20
+ }
21
+ return parentDirs;
22
+ }
23
+ async function getLocalFiles(rootDir, ignorePatterns, recursive) {
24
+ debug('Collecting files in %s', rootDir);
25
+ let fdirBuilder = new fdir().withBasePath().withRelativePaths();
26
+ if (!recursive) {
27
+ debug('Not recursive, limiting depth to current directory');
28
+ fdirBuilder = fdirBuilder.withMaxDepth(0);
29
+ }
30
+ const files = await fdirBuilder.crawl(rootDir).withPromise();
31
+ const filteredFiles = micromatch.not(files, ignorePatterns, { dot: true });
32
+ debug('Filtered %d files from ignore rules', files.length - filteredFiles.length);
33
+ filteredFiles.sort((a, b) => a.localeCompare(b));
34
+ return filteredFiles[Symbol.iterator]();
35
+ }
36
+ async function getUnfilteredLocalFiles(rootDir) {
37
+ debug('Collecting files in %s', rootDir);
38
+ const fdirBuilder = new fdir().withBasePath();
39
+ const files = await fdirBuilder.crawl(rootDir).withPromise();
40
+ files.sort((a, b) => a.localeCompare(b));
41
+ return files[Symbol.iterator]();
42
+ }
43
+ function createFilenameConflictChecker() {
44
+ const files = new Set();
45
+ return (file) => {
46
+ if (file.type !== 'SERVER_JS') {
47
+ return file;
48
+ }
49
+ const parsedPath = path.parse(file.localPath);
50
+ const key = path.format({ dir: parsedPath.dir, name: parsedPath.name });
51
+ if (files.has(key)) {
52
+ throw new Error('Conflicting files found', {
53
+ cause: {
54
+ code: 'FILE_CONFLICT',
55
+ value: key,
56
+ },
57
+ });
58
+ }
59
+ return file;
60
+ };
61
+ }
62
+ function getFileType(fileName) {
63
+ const extension = path.extname(fileName).toUpperCase();
64
+ if (['.GS', '.JS'].includes(extension)) {
65
+ return 'SERVER_JS';
66
+ }
67
+ if (extension === '.JSON' && path.basename(fileName) === 'appsscript.json') {
68
+ return 'JSON';
69
+ }
70
+ if (extension === '.HTML') {
71
+ return 'HTML';
72
+ }
73
+ return undefined;
74
+ }
75
+ function getFileExtension(type) {
76
+ // TODO - Include project setting override
77
+ switch (type) {
78
+ case 'SERVER_JS':
79
+ return 'js';
80
+ case 'JSON':
81
+ return 'json';
82
+ case 'HTML':
83
+ return 'html';
84
+ default:
85
+ throw new Error('Invalid file type', {
86
+ cause: {
87
+ code: 'INVALID_FILE_TYPE',
88
+ value: type,
89
+ },
90
+ });
91
+ }
92
+ }
93
+ function debounceFileChanges(callback, delayMs) {
94
+ let timeoutId;
95
+ let collectedPaths = [];
96
+ return function (path) {
97
+ // Already tracked as changed, ignore
98
+ if (collectedPaths.includes(path)) {
99
+ return;
100
+ }
101
+ collectedPaths.push(path);
102
+ clearTimeout(timeoutId);
103
+ timeoutId = setTimeout(() => {
104
+ callback(collectedPaths);
105
+ collectedPaths = [];
106
+ }, delayMs);
107
+ };
108
+ }
109
+ export class Files {
110
+ constructor(options) {
111
+ this.options = options;
112
+ }
113
+ async fetchRemote(versionNumber) {
114
+ var _a;
115
+ debug('Fetching remote files, version %s', versionNumber !== null && versionNumber !== void 0 ? versionNumber : 'HEAD');
116
+ assertAuthenticated(this.options);
117
+ assertScriptConfigured(this.options);
118
+ const credentials = this.options.credentials;
119
+ const contentDir = this.options.files.contentDir;
120
+ const scriptId = this.options.project.scriptId;
121
+ const script = google.script({ version: 'v1', auth: credentials });
122
+ try {
123
+ const requestOptions = { scriptId, versionNumber };
124
+ debug('Fetchign script content, request %o', requestOptions);
125
+ const response = await script.projects.getContent(requestOptions);
126
+ const files = (_a = response.data.files) !== null && _a !== void 0 ? _a : [];
127
+ return files.map(f => {
128
+ var _a, _b, _c;
129
+ const ext = getFileExtension(f.type);
130
+ const localPath = path.relative(process.cwd(), path.resolve(contentDir, `${f.name}.${ext}`));
131
+ const file = {
132
+ localPath: localPath,
133
+ remotePath: (_a = f.name) !== null && _a !== void 0 ? _a : undefined,
134
+ source: (_b = f.source) !== null && _b !== void 0 ? _b : undefined,
135
+ type: (_c = f.type) !== null && _c !== void 0 ? _c : undefined,
136
+ };
137
+ debug('Fetched file %O', file);
138
+ return file;
139
+ });
140
+ }
141
+ catch (error) {
142
+ handleApiError(error);
143
+ }
144
+ }
145
+ async collectLocalFiles() {
146
+ var _a;
147
+ debug('Collecting local files');
148
+ assertScriptConfigured(this.options);
149
+ const contentDir = this.options.files.contentDir;
150
+ const ignorePatterns = (_a = this.options.files.ignorePatterns) !== null && _a !== void 0 ? _a : [];
151
+ const recursive = this.options.files.ignoreFilePath !== undefined;
152
+ // Read all filenames as a flattened tree
153
+ // Note: filePaths contain relative paths such as "test/bar.ts", "../../src/foo.js"
154
+ const filelist = await getLocalFiles(contentDir, ignorePatterns, recursive);
155
+ const checkDuplicate = createFilenameConflictChecker();
156
+ const files = await Promise.all(filelist.map(async (filename) => {
157
+ const localPath = path.relative(process.cwd(), path.join(contentDir, filename));
158
+ const resolvedPath = path.relative(contentDir, localPath);
159
+ const parsedPath = path.parse(resolvedPath);
160
+ let remotePath = path.format({ dir: normalizePath(parsedPath.dir), name: parsedPath.name });
161
+ const type = getFileType(localPath);
162
+ if (!type) {
163
+ debug('Ignoring unsupported file %s', localPath);
164
+ return undefined;
165
+ }
166
+ if (type === 'JSON' && path.basename(localPath) === 'appsscript.json') {
167
+ // Manifest has a fixed path in script
168
+ remotePath = 'appsscript';
169
+ }
170
+ const content = await fs.readFile(localPath);
171
+ const source = content.toString();
172
+ return checkDuplicate({ localPath, remotePath, source, type });
173
+ }));
174
+ return files.filter((f) => f !== undefined);
175
+ }
176
+ watchLocalFiles(onReady, onFilesChanged) {
177
+ var _a;
178
+ const ignorePatterns = (_a = this.options.files.ignorePatterns) !== null && _a !== void 0 ? _a : [];
179
+ const collector = debounceFileChanges(onFilesChanged, 500);
180
+ const onChange = async (path) => {
181
+ collector(path);
182
+ };
183
+ const watcher = chokidar.watch(this.options.files.contentDir, {
184
+ persistent: true,
185
+ ignoreInitial: true,
186
+ cwd: this.options.files.contentDir,
187
+ ignored: file => {
188
+ return micromatch.not([file], ignorePatterns, { dot: true }).length === 0;
189
+ },
190
+ });
191
+ watcher.on('ready', onReady); // Push on start
192
+ watcher.on('add', onChange);
193
+ watcher.on('change', onChange);
194
+ watcher.on('unlink', onChange);
195
+ return async () => await watcher.close();
196
+ }
197
+ async getChangedFiles() {
198
+ const [localFiles, remoteFiles] = await Promise.all([this.collectLocalFiles(), this.fetchRemote()]);
199
+ return localFiles.reduce((changed, localFile) => {
200
+ const remote = remoteFiles.find(f => f.localPath === localFile.localPath);
201
+ if (!remote || remote.source !== localFile.source) {
202
+ changed.push(localFile);
203
+ }
204
+ return changed;
205
+ }, []);
206
+ }
207
+ async getUntrackedFiles() {
208
+ debug('Collecting untracked files');
209
+ assertScriptConfigured(this.options);
210
+ const contentDir = this.options.files.contentDir;
211
+ const cwd = process.cwd();
212
+ const dirsWithIncludedFiles = new Set();
213
+ const trackedFiles = new Set();
214
+ const untrackedFiles = new Set();
215
+ const projectFiles = await this.collectLocalFiles();
216
+ for (const file of projectFiles) {
217
+ debug('Found tracked file %s', file.localPath);
218
+ trackedFiles.add(file.localPath);
219
+ // Save all parent paths to allow quick lookup.
220
+ // Allows collapsing the unfiltered files to the common parent directory
221
+ const dirs = parentDirs(file.localPath);
222
+ dirs.forEach(dir => dirsWithIncludedFiles.add(dir));
223
+ }
224
+ const allFiles = await getUnfilteredLocalFiles(contentDir);
225
+ for (const file of allFiles) {
226
+ const resolvedPath = path.relative(cwd, file);
227
+ if (trackedFiles.has(resolvedPath)) {
228
+ // Tracked file, skip
229
+ continue;
230
+ }
231
+ // Reduce path to nearest parent directory with no project files included
232
+ let excludedPath = resolvedPath;
233
+ for (const dir of parentDirs(resolvedPath)) {
234
+ if (dirsWithIncludedFiles.has(dir)) {
235
+ break;
236
+ }
237
+ excludedPath = `${dir}/`;
238
+ }
239
+ debug('Found untracked file %s', excludedPath);
240
+ untrackedFiles.add(excludedPath);
241
+ }
242
+ const untrackedFilesArray = Array.from(untrackedFiles);
243
+ untrackedFilesArray.sort((a, b) => a.localeCompare(b));
244
+ return untrackedFilesArray;
245
+ }
246
+ async push() {
247
+ var _a;
248
+ debug('Pushing files');
249
+ assertAuthenticated(this.options);
250
+ assertScriptConfigured(this.options);
251
+ const credentials = this.options.credentials;
252
+ const scriptId = this.options.project.scriptId;
253
+ const files = await this.collectLocalFiles();
254
+ if (!files || files.length === 0) {
255
+ debug('No files found to push.');
256
+ return [];
257
+ }
258
+ const filePushOrder = (_a = this.options.files.filePushOrder) !== null && _a !== void 0 ? _a : [];
259
+ files.sort((a, b) => {
260
+ const indexA = filePushOrder.indexOf(a.localPath);
261
+ const indexB = filePushOrder.indexOf(b.localPath);
262
+ if (indexA === -1 && indexB === -1) {
263
+ // Neither has explicit order, sort by name
264
+ return a.localPath.localeCompare(b.localPath);
265
+ }
266
+ if (indexA === -1) {
267
+ // B has explicit priority, is first
268
+ return 1;
269
+ }
270
+ if (indexB === -1) {
271
+ // A has explicit priority, is first
272
+ return -1;
273
+ }
274
+ // Both prioritized, use rank
275
+ return indexA - indexB;
276
+ });
277
+ // Start pushing.
278
+ try {
279
+ const scriptFiles = files.map(f => ({
280
+ name: f.remotePath,
281
+ type: f.type,
282
+ source: f.source,
283
+ }));
284
+ const script = google.script({ version: 'v1', auth: credentials });
285
+ const requestOptions = {
286
+ scriptId,
287
+ requestBody: {
288
+ files: scriptFiles,
289
+ },
290
+ };
291
+ debug('Updating content, request %O', requestOptions);
292
+ await script.projects.updateContent(requestOptions);
293
+ return files;
294
+ }
295
+ catch (error) {
296
+ debug(error);
297
+ if (error instanceof GaxiosError) {
298
+ const syntaxError = extractSyntaxError(error, files);
299
+ if (syntaxError) {
300
+ throw new Error(syntaxError.message, {
301
+ cause: {
302
+ code: 'SYNTAX_ERROR',
303
+ error: error,
304
+ snippet: syntaxError.snippet,
305
+ },
306
+ });
307
+ }
308
+ }
309
+ handleApiError(error);
310
+ }
311
+ }
312
+ async pull(version) {
313
+ debug('Pulling files');
314
+ assertAuthenticated(this.options);
315
+ assertScriptConfigured(this.options);
316
+ const files = await this.fetchRemote(version);
317
+ await this.WriteFiles(files);
318
+ return files;
319
+ }
320
+ async WriteFiles(files) {
321
+ debug('Writing files');
322
+ const mapper = async (file) => {
323
+ debug('Write file %s', path.resolve(file.localPath));
324
+ if (!file.source) {
325
+ debug('Skipping empty file.');
326
+ return;
327
+ }
328
+ await fs.mkdir(path.dirname(file.localPath), { recursive: true });
329
+ await fs.writeFile(file.localPath, file.source);
330
+ };
331
+ return await pMap(files, mapper);
332
+ }
333
+ }
334
+ function extractSyntaxError(error, files) {
335
+ var _a;
336
+ let message = error.message;
337
+ let snippet = '';
338
+ const re = /Syntax error: (.+) line: (\d+) file: (.+)/;
339
+ const [, errorName, lineNum, fileName] = (_a = re.exec(error.message)) !== null && _a !== void 0 ? _a : [];
340
+ if (fileName === undefined) {
341
+ return undefined;
342
+ }
343
+ message = `${errorName} - "${fileName}:${lineNum}"`;
344
+ // Get formatted code snippet
345
+ const contextCount = 4;
346
+ const errFile = files.find((x) => x.remotePath === fileName);
347
+ if (!errFile || !errFile.source) {
348
+ return undefined;
349
+ }
350
+ const srcLines = errFile.source.split('\n');
351
+ const errIndex = Math.max(parseInt(lineNum) - 1, 0);
352
+ const preIndex = Math.max(errIndex - contextCount, 0);
353
+ const postIndex = Math.min(errIndex + contextCount + 1, srcLines.length);
354
+ const preLines = chalk.dim(` ${srcLines.slice(preIndex, errIndex).join('\n ')}`);
355
+ const errLine = chalk.bold(`⇒ ${srcLines[errIndex]}`);
356
+ const postLines = chalk.dim(` ${srcLines.slice(errIndex + 1, postIndex).join('\n ')}`);
357
+ snippet = preLines + '\n' + errLine + '\n' + postLines;
358
+ return { message, snippet };
359
+ }
@@ -0,0 +1,51 @@
1
+ import Debug from 'debug';
2
+ import { google } from 'googleapis';
3
+ import { assertAuthenticated, assertScriptConfigured, handleApiError } from './utils.js';
4
+ const debug = Debug('clasp:core');
5
+ export class Functions {
6
+ constructor(options) {
7
+ this.options = options;
8
+ }
9
+ async getFunctionNames() {
10
+ debug('Fetching runnable functions');
11
+ assertAuthenticated(this.options);
12
+ assertScriptConfigured(this.options);
13
+ const credentials = this.options.credentials;
14
+ const scriptId = this.options.project.scriptId;
15
+ const script = google.script({ version: 'v1', auth: credentials });
16
+ const res = await script.projects.getContent({ scriptId });
17
+ const files = res.data.files;
18
+ const functions = [];
19
+ if (!files) {
20
+ return functions;
21
+ }
22
+ return files.flatMap(file => { var _a, _b; return (_b = (_a = file.functionSet) === null || _a === void 0 ? void 0 : _a.values) !== null && _b !== void 0 ? _b : []; }).map(func => func.name);
23
+ }
24
+ async runFunction(functionName, parameters, devMode = true) {
25
+ debug('Running script function %s', functionName);
26
+ assertAuthenticated(this.options);
27
+ assertScriptConfigured(this.options);
28
+ const credentials = this.options.credentials;
29
+ const scriptId = this.options.project.scriptId;
30
+ const script = google.script({ version: 'v1', auth: credentials });
31
+ try {
32
+ const request = {
33
+ scriptId,
34
+ requestBody: {
35
+ function: functionName,
36
+ parameters: parameters !== null && parameters !== void 0 ? parameters : [],
37
+ devMode,
38
+ },
39
+ };
40
+ debug('Running function with request: %O', request);
41
+ const res = await script.scripts.run(request);
42
+ if (!res.data) {
43
+ throw new Error('Function returned undefined');
44
+ }
45
+ return res.data;
46
+ }
47
+ catch (error) {
48
+ handleApiError(error);
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,41 @@
1
+ import Debug from 'debug';
2
+ import { google } from 'googleapis';
3
+ import { fetchWithPages } from './utils.js';
4
+ import { assertAuthenticated, assertGcpProjectConfigured, handleApiError } from './utils.js';
5
+ const debug = Debug('clasp:core');
6
+ export class Logs {
7
+ constructor(options) {
8
+ this.options = options;
9
+ }
10
+ async getLogEntries(since) {
11
+ debug('Fetching logs');
12
+ assertAuthenticated(this.options);
13
+ assertGcpProjectConfigured(this.options);
14
+ const credentials = this.options.credentials;
15
+ const projectId = this.options.project.projectId;
16
+ const logger = google.logging({ version: 'v2', auth: credentials });
17
+ // Create a time filter (timestamp >= "2016-11-29T23:00:00Z")
18
+ // https://cloud.google.com/logging/docs/view/advanced-filters#search-by-time
19
+ const filter = since ? `timestamp >= "${since.toISOString()}"` : '';
20
+ try {
21
+ return fetchWithPages(async (pageSize, pageToken) => {
22
+ const res = await logger.entries.list({
23
+ requestBody: {
24
+ resourceNames: [`projects/${projectId}`],
25
+ filter,
26
+ orderBy: 'timestamp desc',
27
+ pageSize,
28
+ pageToken,
29
+ },
30
+ });
31
+ return {
32
+ results: res.data.entries || [],
33
+ nextPageToken: res.data.nextPageToken,
34
+ };
35
+ });
36
+ }
37
+ catch (error) {
38
+ handleApiError(error);
39
+ }
40
+ }
41
+ }
@@ -0,0 +1 @@
1
+ export {};