@google/clasp 3.0.6-alpha → 3.1.1
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 +35 -2
- package/build/src/auth/auth.js +54 -10
- package/build/src/auth/auth_code_flow.js +51 -0
- package/build/src/auth/credential_store.js +13 -0
- package/build/src/auth/file_credential_store.js +62 -7
- package/build/src/auth/localhost_auth_code_flow.js +47 -5
- package/build/src/auth/serverless_auth_code_flow.js +39 -2
- package/build/src/commands/clone-script.js +37 -5
- package/build/src/commands/create-deployment.js +31 -6
- package/build/src/commands/create-script.js +65 -24
- package/build/src/commands/create-version.js +21 -1
- package/build/src/commands/delete-deployment.js +36 -5
- package/build/src/commands/delete-script.js +41 -0
- package/build/src/commands/disable-api.js +20 -1
- package/build/src/commands/enable-api.js +20 -1
- package/build/src/commands/list-apis.js +24 -1
- package/build/src/commands/list-deployments.js +35 -5
- package/build/src/commands/list-scripts.js +26 -2
- package/build/src/commands/list-versions.js +35 -7
- package/build/src/commands/login.js +36 -10
- package/build/src/commands/logout.js +23 -1
- package/build/src/commands/open-apis.js +20 -1
- package/build/src/commands/open-container.js +20 -1
- package/build/src/commands/open-credentials.js +20 -1
- package/build/src/commands/open-logs.js +20 -1
- package/build/src/commands/open-script.js +20 -1
- package/build/src/commands/open-webapp.js +20 -1
- package/build/src/commands/program.js +48 -7
- package/build/src/commands/pull.js +54 -13
- package/build/src/commands/push.js +49 -9
- package/build/src/commands/run-function.js +56 -13
- package/build/src/commands/setup-logs.js +20 -1
- package/build/src/commands/show-authorized-user.js +29 -2
- package/build/src/commands/show-file-status.js +17 -2
- package/build/src/commands/start-mcp.js +17 -1
- package/build/src/commands/tail-logs.js +20 -5
- package/build/src/commands/update-deployment.js +32 -6
- package/build/src/commands/utils.js +68 -0
- package/build/src/constants.js +15 -0
- package/build/src/core/apis.js +13 -3
- package/build/src/core/clasp.js +71 -12
- package/build/src/core/files.js +135 -32
- package/build/src/core/functions.js +36 -0
- package/build/src/core/logs.js +29 -0
- package/build/src/core/manifest.js +13 -0
- package/build/src/core/project.js +154 -7
- package/build/src/core/services.js +105 -16
- package/build/src/core/utils.js +57 -1
- package/build/src/experiments.js +23 -0
- package/build/src/index.js +2 -0
- package/build/src/intl.js +28 -0
- package/build/src/mcp/server.js +82 -6
- package/docs/run.md +10 -4
- package/package.json +3 -3
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
// Copyright 2019 Google LLC
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// This file defines the 'login' command for the clasp CLI.
|
|
1
15
|
/**
|
|
2
16
|
* Clasp command method bodies.
|
|
3
17
|
*/
|
|
@@ -23,17 +37,20 @@ export const command = new Command('login')
|
|
|
23
37
|
.option('--creds <file>', 'Relative path to OAuth client secret file (from GCP).')
|
|
24
38
|
.option('--use-project-scopes', 'Use the scopes from the current project manifest. Used only when authorizing access for the run command.')
|
|
25
39
|
.option('--redirect-port <port>', 'Specify a custom port for the redirect URL.')
|
|
26
|
-
.action(async function (
|
|
40
|
+
.action(async function () {
|
|
27
41
|
var _a;
|
|
28
|
-
const
|
|
29
|
-
const
|
|
42
|
+
const options = this.optsWithGlobals();
|
|
43
|
+
const auth = options.authInfo;
|
|
44
|
+
const clasp = options.clasp;
|
|
30
45
|
if (!auth.credentialStore) {
|
|
31
46
|
const msg = intl.formatMessage({ id: "u1wQGD", defaultMessage: [{ type: 0, value: "No credential store found, unable to login." }] });
|
|
32
47
|
this.error(msg);
|
|
33
48
|
}
|
|
34
49
|
if (auth.credentials) {
|
|
35
|
-
|
|
36
|
-
|
|
50
|
+
if (!options.json) {
|
|
51
|
+
const msg = intl.formatMessage({ id: "FTrSWo", defaultMessage: [{ type: 0, value: "Warning: You seem to already be logged in." }] });
|
|
52
|
+
console.error(msg);
|
|
53
|
+
}
|
|
37
54
|
}
|
|
38
55
|
const useLocalhost = Boolean(options.localhost);
|
|
39
56
|
const redirectPort = options.redirectPort;
|
|
@@ -42,11 +59,13 @@ export const command = new Command('login')
|
|
|
42
59
|
if (options.useProjectScopes) {
|
|
43
60
|
const manifest = await clasp.project.readManifest();
|
|
44
61
|
scopes = (_a = manifest.oauthScopes) !== null && _a !== void 0 ? _a : scopes;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
62
|
+
if (!options.json) {
|
|
63
|
+
const scopesLabel = intl.formatMessage({ id: "S0Kswv", defaultMessage: [{ type: 0, value: "Authorizing with the following scopes:" }] });
|
|
64
|
+
console.log('');
|
|
65
|
+
console.log(scopesLabel);
|
|
66
|
+
for (const scope of scopes) {
|
|
67
|
+
console.log(scope);
|
|
68
|
+
}
|
|
50
69
|
}
|
|
51
70
|
}
|
|
52
71
|
const credentials = await authorize({
|
|
@@ -58,6 +77,13 @@ export const command = new Command('login')
|
|
|
58
77
|
redirectPort,
|
|
59
78
|
});
|
|
60
79
|
const user = await getUserInfo(credentials);
|
|
80
|
+
if (options.json) {
|
|
81
|
+
const output = {
|
|
82
|
+
email: user === null || user === void 0 ? void 0 : user.email,
|
|
83
|
+
};
|
|
84
|
+
console.log(JSON.stringify(output, null, 2));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
61
87
|
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
88
|
email: user === null || user === void 0 ? void 0 : user.email,
|
|
63
89
|
});
|
|
@@ -1,16 +1,38 @@
|
|
|
1
|
+
// Copyright 2019 Google LLC
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// This file defines the 'logout' command for the clasp CLI.
|
|
1
15
|
import { Command } from 'commander';
|
|
2
16
|
import { intl } from '../intl.js';
|
|
3
17
|
export const command = new Command('logout').description('Logout of clasp').action(async function () {
|
|
4
18
|
var _a;
|
|
5
|
-
const
|
|
19
|
+
const options = this.optsWithGlobals();
|
|
20
|
+
const auth = options.authInfo;
|
|
6
21
|
if (!auth.credentialStore) {
|
|
7
22
|
const msg = intl.formatMessage({ id: "vWMhE2", defaultMessage: [{ type: 0, value: "No credential store found, unable to log out." }] });
|
|
8
23
|
this.error(msg);
|
|
9
24
|
}
|
|
10
25
|
if (!auth.credentials) {
|
|
26
|
+
if (options.json) {
|
|
27
|
+
console.log(JSON.stringify({ success: true }, null, 2));
|
|
28
|
+
}
|
|
11
29
|
return;
|
|
12
30
|
}
|
|
13
31
|
(_a = auth.credentialStore) === null || _a === void 0 ? void 0 : _a.delete(auth.user);
|
|
32
|
+
if (options.json) {
|
|
33
|
+
console.log(JSON.stringify({ success: true }, null, 2));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
14
36
|
const successMessage = intl.formatMessage({ id: "lRlj4t", defaultMessage: [{ type: 0, value: "Deleted credentials." }] });
|
|
15
37
|
console.log(successMessage);
|
|
16
38
|
});
|
|
@@ -1,10 +1,26 @@
|
|
|
1
|
+
// Copyright 2025 Google LLC
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// This file defines the 'open-api-console' command for the clasp CLI.
|
|
1
15
|
import { Command } from 'commander';
|
|
2
16
|
import { INCLUDE_USER_HINT_IN_URL } from '../experiments.js';
|
|
3
17
|
import { assertGcpProjectConfigured, maybePromptForProjectId, openUrl } from './utils.js';
|
|
4
18
|
export const command = new Command('open-api-console')
|
|
5
19
|
.description('Open the API console for the current project.')
|
|
6
20
|
.action(async function () {
|
|
7
|
-
const
|
|
21
|
+
const options = this.optsWithGlobals();
|
|
22
|
+
const clasp = options.clasp;
|
|
23
|
+
const json = options.json;
|
|
8
24
|
const projectId = await maybePromptForProjectId(clasp);
|
|
9
25
|
assertGcpProjectConfigured(clasp);
|
|
10
26
|
const url = new URL('https://console.developers.google.com/apis/dashboard');
|
|
@@ -13,5 +29,8 @@ export const command = new Command('open-api-console')
|
|
|
13
29
|
const userHint = await clasp.authorizedUser();
|
|
14
30
|
url.searchParams.set('authUser', userHint !== null && userHint !== void 0 ? userHint : '');
|
|
15
31
|
}
|
|
32
|
+
if (json) {
|
|
33
|
+
console.log(JSON.stringify({ url: url.toString() }, null, 2));
|
|
34
|
+
}
|
|
16
35
|
await openUrl(url.toString());
|
|
17
36
|
});
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
// Copyright 2025 Google LLC
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// This file defines the 'open-container' command for the clasp CLI.
|
|
1
15
|
import { Command } from 'commander';
|
|
2
16
|
import { INCLUDE_USER_HINT_IN_URL } from '../experiments.js';
|
|
3
17
|
import { intl } from '../intl.js';
|
|
@@ -5,7 +19,9 @@ import { openUrl } from './utils.js';
|
|
|
5
19
|
export const command = new Command('open-container')
|
|
6
20
|
.description('Open the Apps Script IDE for the current project.')
|
|
7
21
|
.action(async function () {
|
|
8
|
-
const
|
|
22
|
+
const options = this.optsWithGlobals();
|
|
23
|
+
const clasp = options.clasp;
|
|
24
|
+
const json = options.json;
|
|
9
25
|
const parentId = clasp.project.parentId;
|
|
10
26
|
if (!parentId) {
|
|
11
27
|
const msg = intl.formatMessage({ id: "eXBzoP", defaultMessage: [{ type: 0, value: "Parent ID not set, unable to open document." }] });
|
|
@@ -17,5 +33,8 @@ export const command = new Command('open-container')
|
|
|
17
33
|
const userHint = await clasp.authorizedUser();
|
|
18
34
|
url.searchParams.set('authUser', userHint !== null && userHint !== void 0 ? userHint : '');
|
|
19
35
|
}
|
|
36
|
+
if (json) {
|
|
37
|
+
console.log(JSON.stringify({ url: url.toString() }, null, 2));
|
|
38
|
+
}
|
|
20
39
|
await openUrl(url.toString());
|
|
21
40
|
});
|
|
@@ -1,10 +1,26 @@
|
|
|
1
|
+
// Copyright 2025 Google LLC
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// This file defines the 'open-credentials-setup' command for the clasp CLI.
|
|
1
15
|
import { Command } from 'commander';
|
|
2
16
|
import { INCLUDE_USER_HINT_IN_URL } from '../experiments.js';
|
|
3
17
|
import { assertGcpProjectConfigured, maybePromptForProjectId, openUrl } from './utils.js';
|
|
4
18
|
export const command = new Command('open-credentials-setup')
|
|
5
19
|
.description("Open credentials page for the script's GCP project")
|
|
6
20
|
.action(async function () {
|
|
7
|
-
const
|
|
21
|
+
const options = this.optsWithGlobals();
|
|
22
|
+
const clasp = options.clasp;
|
|
23
|
+
const json = options.json;
|
|
8
24
|
const projectId = await maybePromptForProjectId(clasp);
|
|
9
25
|
assertGcpProjectConfigured(clasp);
|
|
10
26
|
const url = new URL('https://console.developers.google.com/apis/credentials');
|
|
@@ -13,5 +29,8 @@ export const command = new Command('open-credentials-setup')
|
|
|
13
29
|
const userHint = await clasp.authorizedUser();
|
|
14
30
|
url.searchParams.set('authUser', userHint !== null && userHint !== void 0 ? userHint : '');
|
|
15
31
|
}
|
|
32
|
+
if (json) {
|
|
33
|
+
console.log(JSON.stringify({ url: url.toString() }, null, 2));
|
|
34
|
+
}
|
|
16
35
|
await openUrl(url.toString());
|
|
17
36
|
});
|
|
@@ -1,10 +1,26 @@
|
|
|
1
|
+
// Copyright 2025 Google LLC
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// This file defines the 'open-logs' command for the clasp CLI.
|
|
1
15
|
import { Command } from 'commander';
|
|
2
16
|
import { INCLUDE_USER_HINT_IN_URL } from '../experiments.js';
|
|
3
17
|
import { assertGcpProjectConfigured, maybePromptForProjectId, openUrl } from './utils.js';
|
|
4
18
|
export const command = new Command('open-logs')
|
|
5
19
|
.description('Open logs in the developer console')
|
|
6
20
|
.action(async function () {
|
|
7
|
-
const
|
|
21
|
+
const options = this.optsWithGlobals();
|
|
22
|
+
const clasp = options.clasp;
|
|
23
|
+
const json = options.json;
|
|
8
24
|
const projectId = await maybePromptForProjectId(clasp);
|
|
9
25
|
assertGcpProjectConfigured(clasp);
|
|
10
26
|
const url = new URL('https://console.cloud.google.com/logs/viewer');
|
|
@@ -14,5 +30,8 @@ export const command = new Command('open-logs')
|
|
|
14
30
|
const userHint = await clasp.authorizedUser();
|
|
15
31
|
url.searchParams.set('authUser', userHint !== null && userHint !== void 0 ? userHint : '');
|
|
16
32
|
}
|
|
33
|
+
if (json) {
|
|
34
|
+
console.log(JSON.stringify({ url: url.toString() }, null, 2));
|
|
35
|
+
}
|
|
17
36
|
await openUrl(url.toString());
|
|
18
37
|
});
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
// Copyright 2025 Google LLC
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// This file defines the 'open-script' command for the clasp CLI.
|
|
1
15
|
import { Command } from 'commander';
|
|
2
16
|
import { INCLUDE_USER_HINT_IN_URL } from '../experiments.js';
|
|
3
17
|
import { intl } from '../intl.js';
|
|
@@ -6,7 +20,9 @@ export const command = new Command('open-script')
|
|
|
6
20
|
.arguments('[scriptId]')
|
|
7
21
|
.description('Open the Apps Script IDE for the current project.')
|
|
8
22
|
.action(async function (scriptId) {
|
|
9
|
-
const
|
|
23
|
+
const options = this.optsWithGlobals();
|
|
24
|
+
const clasp = options.clasp;
|
|
25
|
+
const json = options.json;
|
|
10
26
|
if (!scriptId) {
|
|
11
27
|
scriptId = clasp.project.scriptId;
|
|
12
28
|
}
|
|
@@ -19,5 +35,8 @@ export const command = new Command('open-script')
|
|
|
19
35
|
const userHint = await clasp.authorizedUser();
|
|
20
36
|
url.searchParams.set('authUser', userHint !== null && userHint !== void 0 ? userHint : '');
|
|
21
37
|
}
|
|
38
|
+
if (json) {
|
|
39
|
+
console.log(JSON.stringify({ url: url.toString() }, null, 2));
|
|
40
|
+
}
|
|
22
41
|
await openUrl(url.toString());
|
|
23
42
|
});
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
// Copyright 2025 Google LLC
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// This file defines the 'open-web-app' command for the clasp CLI.
|
|
1
15
|
import { Command } from 'commander';
|
|
2
16
|
import inquirer from 'inquirer';
|
|
3
17
|
import { INCLUDE_USER_HINT_IN_URL } from '../experiments.js';
|
|
@@ -8,7 +22,9 @@ export const command = new Command('open-web-app')
|
|
|
8
22
|
.description('Open a deployed web app in the browser.')
|
|
9
23
|
.action(async function (deploymentId) {
|
|
10
24
|
var _a, _b;
|
|
11
|
-
const
|
|
25
|
+
const options = this.optsWithGlobals();
|
|
26
|
+
const clasp = options.clasp;
|
|
27
|
+
const json = options.json;
|
|
12
28
|
const scriptId = clasp.project.scriptId;
|
|
13
29
|
if (!scriptId) {
|
|
14
30
|
const msg = intl.formatMessage({ id: "Teli1g", defaultMessage: [{ type: 0, value: "Script ID not set, unable to open web app." }] });
|
|
@@ -57,5 +73,8 @@ export const command = new Command('open-web-app')
|
|
|
57
73
|
const userHint = await clasp.authorizedUser();
|
|
58
74
|
url.searchParams.set('authUser', userHint !== null && userHint !== void 0 ? userHint : '');
|
|
59
75
|
}
|
|
76
|
+
if (json) {
|
|
77
|
+
console.log(JSON.stringify({ url: url.toString() }, null, 2));
|
|
78
|
+
}
|
|
60
79
|
await openUrl(url.toString());
|
|
61
80
|
});
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
// Copyright 2025 Google LLC
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// This file sets up the main CLI program for clasp. It initializes commander,
|
|
15
|
+
// defines global options, registers all command modules, and handles
|
|
16
|
+
// versioning and error handling.
|
|
1
17
|
import { Command, Option } from 'commander';
|
|
2
18
|
import { PROJECT_NAME } from '../constants.js';
|
|
3
19
|
import { command as cloneCommand } from './clone-script.js';
|
|
@@ -5,6 +21,7 @@ import { command as createDeploymentCommand } from './create-deployment.js';
|
|
|
5
21
|
import { command as createCommand } from './create-script.js';
|
|
6
22
|
import { command as createVersionCommand } from './create-version.js';
|
|
7
23
|
import { command as deleteDeploymentCOmand } from './delete-deployment.js';
|
|
24
|
+
import { command as deleteCommand } from './delete-script.js';
|
|
8
25
|
import { command as disableApiCommand } from './disable-api.js';
|
|
9
26
|
import { command as enableApiCommand } from './enable-api.js';
|
|
10
27
|
import { command as listApisCommand } from './list-apis.js';
|
|
@@ -34,12 +51,24 @@ import { readPackageUpSync } from 'read-package-up';
|
|
|
34
51
|
import { initAuth } from '../auth/auth.js';
|
|
35
52
|
import { initClaspInstance } from '../core/clasp.js';
|
|
36
53
|
import { intl } from '../intl.js';
|
|
54
|
+
/**
|
|
55
|
+
* Retrieves the version of the clasp CLI from its package.json.
|
|
56
|
+
* @returns {string} The version string, or 'unknown' if it cannot be determined.
|
|
57
|
+
*/
|
|
37
58
|
export function getVersion() {
|
|
38
59
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
39
60
|
const manifest = readPackageUpSync({ cwd: __dirname });
|
|
40
61
|
const version = manifest ? manifest.packageJson.version : 'unknown';
|
|
41
62
|
return version;
|
|
42
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Creates and configures the main Commander program for the clasp CLI.
|
|
66
|
+
* This includes setting the version, defining global options, registering all commands,
|
|
67
|
+
* and setting up pre-action hooks for auth and Clasp instance initialization.
|
|
68
|
+
* @param { (err: CommanderError) => void } [exitOveride] - Optional function to override
|
|
69
|
+
* the default exit behavior of Commander, primarily for testing.
|
|
70
|
+
* @returns {Command} The configured Commander program instance.
|
|
71
|
+
*/
|
|
43
72
|
export function makeProgram(exitOveride) {
|
|
44
73
|
const version = getVersion();
|
|
45
74
|
const program = new Command();
|
|
@@ -50,20 +79,30 @@ export function makeProgram(exitOveride) {
|
|
|
50
79
|
*/
|
|
51
80
|
program.version(version, '-v, --version', 'output the current version');
|
|
52
81
|
program.name(PROJECT_NAME).usage('<command> [options]').description(`${PROJECT_NAME} - The Apps Script CLI`);
|
|
82
|
+
// This hook runs before any command's action handler.
|
|
83
|
+
// It's used to initialize authentication and the main Clasp instance,
|
|
84
|
+
// making them available to all command actions.
|
|
53
85
|
program.hook('preAction', async (_, cmd) => {
|
|
86
|
+
// `optsWithGlobals()` retrieves all options, including global ones like --auth, --project, etc.
|
|
54
87
|
const opts = cmd.optsWithGlobals();
|
|
88
|
+
// Initialize authentication based on global options.
|
|
89
|
+
// This will load existing credentials or prepare for a new auth flow if needed.
|
|
55
90
|
const auth = await initAuth({
|
|
56
|
-
authFilePath: opts.auth,
|
|
57
|
-
userKey: opts.user,
|
|
58
|
-
useApplicationDefaultCredentials: opts.adc,
|
|
91
|
+
authFilePath: opts.auth, // Path to .clasprc.json
|
|
92
|
+
userKey: opts.user, // User key for multi-user support
|
|
93
|
+
useApplicationDefaultCredentials: opts.adc, // Flag for using ADC
|
|
59
94
|
});
|
|
95
|
+
// Initialize the main Clasp instance with the (potentially) authenticated client
|
|
96
|
+
// and paths to project config and ignore files.
|
|
60
97
|
const clasp = await initClaspInstance({
|
|
61
|
-
credentials: auth.credentials,
|
|
62
|
-
configFile: opts.project,
|
|
63
|
-
ignoreFile: opts.ignore,
|
|
98
|
+
credentials: auth.credentials, // Pass the OAuth2 client (if authenticated)
|
|
99
|
+
configFile: opts.project, // Path to .clasp.json
|
|
100
|
+
ignoreFile: opts.ignore, // Path to .claspignore
|
|
64
101
|
});
|
|
102
|
+
// Make the initialized `clasp` and `auth` objects available to the
|
|
103
|
+
// actual command's action function via its options.
|
|
65
104
|
cmd.setOptionValue('clasp', clasp);
|
|
66
|
-
cmd.setOptionValue('
|
|
105
|
+
cmd.setOptionValue('authInfo', auth);
|
|
67
106
|
});
|
|
68
107
|
/**
|
|
69
108
|
* Path to an auth file, or to a folder with a '.clasprc.json' file.
|
|
@@ -71,6 +110,7 @@ export function makeProgram(exitOveride) {
|
|
|
71
110
|
program.addOption(new Option('-A, --auth <file>', "path to an auth file or a folder with a '.clasprc.json' file.").env('clasp_config_auth'));
|
|
72
111
|
program.option('-u,--user <name>', 'Store named credentials. If unspecified, the "default" user is used.', 'default');
|
|
73
112
|
program.option('--adc', 'Use the application default credentials from the environemnt.');
|
|
113
|
+
program.option('--json', 'Show output in JSON format');
|
|
74
114
|
program.addOption(new Option('-I, --ignore <file>', "path to an ignore file or a folder with a '.claspignore' file.").env('clasp_config_ignore'));
|
|
75
115
|
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'));
|
|
76
116
|
const commandsToAdd = [
|
|
@@ -82,6 +122,7 @@ export function makeProgram(exitOveride) {
|
|
|
82
122
|
pushCommand,
|
|
83
123
|
pullCommand,
|
|
84
124
|
createDeploymentCommand,
|
|
125
|
+
deleteCommand,
|
|
85
126
|
deleteDeploymentCOmand,
|
|
86
127
|
listDeploymentsCommand,
|
|
87
128
|
updateDeploymentCommand,
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
// Copyright 2019 Google LLC
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
// This file defines the 'pull' command for the clasp CLI.
|
|
1
15
|
import { Command } from 'commander';
|
|
2
16
|
import fs from 'fs/promises';
|
|
3
17
|
import inquirer from 'inquirer';
|
|
@@ -8,48 +22,75 @@ export const command = new Command('pull')
|
|
|
8
22
|
.option('--versionNumber <version>', 'The version number of the project to retrieve.')
|
|
9
23
|
.option('-d, --deleteUnusedFiles ', 'Delete local files that are not in the remote project. Use with caution.')
|
|
10
24
|
.option('-f, --force', 'Forcibly delete local files that are not in the remote project without prompting.')
|
|
11
|
-
.action(async function (
|
|
12
|
-
const
|
|
25
|
+
.action(async function () {
|
|
26
|
+
const options = this.optsWithGlobals();
|
|
27
|
+
const clasp = options.clasp;
|
|
13
28
|
const versionNumber = options.versionNumber;
|
|
14
29
|
const forceDelete = options.force;
|
|
30
|
+
// First, collect a list of current local files before pulling.
|
|
31
|
+
// This is used to determine which files might need to be deleted if --deleteUnusedFiles is active.
|
|
15
32
|
let spinnerMsg = intl.formatMessage({ id: "dh7Bw6", defaultMessage: [{ type: 0, value: "Checking local files..." }] });
|
|
16
33
|
const localFiles = await clasp.files.collectLocalFiles();
|
|
34
|
+
// Perform the pull operation from the remote Apps Script project.
|
|
35
|
+
// This fetches the files (optionally a specific version) and writes them to the local filesystem.
|
|
17
36
|
spinnerMsg = intl.formatMessage({ id: "jilcJH", defaultMessage: [{ type: 0, value: "Pulling files..." }] });
|
|
18
37
|
const files = await withSpinner(spinnerMsg, async () => {
|
|
19
|
-
return
|
|
38
|
+
return clasp.files.pull(versionNumber); // `clasp.files.pull` handles fetching and writing.
|
|
20
39
|
});
|
|
40
|
+
const pulledFiles = files.map(f => f.localPath);
|
|
41
|
+
let deletedFiles = [];
|
|
42
|
+
// If the --deleteUnusedFiles option is used, identify and delete local files
|
|
43
|
+
// that are no longer present in the remote project.
|
|
21
44
|
if (options.deleteUnusedFiles) {
|
|
45
|
+
// Compare the initial list of local files with the files just pulled.
|
|
46
|
+
// Any file in `localFiles` that is not in `files` (the pulled files) is considered unused.
|
|
22
47
|
const filesToDelete = localFiles.filter(f => !files.find(p => p.localPath === f.localPath));
|
|
23
|
-
await deleteLocalFiles(filesToDelete, forceDelete);
|
|
48
|
+
deletedFiles = await deleteLocalFiles(filesToDelete, forceDelete, options.json);
|
|
24
49
|
}
|
|
50
|
+
if (options.json) {
|
|
51
|
+
console.log(JSON.stringify({ pulledFiles, deletedFiles }, null, 2));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// Log the paths of the pulled files.
|
|
25
55
|
files.forEach(f => console.log(`└─ ${f.localPath}`));
|
|
26
56
|
const successMessage = intl.formatMessage({ id: "4mRAfN", defaultMessage: [{ type: 0, value: "Pulled " }, { type: 6, value: "count", options: { "=0": { value: [{ type: 0, value: "no files." }] }, one: { value: [{ type: 0, value: "one file." }] }, other: { value: [{ type: 7 }, { type: 0, value: " files" }] } }, offset: 0, pluralType: "cardinal" }, { type: 0, value: "." }] }, {
|
|
27
57
|
count: files.length,
|
|
28
58
|
});
|
|
29
59
|
console.log(successMessage);
|
|
30
60
|
});
|
|
31
|
-
async function deleteLocalFiles(filesToDelete, forceDelete = false) {
|
|
61
|
+
async function deleteLocalFiles(filesToDelete, forceDelete = false, json = false) {
|
|
32
62
|
if (!filesToDelete || filesToDelete.length === 0) {
|
|
33
|
-
return;
|
|
63
|
+
return []; // No files to delete.
|
|
34
64
|
}
|
|
35
65
|
const skipConfirmation = forceDelete;
|
|
66
|
+
// If not in an interactive terminal and --force is not used, skip deletion with a warning.
|
|
67
|
+
// This prevents accidental deletion in non-interactive environments like CI scripts.
|
|
36
68
|
if (!isInteractive() && !forceDelete) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
69
|
+
if (!json) {
|
|
70
|
+
const msg = intl.formatMessage({ id: "zLuvSg", defaultMessage: [{ type: 0, value: "You are not in an interactive terminal and --force not used. Skipping file deletion." }] });
|
|
71
|
+
console.warn(msg);
|
|
72
|
+
}
|
|
73
|
+
return [];
|
|
40
74
|
}
|
|
75
|
+
const deletedFiles = [];
|
|
41
76
|
for (const file of filesToDelete) {
|
|
77
|
+
let doDelete = true; // Assume deletion unless confirmation is required and denied.
|
|
42
78
|
if (!skipConfirmation) {
|
|
79
|
+
// If not forcing, prompt the user to confirm deletion for each file.
|
|
43
80
|
const confirm = await inquirer.prompt({
|
|
44
81
|
type: 'confirm',
|
|
45
82
|
name: 'deleteFile',
|
|
46
83
|
message: intl.formatMessage({ id: "lVx/lI", defaultMessage: [{ type: 0, value: "Delete " }, { type: 1, value: "file" }, { type: 0, value: "?" }] }, { file: file.localPath }),
|
|
47
84
|
});
|
|
48
|
-
|
|
49
|
-
|
|
85
|
+
doDelete = confirm.deleteFile;
|
|
86
|
+
}
|
|
87
|
+
if (doDelete) {
|
|
88
|
+
await fs.unlink(file.localPath); // Delete the file from the local system.
|
|
89
|
+
deletedFiles.push(file.localPath);
|
|
90
|
+
if (!json) {
|
|
91
|
+
console.log(intl.formatMessage({ id: "Nx315v", defaultMessage: [{ type: 0, value: "Deleted " }, { type: 1, value: "file" }] }, { file: file.localPath }));
|
|
50
92
|
}
|
|
51
93
|
}
|
|
52
|
-
await fs.unlink(file.localPath);
|
|
53
|
-
console.log(intl.formatMessage({ id: "Nx315v", defaultMessage: [{ type: 0, value: "Deleted " }, { type: 1, value: "file" }] }, { file: file.localPath }));
|
|
54
94
|
}
|
|
95
|
+
return deletedFiles;
|
|
55
96
|
}
|