1 | import { isArray } from 'lodash-es';
|
2 | import { from, Subscription, throwError } from 'rxjs';
|
3 | import { switchMap, take } from 'rxjs/operators';
|
4 | import { isErrorLike } from '../errors';
|
5 | /**
|
6 | * Registers the builtin client commands that are required for Sourcegraph extensions. See
|
7 | * {@link module:sourcegraph.module/protocol/contribution.ActionContribution#command} for
|
8 | * documentation.
|
9 | */
|
10 | export function registerBuiltinClientCommands(context, controller) {
|
11 | const subscription = new Subscription();
|
12 | subscription.add(controller.registries.commands.registerCommand({
|
13 | command: 'open',
|
14 | run: (url) => {
|
15 | // The `open` client command is usually implemented by ActionItem rendering the action with the
|
16 | // HTML <a> element, not by handling it here. Using an HTML <a> element means it is a standard
|
17 | // link, and native system behaviors such as open-in-new-tab work.
|
18 | //
|
19 | // If a client is not running in a web browser, this handler should be updated to call the system's
|
20 | // default URL handler using the system (e.g., Electron) API.
|
21 | window.open(url, '_blank');
|
22 | return Promise.resolve();
|
23 | },
|
24 | }));
|
25 | subscription.add(controller.registries.commands.registerCommand({
|
26 | command: 'updateConfiguration',
|
27 | run: (...anyArgs) => {
|
28 | const args = anyArgs;
|
29 | return updateConfiguration(context, convertUpdateConfigurationCommandArgs(args));
|
30 | },
|
31 | }));
|
32 | /**
|
33 | * Sends a GraphQL request to the Sourcegraph GraphQL API and returns the result. The request is performed
|
34 | * with the privileges of the current user.
|
35 | */
|
36 | subscription.add(controller.registries.commands.registerCommand({
|
37 | command: 'queryGraphQL',
|
38 | run: (query, variables) =>
|
39 | // 🚨 SECURITY: The request might contain private info (such as
|
40 | // repository names), so the `mightContainPrivateInfo` parameter
|
41 | // is set to `true`. It is up to the client (e.g. browser
|
42 | // extension) to check that parameter and prevent the request
|
43 | // from being sent to Sourcegraph.com.
|
44 | from(context.queryGraphQL(query, variables, true)).toPromise(),
|
45 | }));
|
46 | /**
|
47 | * Sends a batched LSP request to the Sourcegraph LSP gateway API and returns the result. The request is
|
48 | * performed with the privileges of the current user.
|
49 | */
|
50 | subscription.add(controller.registries.commands.registerCommand({
|
51 | command: 'queryLSP',
|
52 | run: requests => from(context.queryLSP(requests)).toPromise(),
|
53 | }));
|
54 | return subscription;
|
55 | }
|
56 | /**
|
57 | * Applies an edit to the configuration settings of the highest-precedence subject.
|
58 | */
|
59 | export function updateConfiguration(context, params) {
|
60 | // TODO(sqs): Allow extensions to specify which subject's configuration to update
|
61 | // (instead of always updating the highest-precedence subject's configuration).
|
62 | return from(context.configurationCascade)
|
63 | .pipe(take(1), switchMap(x => {
|
64 | if (!x.subjects) {
|
65 | return throwError(new Error('unable to update configuration: no configuration subjects available'));
|
66 | }
|
67 | if (isErrorLike(x.subjects)) {
|
68 | return throwError(new Error(`unable to update configuration: error retrieving configuration subjects: ${x.subjects.message}`));
|
69 | }
|
70 | const subject = x.subjects[x.subjects.length - 1].subject;
|
71 | return context.updateExtensionSettings(subject.id, { edit: params });
|
72 | }))
|
73 | .toPromise();
|
74 | }
|
75 | /**
|
76 | * Converts the arguments for the `updateConfiguration` client command (as documented in
|
77 | * {@link ActionContributionClientCommandUpdateConfiguration#commandArguments})
|
78 | * to {@link ConfigurationUpdateParams}.
|
79 | */
|
80 | export function convertUpdateConfigurationCommandArgs(args) {
|
81 | if (!isArray(args) ||
|
82 | !(args.length >= 2 && args.length <= 4) ||
|
83 | !isArray(args[0]) ||
|
84 | !(args[2] === undefined || args[2] === null)) {
|
85 | throw new Error(`invalid updateConfiguration arguments: ${JSON.stringify(args)}`);
|
86 | }
|
87 | const valueIsJSONEncoded = args.length === 4 && args[3] === 'json';
|
88 | return { path: args[0], value: valueIsJSONEncoded ? JSON.parse(args[1]) : args[1] };
|
89 | }
|
90 | //# sourceMappingURL=clientCommands.js.map |
\ | No newline at end of file |