diff --git a/package.json b/package.json index 1e4e7d8..66ba407 100644 --- a/package.json +++ b/package.json @@ -184,12 +184,14 @@ "@raycast/api": "^1.86.1", "@raycast/utils": "^1.18.1", "@sourcegraph/telemetry": "^0.18.0", + "@types/uuid": "^10.0.0", "cross-fetch": "^4.0.0", "eventsource": "^2.0.2", "graphql": "^16.9.0", "luxon": "^3.5.0", "nanoid": "^5.0.9", - "node-fetch": "^3.3.2" + "node-fetch": "^3.3.2", + "uuid": "^11.0.3" }, "devDependencies": { "@graphql-codegen/cli": "^5.0.3", @@ -219,4 +221,4 @@ "gql": "graphql-codegen --config graphql-codegen.yml && npm run fmt", "postinstall": "patch-package" } -} \ No newline at end of file +} diff --git a/src/components/DotComCommand.tsx b/src/components/DotComCommand.tsx index 47e97fb..ef2ac09 100644 --- a/src/components/DotComCommand.tsx +++ b/src/components/DotComCommand.tsx @@ -1,5 +1,5 @@ -import { LaunchProps } from "@raycast/api"; -import { useEffect } from "react"; +import { Detail, LaunchProps } from "@raycast/api"; +import { useEffect, useState } from "react"; import checkAuthEffect from "../hooks/checkAuthEffect"; import { Sourcegraph, sourcegraphDotCom } from "../sourcegraph"; @@ -14,9 +14,31 @@ export default function DotComCommand({ Command: React.FunctionComponent<{ src: Sourcegraph; props?: LaunchProps }>; props?: LaunchProps; }) { - const src = sourcegraphDotCom(); + const [src, setSrc] = useState(); + useEffect(() => { + async function loadSrc() { + setSrc(await sourcegraphDotCom()); + } + loadSrc(); + }, []); - useEffect(checkAuthEffect(src), []); + if (!src) { + return ; + } + return ; +} +// Inner wrapper for the command to deal with using checkAuthEffect while src +// requires async to initialize. +function CheckAuthCommand({ + src, + Command, + props, +}: { + src: Sourcegraph; + props?: LaunchProps; + Command: React.FunctionComponent<{ src: Sourcegraph; props?: LaunchProps }>; +}) { + useEffect(checkAuthEffect(src), []); return ; } diff --git a/src/findNotebooksInstance.tsx b/src/findNotebooksInstance.tsx index 30747b1..f44357b 100644 --- a/src/findNotebooksInstance.tsx +++ b/src/findNotebooksInstance.tsx @@ -1,6 +1,6 @@ import FindNotebooksCommand from "./components/FindNotebooksCommand"; import InstanceCommand from "./components/InstanceCommand"; -export default function FindNotebooksSelfHosted() { +export default async function FindNotebooksSelfHosted() { return ; } diff --git a/src/sourcegraph/gql/apollo.ts b/src/sourcegraph/gql/apollo.ts index 7f66d8d..7e2d191 100644 --- a/src/sourcegraph/gql/apollo.ts +++ b/src/sourcegraph/gql/apollo.ts @@ -3,12 +3,22 @@ import { setContext } from "@apollo/client/link/context"; import operations from "./operations"; import { getProxiedFetch } from "./fetchProxy"; -export function newApolloClient(connect: { instance: string; token?: string; proxy?: string }) { +export function newApolloClient(connect: { + instance: string; + token?: string; + proxy?: string; + anonymousUserID?: string; +}) { + const headers: Record = { + "X-Requested-With": "Raycast-Sourcegraph", + }; + if (connect.anonymousUserID) { + headers["X-Sourcegraph-Actor-Anonymous-UID"] = connect.anonymousUserID; + } + const httpLink = createHttpLink({ uri: `${connect.instance}/.api/graphql`, - headers: { - "X-Requested-With": "Raycast-Sourcegraph", - }, + headers, fetch: getProxiedFetch(connect.proxy) as unknown as WindowOrWorkerGlobalScope["fetch"], }); diff --git a/src/sourcegraph/index.ts b/src/sourcegraph/index.ts index 8446ba9..2fb0e04 100644 --- a/src/sourcegraph/index.ts +++ b/src/sourcegraph/index.ts @@ -1,5 +1,6 @@ +import { getPreferenceValues, LocalStorage } from "@raycast/api"; import { ApolloClient, NormalizedCacheObject } from "@apollo/client"; -import { getPreferenceValues } from "@raycast/api"; +import { v4 as uuidv4 } from "uuid"; import { newApolloClient } from "./gql/apollo"; export interface Sourcegraph { @@ -50,12 +51,24 @@ export function instanceName(src: Sourcegraph) { /** * sourcegraphDotCom returns the user's configuration for connecting to Sourcegraph.com. */ -export function sourcegraphDotCom(): Sourcegraph { +export async function sourcegraphDotCom(): Promise { const prefs = getPreferenceValues(); const searchPrefs = getPreferenceValues(); + + // If there is no token, generate a persisted anonymous identifier for the user. + let anonymousUserID = ""; + if (!prefs.cloudToken) { + anonymousUserID = (await LocalStorage.getItem("anonymous-user-id")) as string; + if (!anonymousUserID) { + anonymousUserID = uuidv4(); + await LocalStorage.setItem("anonymous-user-id", anonymousUserID); + } + } + const connect = { instance: dotComURL, token: prefs.cloudToken, + anonymousUserID, }; return { ...connect,