@vercel/connect 0.8.0 → 1.0.0
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/dist/authorization.d.ts +6 -0
- package/dist/authorization.js +5 -2
- package/dist/chat/index.d.ts +2 -1
- package/dist/chat/index.js +1 -0
- package/dist/chat/linq-adapter.d.ts +37 -0
- package/dist/chat/linq-adapter.js +37 -0
- package/dist/chat/types.d.ts +18 -0
- package/dist/chat/webhook-verifier.d.ts +1 -1
- package/dist/connector.js +3 -1
- package/dist/eve/index.d.ts +1 -0
- package/dist/eve/index.js +1 -0
- package/dist/eve/linq-credentials.d.ts +34 -0
- package/dist/eve/linq-credentials.js +24 -0
- package/dist/eve/provision-oauth-connector.js +7 -3
- package/dist/installation.d.ts +6 -0
- package/dist/installation.js +3 -1
- package/dist/internal/base-url.d.ts +10 -0
- package/dist/internal/base-url.js +12 -0
- package/dist/internal/default-scopes.d.ts +2 -0
- package/dist/internal/default-scopes.js +3 -0
- package/dist/token.d.ts +8 -2
- package/dist/token.js +11 -6
- package/package.json +2 -2
package/dist/authorization.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ export interface ConnectAuthorizationOptions {
|
|
|
7
7
|
expiresInMs?: number;
|
|
8
8
|
/** OAuth prompt value to pass to the connector's authorization server. */
|
|
9
9
|
prompt?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Region to send the request to, e.g. `sfo1`. Defaults to the
|
|
12
|
+
* `VERCEL_REGION` environment variable; override it to target a
|
|
13
|
+
* different region.
|
|
14
|
+
*/
|
|
15
|
+
region?: string;
|
|
10
16
|
}
|
|
11
17
|
export interface ConnectAuthorizationResponse {
|
|
12
18
|
request: string;
|
package/dist/authorization.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getVercelOidcToken } from '@vercel/oidc';
|
|
2
2
|
import { isDetachedInteractiveAuth, validateCallbackUrl, validateWebhookUrl, } from './internal/url-validation.js';
|
|
3
|
+
import { withDefaultScopes } from './internal/default-scopes.js';
|
|
4
|
+
import { resolveBaseUrl } from './internal/base-url.js';
|
|
3
5
|
export async function startAuthorization(connector, params, options) {
|
|
4
6
|
if (!connector) {
|
|
5
7
|
throw new Error('connector is required');
|
|
@@ -12,13 +14,14 @@ export async function startAuthorization(connector, params, options) {
|
|
|
12
14
|
validateWebhookUrl(options.webhook);
|
|
13
15
|
}
|
|
14
16
|
const vercelToken = options?.vercelToken ?? (await getVercelOidcToken());
|
|
15
|
-
const
|
|
17
|
+
const baseUrl = resolveBaseUrl(options);
|
|
18
|
+
const endpoint = `${baseUrl}/v1/connect/authorize/${encodeURIComponent(connector)}`;
|
|
16
19
|
const deviceCode = options?.deviceCode ?? (detachedInteractiveAuth ? true : undefined);
|
|
17
20
|
const returnUrl = !detachedInteractiveAuth && options?.callbackUrl !== undefined
|
|
18
21
|
? { returnUrl: options.callbackUrl }
|
|
19
22
|
: {};
|
|
20
23
|
const body = {
|
|
21
|
-
...params,
|
|
24
|
+
...withDefaultScopes(params),
|
|
22
25
|
...returnUrl,
|
|
23
26
|
...(options?.webhook !== undefined && { webhook: options.webhook }),
|
|
24
27
|
...(deviceCode !== undefined && {
|
package/dist/chat/index.d.ts
CHANGED
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
23
|
export { createConnectWebhookVerifier, type ConnectWebhookVerifier, type ConnectWebhookVerifierOptions, } from './webhook-verifier.js';
|
|
24
|
-
export type { ConnectDiscordAdapterConfig, ConnectGitHubAdapterConfig, ConnectLinearAdapterConfig, ConnectNotionAdapterConfig, ConnectTelegramAdapterConfig, ConnectTokenResolver, } from './types.js';
|
|
24
|
+
export type { ConnectDiscordAdapterConfig, ConnectGitHubAdapterConfig, ConnectLinearAdapterConfig, ConnectLinqAdapterConfig, ConnectLinqCredentials, ConnectNotionAdapterConfig, ConnectTelegramAdapterConfig, ConnectTokenResolver, } from './types.js';
|
|
25
25
|
export { connectDiscordAdapter, type ConnectDiscordAdapterParams, } from './discord-adapter.js';
|
|
26
26
|
export { connectSlackAdapter, type ConnectSlackAdapterConfig, type ConnectSlackAdapterParams, } from './slack-adapter.js';
|
|
27
27
|
export { connectGitHubAdapter, type ConnectGitHubAdapterParams, } from './github-adapter.js';
|
|
28
28
|
export { connectLinearAdapter, type ConnectLinearAdapterParams, } from './linear-adapter.js';
|
|
29
|
+
export { connectLinqAdapter, type ConnectLinqAdapterParams, } from './linq-adapter.js';
|
|
29
30
|
export { connectNotionAdapter, type ConnectNotionAdapterParams, } from './notion-adapter.js';
|
|
30
31
|
export { connectTelegramAdapter, type ConnectTelegramAdapterParams, } from './telegram-adapter.js';
|
package/dist/chat/index.js
CHANGED
|
@@ -25,5 +25,6 @@ export { connectDiscordAdapter, } from './discord-adapter.js';
|
|
|
25
25
|
export { connectSlackAdapter, } from './slack-adapter.js';
|
|
26
26
|
export { connectGitHubAdapter, } from './github-adapter.js';
|
|
27
27
|
export { connectLinearAdapter, } from './linear-adapter.js';
|
|
28
|
+
export { connectLinqAdapter, } from './linq-adapter.js';
|
|
28
29
|
export { connectNotionAdapter, } from './notion-adapter.js';
|
|
29
30
|
export { connectTelegramAdapter, } from './telegram-adapter.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ConnectOptions, type ConnectTokenParams } from '../index.js';
|
|
2
|
+
import type { ConnectLinqAdapterConfig } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Token parameters accepted by {@link connectLinqAdapter}.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors {@link ConnectTokenParams} from `@vercel/connect`, minus `subject`.
|
|
7
|
+
* Linq credentials are app-scoped, so this helper always uses
|
|
8
|
+
* `{ type: 'app' }`.
|
|
9
|
+
*/
|
|
10
|
+
export type ConnectLinqAdapterParams = Omit<ConnectTokenParams, 'subject'>;
|
|
11
|
+
/**
|
|
12
|
+
* Build a Linq adapter config fragment backed by a Vercel Connect connector.
|
|
13
|
+
*
|
|
14
|
+
* Spread the result into `createLinqAdapter` from `@linqapp/chat-sdk-adapter`:
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { createLinqAdapter } from '@linqapp/chat-sdk-adapter';
|
|
18
|
+
* import { connectLinqAdapter } from '@vercel/connect/chat';
|
|
19
|
+
*
|
|
20
|
+
* createLinqAdapter({
|
|
21
|
+
* ...connectLinqAdapter('linq/my-agent'),
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* Linq's SDK calls its Bearer credential `apiKey`; the lazy `credentials`
|
|
26
|
+
* provider supplies the app-scoped Connect token through that field only when
|
|
27
|
+
* the adapter needs it.
|
|
28
|
+
*
|
|
29
|
+
* Connect retains Linq's webhook signing secret and verifies trigger-forwarded
|
|
30
|
+
* webhooks before attaching a Vercel OIDC token. `webhookVerifier` validates
|
|
31
|
+
* that OIDC token, replacing Linq's native HMAC check.
|
|
32
|
+
*
|
|
33
|
+
* The optional `params` and `options` arguments mirror the signature of
|
|
34
|
+
* {@link getTokenResponse}, allowing callers to pass through fields like
|
|
35
|
+
* `installationId`, `scopes`, or `validityBufferMs`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function connectLinqAdapter(connector: string, params?: ConnectLinqAdapterParams, options?: ConnectOptions): ConnectLinqAdapterConfig;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getTokenResponse, } from '../index.js';
|
|
2
|
+
import { createConnectWebhookVerifier } from './webhook-verifier.js';
|
|
3
|
+
/**
|
|
4
|
+
* Build a Linq adapter config fragment backed by a Vercel Connect connector.
|
|
5
|
+
*
|
|
6
|
+
* Spread the result into `createLinqAdapter` from `@linqapp/chat-sdk-adapter`:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { createLinqAdapter } from '@linqapp/chat-sdk-adapter';
|
|
10
|
+
* import { connectLinqAdapter } from '@vercel/connect/chat';
|
|
11
|
+
*
|
|
12
|
+
* createLinqAdapter({
|
|
13
|
+
* ...connectLinqAdapter('linq/my-agent'),
|
|
14
|
+
* });
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Linq's SDK calls its Bearer credential `apiKey`; the lazy `credentials`
|
|
18
|
+
* provider supplies the app-scoped Connect token through that field only when
|
|
19
|
+
* the adapter needs it.
|
|
20
|
+
*
|
|
21
|
+
* Connect retains Linq's webhook signing secret and verifies trigger-forwarded
|
|
22
|
+
* webhooks before attaching a Vercel OIDC token. `webhookVerifier` validates
|
|
23
|
+
* that OIDC token, replacing Linq's native HMAC check.
|
|
24
|
+
*
|
|
25
|
+
* The optional `params` and `options` arguments mirror the signature of
|
|
26
|
+
* {@link getTokenResponse}, allowing callers to pass through fields like
|
|
27
|
+
* `installationId`, `scopes`, or `validityBufferMs`.
|
|
28
|
+
*/
|
|
29
|
+
export function connectLinqAdapter(connector, params = {}, options) {
|
|
30
|
+
return {
|
|
31
|
+
credentials: async () => {
|
|
32
|
+
const response = await getTokenResponse(connector, { ...params, subject: { type: 'app' } }, options);
|
|
33
|
+
return { apiKey: response.token };
|
|
34
|
+
},
|
|
35
|
+
webhookVerifier: createConnectWebhookVerifier(),
|
|
36
|
+
};
|
|
37
|
+
}
|
package/dist/chat/types.d.ts
CHANGED
|
@@ -38,6 +38,24 @@ export interface ConnectLinearAdapterConfig {
|
|
|
38
38
|
accessToken: ConnectTokenResolver;
|
|
39
39
|
webhookVerifier: ConnectWebhookVerifier;
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Credentials resolved lazily by the Linq Chat SDK adapter.
|
|
43
|
+
*
|
|
44
|
+
* Structurally matches the return value of its `credentials` option.
|
|
45
|
+
*/
|
|
46
|
+
export interface ConnectLinqCredentials {
|
|
47
|
+
apiKey: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Partial Linq adapter config backed by Vercel Connect.
|
|
51
|
+
*
|
|
52
|
+
* Structurally matches the `credentials` and `webhookVerifier` options of
|
|
53
|
+
* `createLinqAdapter` from `@linqapp/chat-sdk-adapter`.
|
|
54
|
+
*/
|
|
55
|
+
export interface ConnectLinqAdapterConfig {
|
|
56
|
+
credentials: () => Promise<ConnectLinqCredentials>;
|
|
57
|
+
webhookVerifier: (request: Request, rawBody: Uint8Array) => Promise<unknown> | unknown;
|
|
58
|
+
}
|
|
41
59
|
/**
|
|
42
60
|
* Partial Notion adapter config backed by Vercel Connect.
|
|
43
61
|
*
|
|
@@ -9,7 +9,7 @@ import { verifyVercelOidcToken } from '@vercel/oidc';
|
|
|
9
9
|
* subpath stay decoupled from `@chat-adapter/*` while remaining
|
|
10
10
|
* structurally compatible.
|
|
11
11
|
*/
|
|
12
|
-
export type ConnectWebhookVerifier = (request: Request, body: string) => Promise<unknown> | unknown;
|
|
12
|
+
export type ConnectWebhookVerifier = (request: Request, body: string | Uint8Array) => Promise<unknown> | unknown;
|
|
13
13
|
/**
|
|
14
14
|
* Options forwarded to {@link verifyVercelOidcToken}. Defaults to
|
|
15
15
|
* matching `project_id` / `environment` against the current Vercel
|
package/dist/connector.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getVercelOidcToken } from '@vercel/oidc';
|
|
2
2
|
import { createConnectErrorFromResponse, } from './token.js';
|
|
3
|
+
import { resolveBaseUrl } from './internal/base-url.js';
|
|
3
4
|
/**
|
|
4
5
|
* Fetch a connector's metadata from Vercel Connect.
|
|
5
6
|
*
|
|
@@ -11,7 +12,8 @@ import { createConnectErrorFromResponse, } from './token.js';
|
|
|
11
12
|
*/
|
|
12
13
|
export async function getConnectorMetadata(connector, options) {
|
|
13
14
|
const vercelToken = options?.vercelToken ?? (await getVercelOidcToken());
|
|
14
|
-
const
|
|
15
|
+
const baseUrl = resolveBaseUrl(options);
|
|
16
|
+
const endpoint = `${baseUrl}/v1/connect/connectors/${encodeURIComponent(connector)}`;
|
|
15
17
|
const response = await fetch(endpoint, {
|
|
16
18
|
method: 'GET',
|
|
17
19
|
headers: {
|
package/dist/eve/index.d.ts
CHANGED
|
@@ -11,5 +11,6 @@ export { CONNECT_OAUTH_ISSUER, connectOAuth, type ConnectOAuthAudienceEnvironmen
|
|
|
11
11
|
export { connectDiscordCredentials, type ConnectDiscordCredentialsParams, } from './discord-credentials.js';
|
|
12
12
|
export { connectGitHubCredentials, type ConnectGitHubCredentialsParams, } from './github-credentials.js';
|
|
13
13
|
export { connectLinearCredentials, type ConnectLinearCredentialsParams, } from './linear-credentials.js';
|
|
14
|
+
export { connectLinqCredentials, type ConnectLinqCredentials, type ConnectLinqCredentialsParams, } from './linq-credentials.js';
|
|
14
15
|
export { connectPhotonCredentials, type ConnectPhotonCredentialProvider, type PhotonCredentials, type ConnectPhotonCredentialsParams, } from './photon-credentials.js';
|
|
15
16
|
export { connectSlackCredentials, type ConnectSlackCredentialsParams, } from './slack-credentials.js';
|
package/dist/eve/index.js
CHANGED
|
@@ -11,5 +11,6 @@ export { CONNECT_OAUTH_ISSUER, connectOAuth, } from './connect-oauth.js';
|
|
|
11
11
|
export { connectDiscordCredentials, } from './discord-credentials.js';
|
|
12
12
|
export { connectGitHubCredentials, } from './github-credentials.js';
|
|
13
13
|
export { connectLinearCredentials, } from './linear-credentials.js';
|
|
14
|
+
export { connectLinqCredentials, } from './linq-credentials.js';
|
|
14
15
|
export { connectPhotonCredentials, } from './photon-credentials.js';
|
|
15
16
|
export { connectSlackCredentials, } from './slack-credentials.js';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { vercelOidc } from 'eve/channels/auth';
|
|
2
|
+
import { type ConnectOptions, type ConnectTokenParams } from '../index.js';
|
|
3
|
+
/** Linq channel credentials returned by {@link connectLinqCredentials}. */
|
|
4
|
+
export interface ConnectLinqCredentials {
|
|
5
|
+
/** Short-lived API key for outbound Linq API calls. */
|
|
6
|
+
apiKey: () => Promise<string>;
|
|
7
|
+
/** Verifies webhooks forwarded by Vercel Connect. */
|
|
8
|
+
webhookVerifier: ReturnType<typeof vercelOidc>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Token parameters accepted by {@link connectLinqCredentials}.
|
|
12
|
+
*
|
|
13
|
+
* Mirrors {@link ConnectTokenParams} from `@vercel/connect`, minus `subject`.
|
|
14
|
+
* Linq credentials are app-scoped, so this helper always uses
|
|
15
|
+
* `{ type: 'app' }`.
|
|
16
|
+
*/
|
|
17
|
+
export type ConnectLinqCredentialsParams = Omit<ConnectTokenParams, 'subject'>;
|
|
18
|
+
/**
|
|
19
|
+
* Build Linq channel credentials backed by a Vercel Connect connector.
|
|
20
|
+
*
|
|
21
|
+
* The API-key resolver keeps token rotation delegated to Connect.
|
|
22
|
+
* `webhookVerifier` validates the Vercel OIDC token Connect attaches after it
|
|
23
|
+
* has verified and forwarded the provider webhook.
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { connectLinqCredentials } from '@vercel/connect/eve';
|
|
27
|
+
* import { linqChannel } from 'eve/channels/linq';
|
|
28
|
+
*
|
|
29
|
+
* export default linqChannel({
|
|
30
|
+
* credentials: connectLinqCredentials('linq/my-agent'),
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function connectLinqCredentials(connector: string, params?: ConnectLinqCredentialsParams, options?: ConnectOptions): ConnectLinqCredentials;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { vercelOidc } from 'eve/channels/auth';
|
|
2
|
+
import { getToken, } from '../index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Build Linq channel credentials backed by a Vercel Connect connector.
|
|
5
|
+
*
|
|
6
|
+
* The API-key resolver keeps token rotation delegated to Connect.
|
|
7
|
+
* `webhookVerifier` validates the Vercel OIDC token Connect attaches after it
|
|
8
|
+
* has verified and forwarded the provider webhook.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { connectLinqCredentials } from '@vercel/connect/eve';
|
|
12
|
+
* import { linqChannel } from 'eve/channels/linq';
|
|
13
|
+
*
|
|
14
|
+
* export default linqChannel({
|
|
15
|
+
* credentials: connectLinqCredentials('linq/my-agent'),
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function connectLinqCredentials(connector, params = {}, options) {
|
|
20
|
+
return {
|
|
21
|
+
apiKey: () => getToken(connector, { ...params, subject: { type: 'app' } }, options),
|
|
22
|
+
webhookVerifier: vercelOidc(),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getVercelOidcToken } from '@vercel/oidc';
|
|
2
2
|
import { ConnectError, createConnectErrorFromResponse } from '../token.js';
|
|
3
|
-
|
|
3
|
+
import { resolveBaseUrl } from '../internal/base-url.js';
|
|
4
|
+
const MANAGED_OAUTH_CONNECTOR_PATH = '/v1/connect/connectors/managed/oauth';
|
|
4
5
|
const RESERVED_UID_PATTERN = /^(vc\/|[^/]*\.vercel\.com\/)/;
|
|
5
6
|
const ALLOWED_RESERVED_UID_PREFIXES = ['mcp.vercel.com/'];
|
|
6
7
|
const RESERVED_ID_PREFIXES = ['scl_', 'sca_', 'store_', 'ir_'];
|
|
@@ -12,9 +13,11 @@ export async function provisionEveOAuthConnector({ connector, connection, connec
|
|
|
12
13
|
return;
|
|
13
14
|
}
|
|
14
15
|
const vercelToken = connectOptions?.vercelToken ?? (await getVercelOidcToken());
|
|
16
|
+
const endpoint = `${resolveBaseUrl(connectOptions)}${MANAGED_OAUTH_CONNECTOR_PATH}`;
|
|
15
17
|
const cacheKey = JSON.stringify({
|
|
16
18
|
connector,
|
|
17
19
|
serverUrl,
|
|
20
|
+
endpoint,
|
|
18
21
|
token: await tokenCacheKeyPart(vercelToken),
|
|
19
22
|
});
|
|
20
23
|
let promise = provisionCache.get(cacheKey);
|
|
@@ -23,6 +26,7 @@ export async function provisionEveOAuthConnector({ connector, connection, connec
|
|
|
23
26
|
connector,
|
|
24
27
|
serverUrl,
|
|
25
28
|
vercelToken,
|
|
29
|
+
endpoint,
|
|
26
30
|
}).catch(error => {
|
|
27
31
|
if (isNonOAuthConnectorConflict(error)) {
|
|
28
32
|
return;
|
|
@@ -80,8 +84,8 @@ function isNonOAuthConnectorConflict(error) {
|
|
|
80
84
|
error.status === 409 &&
|
|
81
85
|
/not an OAuth connector/i.test(error.message));
|
|
82
86
|
}
|
|
83
|
-
async function provisionManagedOAuthConnector({ connector, serverUrl, vercelToken, }) {
|
|
84
|
-
const response = await fetch(
|
|
87
|
+
async function provisionManagedOAuthConnector({ connector, serverUrl, vercelToken, endpoint, }) {
|
|
88
|
+
const response = await fetch(endpoint, {
|
|
85
89
|
method: 'POST',
|
|
86
90
|
headers: {
|
|
87
91
|
Accept: 'application/json',
|
package/dist/installation.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ export interface ConnectInstallationOptions {
|
|
|
7
7
|
tenantId?: string;
|
|
8
8
|
deviceCode?: boolean;
|
|
9
9
|
expiresInMs?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Region to send the request to, e.g. `sfo1`. Defaults to the
|
|
12
|
+
* `VERCEL_REGION` environment variable; override it to target a
|
|
13
|
+
* different region.
|
|
14
|
+
*/
|
|
15
|
+
region?: string;
|
|
10
16
|
}
|
|
11
17
|
export interface ConnectInstallationResponse {
|
|
12
18
|
request: string;
|
package/dist/installation.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getVercelOidcToken } from '@vercel/oidc';
|
|
2
2
|
import { isDetachedInteractiveAuth, validateCallbackUrl, validateWebhookUrl, } from './internal/url-validation.js';
|
|
3
3
|
import { createConnectErrorFromResponse } from './token.js';
|
|
4
|
+
import { resolveBaseUrl } from './internal/base-url.js';
|
|
4
5
|
/**
|
|
5
6
|
* Create an operator installation request for an app-scoped connector.
|
|
6
7
|
*
|
|
@@ -19,7 +20,8 @@ export async function experimental_startInstallation(connector, params = {}, opt
|
|
|
19
20
|
validateWebhookUrl(options.webhook);
|
|
20
21
|
}
|
|
21
22
|
const vercelToken = options?.vercelToken ?? (await getVercelOidcToken());
|
|
22
|
-
const
|
|
23
|
+
const baseUrl = resolveBaseUrl(options);
|
|
24
|
+
const endpoint = `${baseUrl}/v1/connect/install/${encodeURIComponent(connector)}`;
|
|
23
25
|
const deviceCode = options?.deviceCode ?? (detachedInteractiveAuth ? true : undefined);
|
|
24
26
|
const returnUrl = !detachedInteractiveAuth && options?.returnUrl !== undefined
|
|
25
27
|
? { returnUrl: options.returnUrl }
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Base URL for the Vercel API when no region is available. */
|
|
2
|
+
export declare const API_BASE_URL = "https://api.vercel.com";
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the Vercel API base URL for a region. The region comes from the
|
|
5
|
+
* `region` argument, then the `VERCEL_REGION` environment variable; without
|
|
6
|
+
* either, requests go to the global {@link API_BASE_URL}.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveBaseUrl({ region }?: {
|
|
9
|
+
region?: string;
|
|
10
|
+
}): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { readNonEmptyEnv } from './env.js';
|
|
2
|
+
/** Base URL for the Vercel API when no region is available. */
|
|
3
|
+
export const API_BASE_URL = 'https://api.vercel.com';
|
|
4
|
+
/**
|
|
5
|
+
* Resolves the Vercel API base URL for a region. The region comes from the
|
|
6
|
+
* `region` argument, then the `VERCEL_REGION` environment variable; without
|
|
7
|
+
* either, requests go to the global {@link API_BASE_URL}.
|
|
8
|
+
*/
|
|
9
|
+
export function resolveBaseUrl({ region } = {}) {
|
|
10
|
+
const resolved = region ?? readNonEmptyEnv('VERCEL_REGION');
|
|
11
|
+
return resolved ? `https://api-${resolved}.vercel.com` : API_BASE_URL;
|
|
12
|
+
}
|
package/dist/token.d.ts
CHANGED
|
@@ -27,8 +27,8 @@ export interface ConnectTokenParams {
|
|
|
27
27
|
installationId?: string;
|
|
28
28
|
audience?: string[];
|
|
29
29
|
/**
|
|
30
|
-
* Access scopes to request.
|
|
31
|
-
* the specified subject type.
|
|
30
|
+
* Access scopes to request. Defaults to `['*']`, which requests the default
|
|
31
|
+
* scopes for the specified subject type.
|
|
32
32
|
*/
|
|
33
33
|
scopes?: string[];
|
|
34
34
|
resources?: string[];
|
|
@@ -103,6 +103,12 @@ export interface ConnectOptions {
|
|
|
103
103
|
* a stale bearer.
|
|
104
104
|
*/
|
|
105
105
|
forceRefresh?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Region to send the request to, e.g. `sfo1`. Defaults to the
|
|
108
|
+
* `VERCEL_REGION` environment variable; override it to target a
|
|
109
|
+
* different region.
|
|
110
|
+
*/
|
|
111
|
+
region?: string;
|
|
106
112
|
}
|
|
107
113
|
export declare function getToken(connector: string, params: ConnectTokenParams, options?: ConnectOptions): Promise<string>;
|
|
108
114
|
export declare function getTokenResponse(connector: string, params: ConnectTokenParams, options?: ConnectOptions): Promise<ConnectTokenResponse>;
|
package/dist/token.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { getVercelOidcToken } from '@vercel/oidc';
|
|
2
|
+
import { resolveBaseUrl } from './internal/base-url.js';
|
|
3
|
+
import { withDefaultScopes } from './internal/default-scopes.js';
|
|
2
4
|
export class ConnectError extends Error {
|
|
3
5
|
code;
|
|
4
6
|
status;
|
|
@@ -36,8 +38,9 @@ export async function getToken(connector, params, options) {
|
|
|
36
38
|
return token;
|
|
37
39
|
}
|
|
38
40
|
export async function getTokenResponse(connector, params, options) {
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
+
const requestParams = withDefaultScopes(params);
|
|
42
|
+
const bufferMs = requestParams.validityBufferMs ?? DEFAULT_VALIDITY_BUFFER_MS;
|
|
43
|
+
const cacheKey = tokenCacheKey(connector, requestParams);
|
|
41
44
|
if (options?.forceRefresh) {
|
|
42
45
|
cache.delete(cacheKey);
|
|
43
46
|
}
|
|
@@ -53,7 +56,8 @@ export async function getTokenResponse(connector, params, options) {
|
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
const vercelToken = options?.vercelToken ?? (await getVercelOidcToken());
|
|
56
|
-
const
|
|
59
|
+
const baseUrl = resolveBaseUrl(options);
|
|
60
|
+
const endpoint = `${baseUrl}/v1/connect/token/${encodeURIComponent(connector)}`;
|
|
57
61
|
const response = await fetch(endpoint, {
|
|
58
62
|
method: 'POST',
|
|
59
63
|
headers: {
|
|
@@ -61,7 +65,7 @@ export async function getTokenResponse(connector, params, options) {
|
|
|
61
65
|
'Content-Type': 'application/json',
|
|
62
66
|
Authorization: `Bearer ${vercelToken}`,
|
|
63
67
|
},
|
|
64
|
-
body: JSON.stringify(
|
|
68
|
+
body: JSON.stringify(requestParams),
|
|
65
69
|
});
|
|
66
70
|
if (!response.ok) {
|
|
67
71
|
throw await createConnectErrorFromResponse(response, 'Failed to get token');
|
|
@@ -75,7 +79,8 @@ export async function getTokenResponse(connector, params, options) {
|
|
|
75
79
|
}
|
|
76
80
|
export async function revokeToken(connector, params, options) {
|
|
77
81
|
const vercelToken = options?.vercelToken ?? (await getVercelOidcToken());
|
|
78
|
-
const
|
|
82
|
+
const baseUrl = resolveBaseUrl(options);
|
|
83
|
+
const endpoint = `${baseUrl}/v1/connect/connectors/${encodeURIComponent(connector)}/tokens`;
|
|
79
84
|
const response = await fetch(endpoint, {
|
|
80
85
|
method: 'DELETE',
|
|
81
86
|
headers: {
|
|
@@ -108,7 +113,7 @@ export async function revokeToken(connector, params, options) {
|
|
|
108
113
|
* call. No-op when no matching entry exists.
|
|
109
114
|
*/
|
|
110
115
|
export function deleteTokenCacheEntry(connector, params) {
|
|
111
|
-
cache.delete(tokenCacheKey(connector, params));
|
|
116
|
+
cache.delete(tokenCacheKey(connector, withDefaultScopes(params)));
|
|
112
117
|
}
|
|
113
118
|
const DEFAULT_VALIDITY_BUFFER_MS = 30_000;
|
|
114
119
|
const MAX_CACHE_SIZE = 100;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/connect",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"dist"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@vercel/oidc": "3.8.
|
|
45
|
+
"@vercel/oidc": "3.8.5"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"@ai-sdk/mcp": "^1 || ^2",
|