@google/clasp 2.5.0 → 3.0.1-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 +63 -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,71 @@
1
+ import { Command } from 'commander';
2
+ import inquirer from 'inquirer';
3
+ import { intl } from '../intl.js';
4
+ import { isInteractive, withSpinner } from './utils.js';
5
+ export const command = new Command('delete-deployment')
6
+ .alias('undeploy')
7
+ .description('Delete a deployment of a project')
8
+ .arguments('[deploymentId]')
9
+ .option('-a, --all', 'Undeploy all deployments')
10
+ .action(async function (deploymentId, options) {
11
+ var _a;
12
+ const clasp = this.opts().clasp;
13
+ const removeAll = options.all;
14
+ const deleteDeployment = async (id) => {
15
+ const spinnerMsg = intl.formatMessage({ id: "d6mKEK", defaultMessage: [{ type: 0, value: "Deleting deployment..." }] });
16
+ await withSpinner(spinnerMsg, async () => {
17
+ return await clasp.project.undeploy(id);
18
+ });
19
+ const successMessage = intl.formatMessage({ id: "GbtFER", defaultMessage: [{ type: 0, value: "Deleted deployment " }, { type: 1, value: "id" }] }, { id });
20
+ console.log(successMessage);
21
+ };
22
+ if (removeAll) {
23
+ const spinnerMsg = intl.formatMessage({ id: "baVdkq", defaultMessage: [{ type: 0, value: "Fetching deployments..." }] });
24
+ const deployments = await withSpinner(spinnerMsg, async () => {
25
+ return await clasp.project.listDeployments();
26
+ });
27
+ deployments.results = deployments.results.filter(deployment => { var _a; return ((_a = deployment.deploymentConfig) === null || _a === void 0 ? void 0 : _a.versionNumber) !== undefined; });
28
+ for (const deployment of deployments.results) {
29
+ const id = deployment.deploymentId;
30
+ if (!id) {
31
+ continue;
32
+ }
33
+ await deleteDeployment(id);
34
+ }
35
+ const successMessage = intl.formatMessage({ id: "cE8hF0", defaultMessage: [{ type: 0, value: "Deleted all deployments." }] });
36
+ console.log(successMessage);
37
+ return;
38
+ }
39
+ if (!deploymentId) {
40
+ const deployments = await clasp.project.listDeployments();
41
+ deployments.results = deployments.results.filter(deployment => { var _a; return ((_a = deployment.deploymentConfig) === null || _a === void 0 ? void 0 : _a.versionNumber) !== undefined; });
42
+ if (deployments.results.length === 1) {
43
+ deploymentId = (_a = deployments.results[0].deploymentId) !== null && _a !== void 0 ? _a : undefined;
44
+ }
45
+ else if (isInteractive()) {
46
+ const prompt = intl.formatMessage({ id: "LDbUYg", defaultMessage: [{ type: 0, value: "Delete which deployment?" }] });
47
+ const choices = deployments.results.map(deployment => {
48
+ var _a, _b;
49
+ return ({
50
+ name: `${deployment.deploymentId} - ${(_b = (_a = deployment.deploymentConfig) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : ''}`,
51
+ value: deployment.deploymentId,
52
+ });
53
+ });
54
+ const answer = await inquirer.prompt([
55
+ {
56
+ choices: choices,
57
+ message: prompt,
58
+ name: 'deploymentId',
59
+ pageSize: 30,
60
+ type: 'list',
61
+ },
62
+ ]);
63
+ deploymentId = answer.deploymentId;
64
+ }
65
+ }
66
+ if (!deploymentId) {
67
+ const msg = intl.formatMessage({ id: "UufukD", defaultMessage: [{ type: 0, value: "No deployments found." }] });
68
+ this.error(msg);
69
+ }
70
+ await deleteDeployment(deploymentId);
71
+ });
@@ -0,0 +1,19 @@
1
+ import { Command } from 'commander';
2
+ import { intl } from '../intl.js';
3
+ import { assertGcpProjectConfigured, maybePromptForProjectId, withSpinner } from './utils.js';
4
+ export const command = new Command('disable-api')
5
+ .description('Disable a service for the current project.')
6
+ .argument('<api>', 'Service to disable')
7
+ .action(async function (serviceName) {
8
+ const clasp = this.opts().clasp;
9
+ await maybePromptForProjectId(clasp);
10
+ assertGcpProjectConfigured(clasp);
11
+ const spinnerMsg = intl.formatMessage({ id: "awbyYM", defaultMessage: [{ type: 0, value: "Disabling service..." }] });
12
+ await withSpinner(spinnerMsg, async () => {
13
+ await clasp.services.disableService(serviceName);
14
+ });
15
+ const successMessage = intl.formatMessage({ id: "tjmJ+e", defaultMessage: [{ type: 0, value: "Disabled " }, { type: 1, value: "name" }, { type: 0, value: " API." }] }, {
16
+ name: serviceName,
17
+ });
18
+ console.log(successMessage);
19
+ });
@@ -0,0 +1,31 @@
1
+ import { Command } from 'commander';
2
+ import { intl } from '../intl.js';
3
+ import { assertGcpProjectConfigured, maybePromptForProjectId, withSpinner } from './utils.js';
4
+ export const command = new Command('enable-api')
5
+ .description('Enable a service for the current project.')
6
+ .argument('<api>', 'Service to enable')
7
+ .action(async function (serviceName) {
8
+ var _a;
9
+ const clasp = this.opts().clasp;
10
+ await maybePromptForProjectId(clasp);
11
+ assertGcpProjectConfigured(clasp);
12
+ try {
13
+ const spinnerMsg = intl.formatMessage({ id: "UqhzFn", defaultMessage: [{ type: 0, value: "Enabling service..." }] });
14
+ await withSpinner(spinnerMsg, async () => {
15
+ await clasp.services.enableService(serviceName);
16
+ });
17
+ }
18
+ catch (error) {
19
+ if (((_a = error.cause) === null || _a === void 0 ? void 0 : _a.code) === 'NOT_AUTHORIZED') {
20
+ const msg = intl.formatMessage({ id: "+y0rAf", defaultMessage: [{ type: 0, value: "Not authorized to enable " }, { type: 1, value: "name" }, { type: 0, value: " or it does not exist." }] }, {
21
+ name: serviceName,
22
+ });
23
+ this.error(msg);
24
+ }
25
+ throw error;
26
+ }
27
+ const successMessage = intl.formatMessage({ id: "6lXgOl", defaultMessage: [{ type: 0, value: "Enabled " }, { type: 1, value: "name" }, { type: 0, value: " API." }] }, {
28
+ name: serviceName,
29
+ });
30
+ console.log(successMessage);
31
+ });
@@ -0,0 +1,23 @@
1
+ import { Command } from 'commander';
2
+ import { intl } from '../intl.js';
3
+ import { assertGcpProjectConfigured, maybePromptForProjectId, withSpinner } from './utils.js';
4
+ export const command = new Command('list-apis')
5
+ .alias('apis')
6
+ .description('List enabled APIs for the current project')
7
+ .action(async function () {
8
+ const clasp = this.opts().clasp;
9
+ await maybePromptForProjectId(clasp);
10
+ assertGcpProjectConfigured(clasp);
11
+ const spinnerMsg = intl.formatMessage({ id: "aY+ZR2", defaultMessage: [{ type: 0, value: "Fetching APIs..." }] });
12
+ const [enabledApis, availableApis] = await withSpinner(spinnerMsg, () => Promise.all([clasp.services.getEnabledServices(), clasp.services.getAvailableServices()]));
13
+ const enabledApisLabel = intl.formatMessage({ id: "QfnjZ4", defaultMessage: [{ type: 0, value: "# Currently enabled APIs:" }] });
14
+ console.log(`\n${enabledApisLabel}`);
15
+ for (const service of enabledApis) {
16
+ console.log(`${service.name.padEnd(25)} - ${service.description.padEnd(60)}`);
17
+ }
18
+ const availableApisLabel = intl.formatMessage({ id: "qnV3uR", defaultMessage: [{ type: 0, value: "# List of available APIs:" }] });
19
+ console.log(`\n${availableApisLabel}`);
20
+ for (const service of availableApis) {
21
+ console.log(`${service.name.padEnd(25)} - ${service.description.padEnd(60)}`);
22
+ }
23
+ });
@@ -0,0 +1,30 @@
1
+ import { Command } from 'commander';
2
+ import { intl } from '../intl.js';
3
+ import { withSpinner } from './utils.js';
4
+ export const command = new Command('list-deployments')
5
+ .alias('deployments')
6
+ .description('List deployment ids of a script')
7
+ .action(async function () {
8
+ const clasp = this.opts().clasp;
9
+ const spinnerMsg = intl.formatMessage({ id: "baVdkq", defaultMessage: [{ type: 0, value: "Fetching deployments..." }] });
10
+ const deployments = await withSpinner(spinnerMsg, async () => {
11
+ return await clasp.project.listDeployments();
12
+ });
13
+ if (!deployments.results.length) {
14
+ const msg = intl.formatMessage({ id: "q2/XsW", defaultMessage: [{ type: 0, value: "No deployments." }] });
15
+ console.log(msg);
16
+ return;
17
+ }
18
+ const successMessage = intl.formatMessage({ id: "EJQ1WM", defaultMessage: [{ type: 0, value: "Found " }, { type: 6, value: "count", options: { one: { value: [{ type: 7 }, { type: 0, value: " deployment" }] }, other: { value: [{ type: 7 }, { type: 0, value: " deployments" }] } }, offset: 0, pluralType: "cardinal" }, { type: 0, value: "." }] }, {
19
+ count: deployments.results.length,
20
+ });
21
+ console.log(successMessage);
22
+ deployments.results
23
+ .filter(d => d.deploymentConfig && d.deploymentId)
24
+ .forEach(d => {
25
+ var _a, _b;
26
+ const versionString = ((_a = d.deploymentConfig) === null || _a === void 0 ? void 0 : _a.versionNumber) ? `@${d.deploymentConfig.versionNumber}` : '@HEAD';
27
+ const description = ((_b = d.deploymentConfig) === null || _b === void 0 ? void 0 : _b.description) ? `- ${d.deploymentConfig.description}` : '';
28
+ console.log(`- ${d.deploymentId} ${versionString} ${description}`);
29
+ });
30
+ });
@@ -0,0 +1,28 @@
1
+ import { Command } from 'commander';
2
+ import { intl } from '../intl.js';
3
+ import { ellipsize, withSpinner } from './utils.js';
4
+ export const command = new Command('list-scripts')
5
+ .alias('list')
6
+ .description('List App Scripts projects')
7
+ .option('--noShorten', 'Do not shorten long names', false)
8
+ .action(async function (options) {
9
+ const clasp = this.opts().clasp;
10
+ const spinnerMsg = intl.formatMessage({ id: "x0awdZ", defaultMessage: [{ type: 0, value: "Finding your scripts..." }] });
11
+ const files = await withSpinner(spinnerMsg, async () => {
12
+ return clasp.project.listScripts();
13
+ });
14
+ if (!files.results.length) {
15
+ const msg = intl.formatMessage({ id: "rPMgOk", defaultMessage: [{ type: 0, value: "No script files found." }] });
16
+ console.log(msg);
17
+ return;
18
+ }
19
+ const successMessage = intl.formatMessage({ id: "TBJtFJ", defaultMessage: [{ type: 0, value: "Found " }, { type: 6, value: "count", options: { one: { value: [{ type: 7 }, { type: 0, value: " script" }] }, other: { value: [{ type: 7 }, { type: 0, value: " scripts" }] } }, offset: 0, pluralType: "cardinal" }, { type: 0, value: "." }] }, {
20
+ count: files.results.length,
21
+ });
22
+ console.log(successMessage);
23
+ files.results.forEach(file => {
24
+ const name = options.noShorten ? file.name : ellipsize(file.name, 20);
25
+ const url = `https://script.google.com/d/${file.id}/edit`;
26
+ console.log(`${name} - ${url}`);
27
+ });
28
+ });
@@ -0,0 +1,29 @@
1
+ import { Command } from 'commander';
2
+ import { intl } from '../intl.js';
3
+ import { withSpinner } from './utils.js';
4
+ export const command = new Command('list-versions')
5
+ .alias('versions')
6
+ .description('List versions of a script')
7
+ .action(async function () {
8
+ const clasp = this.opts().clasp;
9
+ const spinnerMsg = intl.formatMessage({ id: "Cqxqh0", defaultMessage: [{ type: 0, value: "Fetching versions..." }] });
10
+ const versions = await withSpinner(spinnerMsg, async () => {
11
+ return await clasp.project.listVersions();
12
+ });
13
+ if (versions.results.length === 0) {
14
+ const msg = intl.formatMessage({ id: "Jmvq7L", defaultMessage: [{ type: 0, value: "No deployed versions of script." }] });
15
+ this.error(msg);
16
+ }
17
+ const successMessage = intl.formatMessage({ id: "6CS9SE", defaultMessage: [{ type: 0, value: "Found " }, { type: 6, value: "count", options: { one: { value: [{ type: 7 }, { type: 0, value: " version" }] }, other: { value: [{ type: 7 }, { type: 0, value: " versions" }] } }, offset: 0, pluralType: "cardinal" }, { type: 0, value: "." }] }, {
18
+ count: versions.results.length,
19
+ });
20
+ console.log(successMessage);
21
+ versions.results.reverse();
22
+ versions.results.forEach(version => {
23
+ const msg = intl.formatMessage({ id: "CAt8s3", defaultMessage: [{ type: 2, value: "version", style: null }, { type: 0, value: " - " }, { type: 5, value: "description", options: { undefined: { value: [{ type: 0, value: "No description" }] }, other: { value: [{ type: 1, value: "description" }] } } }] }, {
24
+ version: version.versionNumber,
25
+ description: version.description,
26
+ });
27
+ console.log(msg);
28
+ });
29
+ });
@@ -1,66 +1,65 @@
1
1
  /**
2
2
  * Clasp command method bodies.
3
3
  */
4
- import fs from 'fs-extra';
5
- import { enableAppsScriptAPI } from '../apiutils.js';
6
- import { authorize, defaultScopes, getLoggedInEmail, scopeWebAppDeploy } from '../auth.js';
7
- import { FS_OPTIONS } from '../constants.js';
8
- import { readManifest } from '../manifest.js';
9
- import { ERROR, LOG } from '../messages.js';
10
- import { hasOauthClientSettings, safeIsOnline } from '../utils.js';
11
- const { readJsonSync } = fs;
12
- /**
13
- * Logs the user in. Saves the client credentials to an either local or global rc file.
14
- * @param {object} options The login options.
15
- * @param {boolean?} options.localhost If true, authorizes without a HTTP server.
16
- * @param {string?} options.creds The location of credentials file.
17
- * @param {boolean?} options.status If true, prints who is logged in instead of doing login.
18
- */
19
- export default async (options) => {
20
- if (options.status) {
21
- if (hasOauthClientSettings()) {
22
- const email = (await safeIsOnline()) ? await getLoggedInEmail() : undefined;
23
- console.log(email ? LOG.LOGGED_IN_AS(email) : LOG.LOGGED_IN_UNKNOWN);
24
- }
25
- else {
26
- console.log(LOG.NOT_LOGGED_IN);
27
- }
28
- return;
29
- }
30
- // Local vs global checks
31
- const isLocalLogin = Boolean(options.creds);
32
- if (isLocalLogin && hasOauthClientSettings(true)) {
33
- console.error(ERROR.LOGGED_IN_LOCAL);
4
+ import { Command } from 'commander';
5
+ import { authorize, getUnauthorizedOuth2Client, getUserInfo } from '../auth/auth.js';
6
+ import { intl } from '../intl.js';
7
+ const DEFAULT_SCOPES = [
8
+ // Default to clasp scopes
9
+ 'https://www.googleapis.com/auth/script.deployments', // Apps Script deployments
10
+ 'https://www.googleapis.com/auth/script.projects', // Apps Script management
11
+ 'https://www.googleapis.com/auth/script.webapp.deploy', // Apps Script Web Apps
12
+ 'https://www.googleapis.com/auth/drive.metadata.readonly', // Drive metadata
13
+ 'https://www.googleapis.com/auth/drive.file', // Create Drive files
14
+ 'https://www.googleapis.com/auth/service.management', // Cloud Project Service Management API
15
+ 'https://www.googleapis.com/auth/logging.read', // StackDriver logs
16
+ 'https://www.googleapis.com/auth/userinfo.email', // User email address
17
+ 'https://www.googleapis.com/auth/userinfo.profile',
18
+ 'https://www.googleapis.com/auth/cloud-platform',
19
+ ];
20
+ export const command = new Command('login')
21
+ .description('Log in to script.google.com')
22
+ .option('--no-localhost', 'Do not run a local server, manually enter code instead')
23
+ .option('--creds <file>', 'Relative path to OAuth client secret file (from GCP).')
24
+ .option('--use-project-scopes', 'Use the scopes from the current project manifest. Used only when authorizing access for the run command.')
25
+ .option('--redirect-port <port>', 'Specify a custom port for the redirect URL.')
26
+ .action(async function (options) {
27
+ var _a;
28
+ const auth = this.opts().auth;
29
+ const clasp = this.opts().clasp;
30
+ if (!auth.credentialStore) {
31
+ const msg = intl.formatMessage({ id: "u1wQGD", defaultMessage: [{ type: 0, value: "No credential store found, unable to login." }] });
32
+ this.error(msg);
34
33
  }
35
- if (!isLocalLogin && hasOauthClientSettings(false)) {
36
- console.error(ERROR.LOGGED_IN_GLOBAL);
34
+ if (auth.credentials) {
35
+ const msg = intl.formatMessage({ id: "FTrSWo", defaultMessage: [{ type: 0, value: "Warning: You seem to already be logged in." }] });
36
+ console.error(msg);
37
37
  }
38
- console.log(LOG.LOGIN(isLocalLogin));
39
- // Localhost check
40
38
  const useLocalhost = Boolean(options.localhost);
41
- // Use the specified redirectPort if provided
42
39
  const redirectPort = options.redirectPort;
43
- // Using own credentials.
44
- if (options.creds) {
45
- // First read the manifest to detect any additional scopes in "oauthScopes" fields.
46
- // In the script.google.com UI, these are found under File > Project Properties > Scopes
47
- const { oauthScopes = [] } = await readManifest();
48
- const scopes = [...new Set([...oauthScopes, scopeWebAppDeploy])];
40
+ const oauth2Client = getUnauthorizedOuth2Client(options.creds);
41
+ let scopes = [...DEFAULT_SCOPES];
42
+ if (options.useProjectScopes) {
43
+ const manifest = await clasp.project.readManifest();
44
+ scopes = (_a = manifest.oauthScopes) !== null && _a !== void 0 ? _a : scopes;
45
+ const scopesLabel = intl.formatMessage({ id: "S0Kswv", defaultMessage: [{ type: 0, value: "Authorizing with the following scopes:" }] });
49
46
  console.log('');
50
- console.log('Authorizing with the following scopes:');
47
+ console.log(scopesLabel);
51
48
  for (const scope of scopes) {
52
49
  console.log(scope);
53
50
  }
54
- console.log(`\nNOTE: The full list of scopes your project may need can be found at script.google.com under:
55
- File > Project Properties > Scopes\n`);
56
- // Read credentials file.
57
- const creds = readJsonSync(options.creds, FS_OPTIONS);
58
- await authorize({ creds, scopes, useLocalhost, redirectPort });
59
- await enableAppsScriptAPI();
60
- return;
61
51
  }
62
- // Not using own credentials
63
- // Use the default scopes needed for clasp.
64
- await authorize({ scopes: defaultScopes, useLocalhost, redirectPort });
65
- };
66
- //# sourceMappingURL=login.js.map
52
+ const credentials = await authorize({
53
+ store: auth.credentialStore,
54
+ userKey: auth.user,
55
+ oauth2Client,
56
+ scopes,
57
+ noLocalServer: !useLocalhost,
58
+ redirectPort,
59
+ });
60
+ const user = await getUserInfo(credentials);
61
+ const msg = intl.formatMessage({ id: "sZ9k34", defaultMessage: [{ type: 5, value: "email", options: { undefined: { value: [{ type: 0, value: "You are logged in as an unknown user." }] }, other: { value: [{ type: 0, value: "You are logged in as " }, { type: 1, value: "email" }, { type: 0, value: "." }] } } }] }, {
62
+ email: user === null || user === void 0 ? void 0 : user.email,
63
+ });
64
+ console.log(msg);
65
+ });
@@ -1,16 +1,16 @@
1
- import fs from 'fs-extra';
2
- import { Conf } from '../conf.js';
3
- const config = Conf.get();
4
- const deleteIfExists = (file) => {
5
- if (file && fs.existsSync(file)) {
6
- fs.unlinkSync(file);
1
+ import { Command } from 'commander';
2
+ import { intl } from '../intl.js';
3
+ export const command = new Command('logout').description('Logout of clasp').action(async function () {
4
+ var _a;
5
+ const auth = this.opts().auth;
6
+ if (!auth.credentialStore) {
7
+ const msg = intl.formatMessage({ id: "vWMhE2", defaultMessage: [{ type: 0, value: "No credential store found, unable to log out." }] });
8
+ this.error(msg);
7
9
  }
8
- };
9
- /**
10
- * Logs out the user by deleting credentials.
11
- */
12
- export default async () => {
13
- deleteIfExists(config.auth);
14
- deleteIfExists(config.authLocal);
15
- };
16
- //# sourceMappingURL=logout.js.map
10
+ if (!auth.credentials) {
11
+ return;
12
+ }
13
+ (_a = auth.credentialStore) === null || _a === void 0 ? void 0 : _a.delete(auth.user);
14
+ const successMessage = intl.formatMessage({ id: "lRlj4t", defaultMessage: [{ type: 0, value: "Deleted credentials." }] });
15
+ console.log(successMessage);
16
+ });
@@ -0,0 +1,11 @@
1
+ import { Command } from 'commander';
2
+ import { assertGcpProjectConfigured, maybePromptForProjectId, openUrl } from './utils.js';
3
+ export const command = new Command('open-api-console')
4
+ .description('Open the API console for the current project.')
5
+ .action(async function () {
6
+ const clasp = this.opts().clasp;
7
+ const projectId = await maybePromptForProjectId(clasp);
8
+ assertGcpProjectConfigured(clasp);
9
+ const url = `https://console.developers.google.com/apis/dashboard?project=${projectId}`;
10
+ await openUrl(url);
11
+ });
@@ -0,0 +1,15 @@
1
+ import { Command } from 'commander';
2
+ import { intl } from '../intl.js';
3
+ import { openUrl } from './utils.js';
4
+ export const command = new Command('open-container')
5
+ .description('Open the Apps Script IDE for the current project.')
6
+ .action(async function () {
7
+ const clasp = this.opts().clasp;
8
+ const parentId = clasp.project.parentId;
9
+ if (!parentId) {
10
+ const msg = intl.formatMessage({ id: "eXBzoP", defaultMessage: [{ type: 0, value: "Parent ID not set, unable to open document." }] });
11
+ this.error(msg);
12
+ }
13
+ const url = `https://drive.google.com/open?id=${parentId}`;
14
+ await openUrl(url);
15
+ });
@@ -0,0 +1,11 @@
1
+ import { Command } from 'commander';
2
+ import { assertGcpProjectConfigured, maybePromptForProjectId, openUrl } from './utils.js';
3
+ export const command = new Command('open-credentials-setup')
4
+ .description("Open credentials page for the script's GCP project")
5
+ .action(async function () {
6
+ const clasp = this.opts().clasp;
7
+ const projectId = await maybePromptForProjectId(clasp);
8
+ assertGcpProjectConfigured(clasp);
9
+ const url = `https://console.developers.google.com/apis/credentials?project=${projectId}`;
10
+ await openUrl(url);
11
+ });
@@ -0,0 +1,11 @@
1
+ import { Command } from 'commander';
2
+ import { assertGcpProjectConfigured, maybePromptForProjectId, openUrl } from './utils.js';
3
+ export const command = new Command('open-logs')
4
+ .description('Open logs in the developer console')
5
+ .action(async function () {
6
+ const clasp = this.opts().clasp;
7
+ const projectId = await maybePromptForProjectId(clasp);
8
+ assertGcpProjectConfigured(clasp);
9
+ const url = `https://console.cloud.google.com/logs/viewer?project=${projectId}&resource=app_script_function`;
10
+ await openUrl(url);
11
+ });
@@ -0,0 +1,18 @@
1
+ import { Command } from 'commander';
2
+ import { intl } from '../intl.js';
3
+ import { openUrl } from './utils.js';
4
+ export const command = new Command('open-script')
5
+ .arguments('[scriptId]')
6
+ .description('Open the Apps Script IDE for the current project.')
7
+ .action(async function (scriptId) {
8
+ const clasp = this.opts().clasp;
9
+ if (!scriptId) {
10
+ scriptId = clasp.project.scriptId;
11
+ }
12
+ if (!scriptId) {
13
+ const msg = intl.formatMessage({ id: "RXEA+0", defaultMessage: [{ type: 0, value: "Script ID not set, unable to open IDE." }] });
14
+ this.error(msg);
15
+ }
16
+ const url = `https://script.google.com/d/${scriptId}/edit`;
17
+ await openUrl(url);
18
+ });
@@ -0,0 +1,56 @@
1
+ import { Command } from 'commander';
2
+ import inquirer from 'inquirer';
3
+ import { intl } from '../intl.js';
4
+ import { ellipsize, isInteractive, openUrl } from './utils.js';
5
+ export const command = new Command('open-web-app')
6
+ .arguments('[deploymentId]')
7
+ .description('Open a deployed web app in the browser.')
8
+ .action(async function (deploymentId) {
9
+ var _a, _b;
10
+ const clasp = this.opts().clasp;
11
+ const scriptId = clasp.project.scriptId;
12
+ if (!scriptId) {
13
+ const msg = intl.formatMessage({ id: "Teli1g", defaultMessage: [{ type: 0, value: "Script ID not set, unable to open web app." }] });
14
+ this.error(msg);
15
+ }
16
+ if (!deploymentId && isInteractive()) {
17
+ const deployments = await clasp.project.listDeployments();
18
+ // Order deployments by update time.
19
+ deployments.results.sort((a, b) => (a.updateTime && b.updateTime ? a.updateTime.localeCompare(b.updateTime) : 0));
20
+ const choices = deployments.results.map(deployment => {
21
+ var _a, _b, _c, _d, _e;
22
+ const description = ellipsize((_b = (_a = deployment.deploymentConfig) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : '', 30);
23
+ const versionNumber = ((_e = (_d = (_c = deployment.deploymentConfig) === null || _c === void 0 ? void 0 : _c.versionNumber) === null || _d === void 0 ? void 0 : _d.toString()) !== null && _e !== void 0 ? _e : 'HEAD').padEnd(4);
24
+ const name = `${description}@${versionNumber}} - ${deployment.deploymentId}`;
25
+ return {
26
+ name: name,
27
+ value: deployment.deploymentId,
28
+ };
29
+ });
30
+ const prompt = intl.formatMessage({ id: "D5Y2Qm", defaultMessage: [{ type: 0, value: "Open which deployment?" }] });
31
+ const answer = await inquirer.prompt([
32
+ {
33
+ choices: choices,
34
+ message: prompt,
35
+ name: 'deployment',
36
+ type: 'list',
37
+ },
38
+ ]);
39
+ deploymentId = answer.deployment;
40
+ }
41
+ if (!deploymentId) {
42
+ const msg = intl.formatMessage({ id: "j847fH", defaultMessage: [{ type: 0, value: "Deployment ID is requrired." }] });
43
+ this.error(msg);
44
+ }
45
+ const entryPoints = (_a = (await clasp.project.entryPoints(deploymentId))) !== null && _a !== void 0 ? _a : [];
46
+ const webAppEntry = entryPoints.find(entryPoint => {
47
+ var _a;
48
+ return entryPoint.entryPointType === 'WEB_APP' && !!((_a = entryPoint.webApp) === null || _a === void 0 ? void 0 : _a.url);
49
+ });
50
+ if (!webAppEntry || !((_b = webAppEntry.webApp) === null || _b === void 0 ? void 0 : _b.url)) {
51
+ const msg = intl.formatMessage({ id: "Kfeimc", defaultMessage: [{ type: 0, value: "No web app entry point found." }] });
52
+ this.error(msg);
53
+ }
54
+ const url = webAppEntry.webApp.url;
55
+ await openUrl(url);
56
+ });
@@ -0,0 +1,108 @@
1
+ import { Command, Option } from 'commander';
2
+ import { PROJECT_NAME } from '../constants.js';
3
+ import { command as cloneCommand } from './clone-script.js';
4
+ import { command as createDeploymentCommand } from './create-deployment.js';
5
+ import { command as createCommand } from './create-script.js';
6
+ import { command as createVersionCommand } from './create-version.js';
7
+ import { command as deleteDeploymentCOmand } from './delete-deployment.js';
8
+ import { command as disableApiCommand } from './disable-api.js';
9
+ import { command as enableApiCommand } from './enable-api.js';
10
+ import { command as listApisCommand } from './list-apis.js';
11
+ import { command as listDeploymentsCommand } from './list-deployments.js';
12
+ import { command as listCommand } from './list-scripts.js';
13
+ import { command as listVersionsCommand } from './list-versions.js';
14
+ import { command as loginCommand } from './login.js';
15
+ import { command as logoutCommand } from './logout.js';
16
+ import { command as openApisConsoleCommand } from './open-apis.js';
17
+ import { command as openContainerCommand } from './open-container.js';
18
+ import { command as openAuthCommand } from './open-credentials.js';
19
+ import { command as openLogsCommand } from './open-logs.js';
20
+ import { command as openScriptCommand } from './open-script.js';
21
+ import { command as pullCommand } from './pull.js';
22
+ import { command as pushCommand } from './push.js';
23
+ import { command as runCommand } from './run-function.js';
24
+ import { command as setupLogsCommand } from './setup-logs.js';
25
+ import { command as authStatusCommand } from './show-authorized-user.js';
26
+ import { command as filesStatusCommand } from './show-file-status.js';
27
+ import { command as tailLogsCommand } from './tail-logs.js';
28
+ import { dirname } from 'path';
29
+ import { fileURLToPath } from 'url';
30
+ import { readPackageUpSync } from 'read-pkg-up';
31
+ import { initAuth } from '../auth/auth.js';
32
+ import { initClaspInstance } from '../core/clasp.js';
33
+ import { intl } from '../intl.js';
34
+ export function makeProgram(exitOveride) {
35
+ const __dirname = dirname(fileURLToPath(import.meta.url));
36
+ const manifest = readPackageUpSync({ cwd: __dirname });
37
+ const version = manifest ? manifest.packageJson.version : 'unknown';
38
+ const program = new Command();
39
+ program.exitOverride(exitOveride);
40
+ program.storeOptionsAsProperties(false);
41
+ /**
42
+ * Displays clasp version
43
+ */
44
+ program.version(version, '-v, --version', 'output the current version');
45
+ program.name(PROJECT_NAME).usage('<command> [options]').description(`${PROJECT_NAME} - The Apps Script CLI`);
46
+ program.hook('preAction', async (_, cmd) => {
47
+ const opts = cmd.optsWithGlobals();
48
+ const auth = await initAuth({
49
+ authFilePath: opts.auth,
50
+ userKey: opts.user,
51
+ useApplicationDefaultCredentials: opts.adc,
52
+ });
53
+ const clasp = await initClaspInstance({
54
+ credentials: auth.credentials,
55
+ configFile: opts.project,
56
+ ignoreFile: opts.ignore,
57
+ });
58
+ cmd.setOptionValue('clasp', clasp);
59
+ cmd.setOptionValue('auth', auth);
60
+ });
61
+ /**
62
+ * Path to an auth file, or to a folder with a '.clasprc.json' file.
63
+ */
64
+ program.addOption(new Option('-A, --auth <file>', "path to an auth file or a folder with a '.clasprc.json' file.").env('clasp_config_auth'));
65
+ program.option('-u,--user <name>', 'Store named credentials. If unspecified, the "default" user is used.', 'default');
66
+ program.option('--adc', 'Use the application default credentials from the environemnt.');
67
+ program.addOption(new Option('-I, --ignore <file>', "path to an ignore file or a folder with a '.claspignore' file.").env('clasp_config_ignore'));
68
+ program.addOption(new Option('-P, --project <file>', "path to a project file or to a folder with a '.clasp.json' file.").env('clasp_config_project'));
69
+ const commandsToAdd = [
70
+ loginCommand,
71
+ logoutCommand,
72
+ openAuthCommand,
73
+ cloneCommand,
74
+ createCommand,
75
+ pushCommand,
76
+ pullCommand,
77
+ createDeploymentCommand,
78
+ deleteDeploymentCOmand,
79
+ listDeploymentsCommand,
80
+ disableApiCommand,
81
+ enableApiCommand,
82
+ listApisCommand,
83
+ openApisConsoleCommand,
84
+ authStatusCommand,
85
+ filesStatusCommand,
86
+ openLogsCommand,
87
+ setupLogsCommand,
88
+ tailLogsCommand,
89
+ openScriptCommand,
90
+ openContainerCommand,
91
+ runCommand,
92
+ listCommand,
93
+ createVersionCommand,
94
+ listVersionsCommand,
95
+ ];
96
+ for (const cmd of commandsToAdd) {
97
+ program.addCommand(cmd);
98
+ cmd.copyInheritedSettings(program);
99
+ }
100
+ program.on('command:*', async function (op) {
101
+ const msg = intl.formatMessage({ id: "UlHLBZ", defaultMessage: [{ type: 0, value: "Unknown command \"clasp " }, { type: 1, value: "command" }, { type: 0, value: "\"" }] }, {
102
+ command: op[0],
103
+ });
104
+ this.error(msg);
105
+ });
106
+ program.error;
107
+ return program;
108
+ }