@every-app/sdk 0.3.0-rc.1 → 0.3.0-rc.3
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/LICENSE +21 -0
- package/dist/cloudflare/index.d.ts +2 -2
- package/dist/cloudflare/index.d.ts.map +1 -1
- package/dist/cloudflare/index.js +1 -1
- package/dist/cloudflare/sentinel.d.ts +39 -1
- package/dist/cloudflare/sentinel.d.ts.map +1 -1
- package/dist/cloudflare/sentinel.js +22 -1
- package/dist/cloudflare/worker.d.ts +205 -7
- package/dist/cloudflare/worker.d.ts.map +1 -1
- package/dist/cloudflare/worker.js +174 -11
- package/dist/internal/aiDefault.d.ts +141 -0
- package/dist/internal/aiDefault.d.ts.map +1 -0
- package/dist/internal/aiDefault.js +204 -0
- package/dist/internal/aiProviders.d.ts +4 -1
- package/dist/internal/aiProviders.d.ts.map +1 -1
- package/dist/internal/aiProviders.js +5 -1
- package/dist/internal/appSettings.d.ts +20 -2
- package/dist/internal/appSettings.d.ts.map +1 -1
- package/dist/internal/appSettings.js +53 -7
- package/dist/internal/audit.d.ts +108 -0
- package/dist/internal/audit.d.ts.map +1 -0
- package/dist/internal/audit.js +235 -0
- package/dist/internal/capabilities.d.ts +2315 -141
- package/dist/internal/capabilities.d.ts.map +1 -1
- package/dist/internal/capabilities.js +122 -0
- package/dist/internal/catalog/commerce.d.ts +394 -0
- package/dist/internal/catalog/commerce.d.ts.map +1 -0
- package/dist/internal/catalog/commerce.js +477 -0
- package/dist/internal/catalog/comms.d.ts +338 -0
- package/dist/internal/catalog/comms.d.ts.map +1 -0
- package/dist/internal/catalog/comms.js +477 -0
- package/dist/internal/catalog/index.d.ts +1936 -0
- package/dist/internal/catalog/index.d.ts.map +1 -0
- package/dist/internal/catalog/index.js +19 -0
- package/dist/internal/catalog/inference.d.ts +393 -0
- package/dist/internal/catalog/inference.d.ts.map +1 -0
- package/dist/internal/catalog/inference.js +457 -0
- package/dist/internal/catalog/infra.d.ts +423 -0
- package/dist/internal/catalog/infra.d.ts.map +1 -0
- package/dist/internal/catalog/infra.js +543 -0
- package/dist/internal/catalog/search.d.ts +400 -0
- package/dist/internal/catalog/search.d.ts.map +1 -0
- package/dist/internal/catalog/search.js +463 -0
- package/dist/internal/devProviders.d.ts +2 -2
- package/dist/internal/devProviders.d.ts.map +1 -1
- package/dist/internal/devProviders.js +19 -1
- package/dist/internal/events.d.ts +13 -2
- package/dist/internal/events.d.ts.map +1 -1
- package/dist/internal/events.js +21 -3
- package/dist/internal/gatewaySettings.d.ts +2 -1
- package/dist/internal/gatewaySettings.d.ts.map +1 -1
- package/dist/internal/gatewaySettings.js +10 -2
- package/dist/internal/index.d.ts +5 -0
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +5 -0
- package/dist/internal/oauthPresets.d.ts +29 -0
- package/dist/internal/oauthPresets.d.ts.map +1 -0
- package/dist/internal/oauthPresets.js +534 -0
- package/dist/internal/oauthScopes.d.ts +56 -1
- package/dist/internal/oauthScopes.d.ts.map +1 -1
- package/dist/internal/oauthScopes.js +98 -4
- package/dist/internal/oauthSpec.d.ts +59 -0
- package/dist/internal/oauthSpec.d.ts.map +1 -0
- package/dist/internal/oauthSpec.js +676 -0
- package/dist/internal/protocol.d.ts +11 -0
- package/dist/internal/protocol.d.ts.map +1 -1
- package/dist/internal/protocol.js +9 -0
- package/dist/internal/providerRegistry.d.ts +17 -6
- package/dist/internal/providerRegistry.d.ts.map +1 -1
- package/dist/internal/providerRegistry.js +51 -2
- package/dist/internal/providerSpec.d.ts +11 -7
- package/dist/internal/providerSpec.d.ts.map +1 -1
- package/dist/internal/providerSpec.js +142 -33
- package/dist/internal/signInProviders.d.ts +104 -0
- package/dist/internal/signInProviders.d.ts.map +1 -0
- package/dist/internal/signInProviders.js +245 -0
- package/dist/server/ai.d.ts +45 -0
- package/dist/server/ai.d.ts.map +1 -0
- package/dist/server/ai.js +40 -0
- package/dist/server/connectUrl.d.ts +21 -0
- package/dist/server/connectUrl.d.ts.map +1 -0
- package/dist/server/connectUrl.js +37 -0
- package/dist/server/gatewayFetch.d.ts.map +1 -1
- package/dist/server/gatewayFetch.js +72 -8
- package/dist/server/index.d.ts +4 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -1
- package/dist/server/integrationFetch.d.ts +39 -2
- package/dist/server/integrationFetch.d.ts.map +1 -1
- package/dist/server/integrationFetch.js +177 -13
- package/package.json +12 -12
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sign-in providers a Gateway can offer beside passwords ("Continue
|
|
3
|
+
* with Google"), as data: what each one is called, the Worker secrets it
|
|
4
|
+
* reads, where the OAuth app is made, the scopes asked for and which claim
|
|
5
|
+
* becomes the email. One catalog serves the Gateway (which providers are
|
|
6
|
+
* on, the sign-in page's buttons, Manage workspace → Sign-in), the CLI
|
|
7
|
+
* (`everyapp signin add|list|show|remove`, `secret set`), the manifest
|
|
8
|
+
* validator (an app's own secret can never take one of these names) and
|
|
9
|
+
* the docs' drift tests.
|
|
10
|
+
*
|
|
11
|
+
* Naming rule, agreed with the provider registry's conventions
|
|
12
|
+
* (docs/design/2026-10-provider-registry.md, section 6): a sign-in
|
|
13
|
+
* provider's settings are `<ID>_SIGNIN_<FIELD>`, with FIELD one of
|
|
14
|
+
* CLIENT_ID, CLIENT_SECRET, ISSUER, LABEL or TENANT. The `_SIGNIN_` infix is
|
|
15
|
+
* what keeps the family apart from the API providers' `<ID>_API_KEY`,
|
|
16
|
+
* `<ID>_CLIENT_ID` (the OAuth clients the Gateway holds for apps) and the
|
|
17
|
+
* MCP apps' `<ID>_MCP_TOKEN`: `GOOGLE_SIGNIN_CLIENT_ID` is the sign-in
|
|
18
|
+
* provider's, `GOOGLE_WORKSPACE_CLIENT_ID` the OAuth client apps use, and
|
|
19
|
+
* a registered provider row or an app manifest can never claim a name in
|
|
20
|
+
* the family (isSignInSettingName).
|
|
21
|
+
*
|
|
22
|
+
* The settings are Worker secrets, set under the Cloudflare login (`everyapp
|
|
23
|
+
* signin add`, or `secret set`), never from the admin UI or an agent
|
|
24
|
+
* connection: a stolen session can't add a way in.
|
|
25
|
+
*/
|
|
26
|
+
export const SIGN_IN_PROVIDER_IDS = [
|
|
27
|
+
"google",
|
|
28
|
+
"microsoft",
|
|
29
|
+
"github",
|
|
30
|
+
"apple",
|
|
31
|
+
"cloudflare",
|
|
32
|
+
"oidc",
|
|
33
|
+
];
|
|
34
|
+
/** The path Better Auth serves the provider's callback on, under the Gateway's URL. */
|
|
35
|
+
export function signInCallbackPath(id) {
|
|
36
|
+
return `/api/auth/callback/${id}`;
|
|
37
|
+
}
|
|
38
|
+
/** The redirect URL to register with the provider, for a Gateway at `gatewayUrl`. */
|
|
39
|
+
export function signInCallbackUrl(gatewayUrl, id) {
|
|
40
|
+
return `${gatewayUrl.replace(/\/+$/, "")}${signInCallbackPath(id)}`;
|
|
41
|
+
}
|
|
42
|
+
function settingName(id, field) {
|
|
43
|
+
return `${id.toUpperCase()}_SIGNIN_${field}`;
|
|
44
|
+
}
|
|
45
|
+
function clientPair(id, what) {
|
|
46
|
+
return [
|
|
47
|
+
{
|
|
48
|
+
name: settingName(id, "CLIENT_ID"),
|
|
49
|
+
role: "clientId",
|
|
50
|
+
required: true,
|
|
51
|
+
plain: true,
|
|
52
|
+
what: what.clientId,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: settingName(id, "CLIENT_SECRET"),
|
|
56
|
+
role: "clientSecret",
|
|
57
|
+
required: true,
|
|
58
|
+
plain: false,
|
|
59
|
+
what: what.clientSecret,
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
const IDENTITY_SCOPES = ["openid", "email", "profile"];
|
|
64
|
+
export const SIGN_IN_PROVIDERS = {
|
|
65
|
+
google: {
|
|
66
|
+
id: "google",
|
|
67
|
+
label: "Google",
|
|
68
|
+
console: "https://console.cloud.google.com/apis/credentials",
|
|
69
|
+
appNoun: "OAuth client ID (Web application)",
|
|
70
|
+
settings: clientPair("google", {
|
|
71
|
+
clientId: "The OAuth client's Client ID (ends in .apps.googleusercontent.com)",
|
|
72
|
+
clientSecret: "The OAuth client's Client secret",
|
|
73
|
+
}),
|
|
74
|
+
scopes: IDENTITY_SCOPES,
|
|
75
|
+
emailClaim: "the ID token's `email`, counted as verified only when its `email_verified` is true (every Google account's own address is)",
|
|
76
|
+
setup: "setup/signin-google.md",
|
|
77
|
+
notes: [
|
|
78
|
+
"An OAuth consent screen still in Testing only signs in the test users listed on it; publish it for everyone else.",
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
microsoft: {
|
|
82
|
+
id: "microsoft",
|
|
83
|
+
label: "Microsoft",
|
|
84
|
+
console: "https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade",
|
|
85
|
+
appNoun: "App registration",
|
|
86
|
+
settings: [
|
|
87
|
+
...clientPair("microsoft", {
|
|
88
|
+
clientId: "The app registration's Application (client) ID",
|
|
89
|
+
clientSecret: "A client secret from Certificates & secrets (it expires; 24 months at most)",
|
|
90
|
+
}),
|
|
91
|
+
{
|
|
92
|
+
name: settingName("microsoft", "TENANT"),
|
|
93
|
+
role: "tenant",
|
|
94
|
+
required: false,
|
|
95
|
+
plain: true,
|
|
96
|
+
what: "The Directory (tenant) ID to pin sign-in to your own directory; unset means any Microsoft account (common), which then needs the xms_edov claim",
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
scopes: IDENTITY_SCOPES,
|
|
100
|
+
emailClaim: "the ID token's `email`, counted as verified when MICROSOFT_SIGNIN_TENANT pins your own directory, or the token carries `xms_edov: true` (the optional claim that says the domain's owner verified it), `email_verified: true`, a matching `verified_primary_email`, or comes from a personal Microsoft account",
|
|
101
|
+
setup: "setup/signin-microsoft.md",
|
|
102
|
+
notes: [
|
|
103
|
+
"Without MICROSOFT_SIGNIN_TENANT, add the optional claims `email` and `xms_edov` under Token configuration, or every sign-in is refused as unverified: any tenant's admin can put any address on their users.",
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
github: {
|
|
107
|
+
id: "github",
|
|
108
|
+
label: "GitHub",
|
|
109
|
+
console: "https://github.com/settings/developers",
|
|
110
|
+
appNoun: "OAuth App",
|
|
111
|
+
settings: clientPair("github", {
|
|
112
|
+
clientId: "The OAuth App's Client ID",
|
|
113
|
+
clientSecret: "A client secret generated on the OAuth App",
|
|
114
|
+
}),
|
|
115
|
+
scopes: ["read:user", "user:email"],
|
|
116
|
+
emailClaim: "the primary address from GitHub's emails API, counted as verified only when GitHub marks it verified",
|
|
117
|
+
setup: "setup/signin-github.md",
|
|
118
|
+
notes: [
|
|
119
|
+
"GitHub Apps are something else: make an OAuth App (Settings → Developer settings → OAuth Apps).",
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
apple: {
|
|
123
|
+
id: "apple",
|
|
124
|
+
label: "Apple",
|
|
125
|
+
console: "https://developer.apple.com/account/resources/identifiers/list/serviceId",
|
|
126
|
+
appNoun: "Services ID",
|
|
127
|
+
settings: clientPair("apple", {
|
|
128
|
+
clientId: "The Services ID's identifier (com.example.gateway)",
|
|
129
|
+
clientSecret: "The client secret JWT you generate from your Sign in with Apple key (ES256; valid six months at most, then generate it again)",
|
|
130
|
+
}),
|
|
131
|
+
scopes: ["email", "name"],
|
|
132
|
+
emailClaim: "the ID token's `email`, counted as verified only when its `email_verified` is true; someone who chose Hide My Email arrives as a @privaterelay.appleid.com address, which no invitation names",
|
|
133
|
+
setup: "setup/signin-apple.md",
|
|
134
|
+
notes: [
|
|
135
|
+
"Apple returns to the Gateway with a POST; behind the outer ring, `everyapp access on` leaves /api/auth/callback/apple public (it only redirects to the same URL as a GET, which Access then checks).",
|
|
136
|
+
"The client secret is a JWT that expires within six months: generate a new one before then or sign-in stops.",
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
cloudflare: {
|
|
140
|
+
id: "cloudflare",
|
|
141
|
+
label: "Cloudflare",
|
|
142
|
+
console: "https://dash.cloudflare.com/?to=/:account/oauth-clients",
|
|
143
|
+
appNoun: "OAuth client (Manage Account → OAuth clients)",
|
|
144
|
+
settings: clientPair("cloudflare", {
|
|
145
|
+
clientId: "The OAuth client's Client ID",
|
|
146
|
+
clientSecret: "The OAuth client's Client secret",
|
|
147
|
+
}),
|
|
148
|
+
scopes: ["user-details.read"],
|
|
149
|
+
emailClaim: "the Cloudflare API's /user `email` (the account's sign-in address). Cloudflare reports no verified flag, so the email counts as verified on the strength of the client being private: only members of your Cloudflare account can authorize it, and they got in by accepting an invitation sent to that address",
|
|
150
|
+
setup: "setup/signin-cloudflare.md",
|
|
151
|
+
notes: [
|
|
152
|
+
"Keep the client private (the default): a public client lets any Cloudflare user sign in, and Cloudflare says nothing about whether their address is verified. Making a client public is permanent.",
|
|
153
|
+
"The Cloudflare account's members sign in; for everyone else use Cloudflare Access's one-time PIN (`everyapp access on`) or another provider.",
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
oidc: {
|
|
157
|
+
id: "oidc",
|
|
158
|
+
label: "SSO",
|
|
159
|
+
console: "your identity provider's admin console",
|
|
160
|
+
appNoun: "OpenID Connect client (web application, authorization code)",
|
|
161
|
+
settings: [
|
|
162
|
+
{
|
|
163
|
+
name: settingName("oidc", "ISSUER"),
|
|
164
|
+
role: "issuer",
|
|
165
|
+
required: true,
|
|
166
|
+
plain: true,
|
|
167
|
+
what: "The issuer URL (https://…), which serves /.well-known/openid-configuration",
|
|
168
|
+
},
|
|
169
|
+
...clientPair("oidc", {
|
|
170
|
+
clientId: "The client ID",
|
|
171
|
+
clientSecret: "The client secret",
|
|
172
|
+
}),
|
|
173
|
+
{
|
|
174
|
+
name: settingName("oidc", "LABEL"),
|
|
175
|
+
role: "label",
|
|
176
|
+
required: false,
|
|
177
|
+
plain: true,
|
|
178
|
+
what: 'The button text after "Continue with" (default "SSO")',
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
scopes: IDENTITY_SCOPES,
|
|
182
|
+
emailClaim: "the ID token's `email` (else the userinfo endpoint's), counted as verified only when `email_verified` is true",
|
|
183
|
+
setup: "setup/signin-oidc.md",
|
|
184
|
+
notes: [
|
|
185
|
+
"Cloudflare Access has its own settings (CLOUDFLARE_ACCESS_OIDC_*, `everyapp access`): use those for Access, this for Okta, Keycloak, Auth0, Authentik, Google Workspace as an OIDC issuer and the like. For Microsoft Entra ID use the `microsoft` provider: Entra's ID tokens carry no `email_verified`, so through this entry every sign-in would be refused as unverified.",
|
|
186
|
+
"ID tokens must be signed with RS256 (every major provider's default).",
|
|
187
|
+
],
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
/** The catalog in listing order. */
|
|
191
|
+
export const SIGN_IN_PROVIDER_LIST = SIGN_IN_PROVIDER_IDS.map((id) => SIGN_IN_PROVIDERS[id]);
|
|
192
|
+
export function isSignInProviderId(value) {
|
|
193
|
+
return SIGN_IN_PROVIDER_IDS.includes(value);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Every setting a sign-in provider reads, in catalog order: what `everyapp
|
|
197
|
+
* secret set` accepts for the Gateway, and what the Gateway's dev config
|
|
198
|
+
* declares.
|
|
199
|
+
*/
|
|
200
|
+
export const SIGN_IN_GATEWAY_SETTINGS = SIGN_IN_PROVIDER_LIST.flatMap((provider) => provider.settings.map((setting) => setting.name));
|
|
201
|
+
/** The plain (non-credential) ones among them: ids, the issuer, the label, the tenant. */
|
|
202
|
+
export const PLAIN_SIGN_IN_SETTINGS = SIGN_IN_PROVIDER_LIST.flatMap((provider) => provider.settings
|
|
203
|
+
.filter((setting) => setting.plain)
|
|
204
|
+
.map((setting) => setting.name));
|
|
205
|
+
/**
|
|
206
|
+
* The family: any name of the shape `<ID>_SIGNIN_<FIELD>`. Reserved for the
|
|
207
|
+
* catalog above, whether or not an entry reads the name today, so no
|
|
208
|
+
* registered provider row and no app manifest can ever take one.
|
|
209
|
+
*/
|
|
210
|
+
export const SIGN_IN_SETTING_PATTERN = /^[A-Z][A-Z0-9_]*_SIGNIN_(CLIENT_ID|CLIENT_SECRET|ISSUER|LABEL|TENANT)$/;
|
|
211
|
+
export function isSignInSettingName(name) {
|
|
212
|
+
return SIGN_IN_SETTING_PATTERN.test(name);
|
|
213
|
+
}
|
|
214
|
+
/** The provider a setting belongs to, if one reads it. */
|
|
215
|
+
export function signInProviderOfSetting(name) {
|
|
216
|
+
for (const provider of SIGN_IN_PROVIDER_LIST) {
|
|
217
|
+
if (provider.settings.some((setting) => setting.name === name)) {
|
|
218
|
+
return provider;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* A provider's state from which of its settings exist: on when every
|
|
225
|
+
* required one is set, off when none at all is, incomplete in between (the
|
|
226
|
+
* Gateway refuses to half-configure a sign-in: the provider is off and the
|
|
227
|
+
* problem is reported).
|
|
228
|
+
*/
|
|
229
|
+
export function signInProviderState(provider, isSet) {
|
|
230
|
+
const set = provider.settings
|
|
231
|
+
.filter((setting) => isSet(setting.name))
|
|
232
|
+
.map((setting) => setting.name);
|
|
233
|
+
const unset = provider.settings
|
|
234
|
+
.filter((setting) => setting.required && !isSet(setting.name))
|
|
235
|
+
.map((setting) => setting.name);
|
|
236
|
+
const status = unset.length === 0 ? "on" : set.length === 0 ? "off" : "incomplete";
|
|
237
|
+
// `missing` names what a half-set provider still needs; a provider nobody
|
|
238
|
+
// started setting up isn't missing anything, it is off.
|
|
239
|
+
return {
|
|
240
|
+
id: provider.id,
|
|
241
|
+
status,
|
|
242
|
+
missing: status === "incomplete" ? unset : [],
|
|
243
|
+
set,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ai()`: the Gateway's default chat model for an app that needs "a model"
|
|
3
|
+
* rather than one provider (docs/design/2026-10-model-providers.md). The
|
|
4
|
+
* manifest says `ai: { chat: true }` (or `{ chat: { why } }`); the Gateway's
|
|
5
|
+
* operator decides which provider and model that is (`everyapp ai
|
|
6
|
+
* default`, else OpenRouter → Workers AI → OpenAI → …, the first with its
|
|
7
|
+
* key set), and the app never names either: it sends OpenAI-shaped chat
|
|
8
|
+
* completions (and embeddings) to `/api/ai/default/v1/…` with `model:
|
|
9
|
+
* "default"` or no model at all, and the Gateway fills the model in.
|
|
10
|
+
*
|
|
11
|
+
* An OpenAI client takes `baseURL` and `fetch` as they are:
|
|
12
|
+
*
|
|
13
|
+
* const { baseURL, fetch, model } = ai({ env, for: request });
|
|
14
|
+
* const client = new OpenAI({ baseURL, fetch, apiKey: "gateway-managed" });
|
|
15
|
+
* await client.chat.completions.create({ model, messages });
|
|
16
|
+
*
|
|
17
|
+
* In local development with no Gateway, the developer's own key in
|
|
18
|
+
* `.dev.vars` decides the provider by the same order (createGatewayFetch's
|
|
19
|
+
* fallback). An app that needs one provider in particular keeps listing it
|
|
20
|
+
* under `providers` and calling `/api/ai/<provider>/…`.
|
|
21
|
+
*/
|
|
22
|
+
import { AI_DEFAULT_MODEL } from "../internal/index.js";
|
|
23
|
+
import { type CreateGatewayFetchOptions } from "./gatewayFetch.js";
|
|
24
|
+
export interface AiClient {
|
|
25
|
+
/** `http://every-app-gateway.internal/api/ai/default/v1`: an OpenAI client's base URL. */
|
|
26
|
+
baseURL: string;
|
|
27
|
+
/** The fetch that reaches the Gateway (or, in dev, the provider directly). */
|
|
28
|
+
fetch: typeof fetch;
|
|
29
|
+
/** The model name that means "whatever the Gateway's default is": `default`. */
|
|
30
|
+
model: typeof AI_DEFAULT_MODEL;
|
|
31
|
+
/** The default route's chat completions URL, for a plain `fetch`. */
|
|
32
|
+
chatCompletionsUrl: string;
|
|
33
|
+
/** The default route's embeddings URL, for a plain `fetch`. */
|
|
34
|
+
embeddingsUrl: string;
|
|
35
|
+
}
|
|
36
|
+
/** The base URL of the default route, as the SDK and the docs name it. */
|
|
37
|
+
export declare const AI_DEFAULT_BASE_URL = "http://every-app-gateway.internal/api/ai/default/v1";
|
|
38
|
+
/**
|
|
39
|
+
* The Gateway's default chat model as a client: a base URL, a fetch and
|
|
40
|
+
* the model name to send. Throws `ConfigurationError` where
|
|
41
|
+
* `createGatewayFetch` does (no binding and no dev key) and
|
|
42
|
+
* `AttributionError` where a shared app's call says nobody's.
|
|
43
|
+
*/
|
|
44
|
+
export declare function ai(options: CreateGatewayFetchOptions): AiClient;
|
|
45
|
+
//# sourceMappingURL=ai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/server/ai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,gBAAgB,EAAuB,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,QAAQ;IACvB,0FAA0F;IAC1F,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,gFAAgF;IAChF,KAAK,EAAE,OAAO,gBAAgB,CAAC;IAC/B,qEAAqE;IACrE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,wDAAuD,CAAC;AAExF;;;;;GAKG;AACH,wBAAgB,EAAE,CAAC,OAAO,EAAE,yBAAyB,GAAG,QAAQ,CAQ/D"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ai()`: the Gateway's default chat model for an app that needs "a model"
|
|
3
|
+
* rather than one provider (docs/design/2026-10-model-providers.md). The
|
|
4
|
+
* manifest says `ai: { chat: true }` (or `{ chat: { why } }`); the Gateway's
|
|
5
|
+
* operator decides which provider and model that is (`everyapp ai
|
|
6
|
+
* default`, else OpenRouter → Workers AI → OpenAI → …, the first with its
|
|
7
|
+
* key set), and the app never names either: it sends OpenAI-shaped chat
|
|
8
|
+
* completions (and embeddings) to `/api/ai/default/v1/…` with `model:
|
|
9
|
+
* "default"` or no model at all, and the Gateway fills the model in.
|
|
10
|
+
*
|
|
11
|
+
* An OpenAI client takes `baseURL` and `fetch` as they are:
|
|
12
|
+
*
|
|
13
|
+
* const { baseURL, fetch, model } = ai({ env, for: request });
|
|
14
|
+
* const client = new OpenAI({ baseURL, fetch, apiKey: "gateway-managed" });
|
|
15
|
+
* await client.chat.completions.create({ model, messages });
|
|
16
|
+
*
|
|
17
|
+
* In local development with no Gateway, the developer's own key in
|
|
18
|
+
* `.dev.vars` decides the provider by the same order (createGatewayFetch's
|
|
19
|
+
* fallback). An app that needs one provider in particular keeps listing it
|
|
20
|
+
* under `providers` and calling `/api/ai/<provider>/…`.
|
|
21
|
+
*/
|
|
22
|
+
import { AI_DEFAULT_MODEL, AI_DEFAULT_PROVIDER } from "../internal/index.js";
|
|
23
|
+
import { BINDING_ORIGIN, createGatewayFetch, } from "./gatewayFetch.js";
|
|
24
|
+
/** The base URL of the default route, as the SDK and the docs name it. */
|
|
25
|
+
export const AI_DEFAULT_BASE_URL = `${BINDING_ORIGIN}/api/ai/${AI_DEFAULT_PROVIDER}/v1`;
|
|
26
|
+
/**
|
|
27
|
+
* The Gateway's default chat model as a client: a base URL, a fetch and
|
|
28
|
+
* the model name to send. Throws `ConfigurationError` where
|
|
29
|
+
* `createGatewayFetch` does (no binding and no dev key) and
|
|
30
|
+
* `AttributionError` where a shared app's call says nobody's.
|
|
31
|
+
*/
|
|
32
|
+
export function ai(options) {
|
|
33
|
+
return {
|
|
34
|
+
baseURL: AI_DEFAULT_BASE_URL,
|
|
35
|
+
fetch: createGatewayFetch(options),
|
|
36
|
+
model: AI_DEFAULT_MODEL,
|
|
37
|
+
chatCompletionsUrl: `${AI_DEFAULT_BASE_URL}/chat/completions`,
|
|
38
|
+
embeddingsUrl: `${AI_DEFAULT_BASE_URL}/embeddings`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ConnectionAccount } from "../internal/index.js";
|
|
2
|
+
export interface ConnectUrlOptions {
|
|
3
|
+
/** The Worker env: `GATEWAY_URL`, which every deployed Worker and `everyapp dev` set. */
|
|
4
|
+
env: object;
|
|
5
|
+
/** The OAuth provider's id (`google-workspace`, `github`). */
|
|
6
|
+
provider: string;
|
|
7
|
+
/**
|
|
8
|
+
* Where to send the person afterwards: the app's own URL (absolute) or
|
|
9
|
+
* a path on the Gateway. Absent: Settings → Connected accounts.
|
|
10
|
+
*/
|
|
11
|
+
returnTo?: string;
|
|
12
|
+
/** Whose connection to make: the person's (default) or the organization's (owner or admin). */
|
|
13
|
+
account?: ConnectionAccount;
|
|
14
|
+
/** Scope sets to ask for; absent: the union every active app that lists the provider declares. */
|
|
15
|
+
sets?: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
/** The path of the connect page for `provider` on the Gateway. */
|
|
18
|
+
export declare function connectPath(provider: string): string;
|
|
19
|
+
/** The absolute URL that starts the Gateway-owned flow for `provider`. */
|
|
20
|
+
export declare function connectUrl({ env, provider, returnTo, account, sets, }: ConnectUrlOptions): string;
|
|
21
|
+
//# sourceMappingURL=connectUrl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectUrl.d.ts","sourceRoot":"","sources":["../../src/server/connectUrl.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,WAAW,iBAAiB;IAChC,yFAAyF;IACzF,GAAG,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,kGAAkG;IAClG,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,EACzB,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,IAAI,GACL,EAAE,iBAAiB,GAAG,MAAM,CAmB5B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an app sends a person to connect an OAuth provider the Gateway
|
|
3
|
+
* runs the flow for (docs/design/2026-10-oauth-providers.md section 5):
|
|
4
|
+
* `<gateway>/connect/<id>?return=<back here>&account=<user|organization>`.
|
|
5
|
+
* The Gateway checks the session, asks the provider for the union of the
|
|
6
|
+
* sets every active app declares, finishes on its own callback and sends
|
|
7
|
+
* the browser back to `returnTo`, which must be a path on the Gateway or
|
|
8
|
+
* an https URL on one of its app hosts (in local dev also localhost).
|
|
9
|
+
*/
|
|
10
|
+
import { ConfigurationError } from "../internal/index.js";
|
|
11
|
+
/** The path of the connect page for `provider` on the Gateway. */
|
|
12
|
+
export function connectPath(provider) {
|
|
13
|
+
return `/connect/${encodeURIComponent(provider)}`;
|
|
14
|
+
}
|
|
15
|
+
/** The absolute URL that starts the Gateway-owned flow for `provider`. */
|
|
16
|
+
export function connectUrl({ env, provider, returnTo, account, sets, }) {
|
|
17
|
+
const values = env;
|
|
18
|
+
const gateway = values["GATEWAY_URL"];
|
|
19
|
+
if (typeof gateway !== "string" || !gateway.trim()) {
|
|
20
|
+
throw new ConfigurationError("connectUrl() needs GATEWAY_URL in the Worker env: the deploy sets it, and everyapp dev sets it to the local gateway.");
|
|
21
|
+
}
|
|
22
|
+
let base;
|
|
23
|
+
try {
|
|
24
|
+
base = new URL(gateway.trim());
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new ConfigurationError(`GATEWAY_URL isn't a URL: ${gateway}`);
|
|
28
|
+
}
|
|
29
|
+
const url = new URL(connectPath(provider), base.origin);
|
|
30
|
+
if (returnTo)
|
|
31
|
+
url.searchParams.set("return", returnTo);
|
|
32
|
+
if (account)
|
|
33
|
+
url.searchParams.set("account", account);
|
|
34
|
+
if (sets && sets.length > 0)
|
|
35
|
+
url.searchParams.set("sets", sets.join(","));
|
|
36
|
+
return url.toString();
|
|
37
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gatewayFetch.d.ts","sourceRoot":"","sources":["../../src/server/gatewayFetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gatewayFetch.d.ts","sourceRoot":"","sources":["../../src/server/gatewayFetch.ts"],"names":[],"mappings":"AAaA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAE1B,eAAO,MAAM,cAAc,sCAAsC,CAAC;AAGlE,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACxE;AAED,MAAM,WAAW,eAAe;IAC9B,iBAAiB,CAAC,EAAE,qBAAqB,CAAC;IAC1C,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,kEAAkE;IAClE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oFAAoF;IACpF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,eAAe,CAAC;IACrB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,GAAG,EACH,GAAG,EAAE,MAAM,GACZ,EAAE,yBAAyB,GAAG,OAAO,KAAK,CAoE1C;AAwCD,sFAAsF;AACtF,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,OAAO,GACf,OAAO,CAUT"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { aiProviderSettings, authorizationOf, ConfigurationError, DEV_AI_PROVIDERS, devAiProvider, joinProviderUrl, } from "../internal/index.js";
|
|
1
|
+
import { AI_DEFAULT_MODEL, AI_DEFAULT_PROVIDER, AI_DEFAULT_ROUTES, aiProviderSettings, authorizationOf, ConfigurationError, DEV_AI_PROVIDERS, devAiProvider, joinProviderUrl, resolveAiDefault, } from "../internal/index.js";
|
|
2
2
|
import { applyAttribution, checkAttribution, } from "./attribution.js";
|
|
3
3
|
export const BINDING_ORIGIN = "http://every-app-gateway.internal";
|
|
4
4
|
const AI_PROXY_PREFIX = "/api/ai/";
|
|
@@ -28,7 +28,8 @@ export function createGatewayFetch({ env, for: target, }) {
|
|
|
28
28
|
const bindingRequest = streamingRequest(`${BINDING_ORIGIN}${url.pathname}${url.search}`, outbound, headers);
|
|
29
29
|
return binding.fetch(bindingRequest);
|
|
30
30
|
}
|
|
31
|
-
const
|
|
31
|
+
const direct = directProviderPath(outbound.url, env);
|
|
32
|
+
const { provider, spec, path, search } = direct;
|
|
32
33
|
const dev = devProviders[provider];
|
|
33
34
|
if (!dev) {
|
|
34
35
|
throw new ConfigurationError(`Set ${settingsNames(spec)} in .dev.vars to call ${provider} in local development.`);
|
|
@@ -37,6 +38,11 @@ export function createGatewayFetch({ env, for: target, }) {
|
|
|
37
38
|
if (!url)
|
|
38
39
|
throw new ConfigurationError("Invalid provider proxy path.");
|
|
39
40
|
applyAttribution(headers, undefined);
|
|
41
|
+
// The default route in dev: the model filled in as the gateway would.
|
|
42
|
+
let body = outbound;
|
|
43
|
+
if (direct.fillModel !== null) {
|
|
44
|
+
body = await withModel(outbound, direct.fillModel, headers);
|
|
45
|
+
}
|
|
40
46
|
// The developer's key, put where the provider's entry says (a bearer
|
|
41
47
|
// token for the three today), as the gateway would put its own.
|
|
42
48
|
const auth = authorizationOf(spec.auth, { [spec.keyEnv]: dev.key });
|
|
@@ -46,11 +52,44 @@ export function createGatewayFetch({ env, for: target, }) {
|
|
|
46
52
|
for (const [name, value] of Object.entries(auth?.query ?? {})) {
|
|
47
53
|
url.searchParams.set(name, value);
|
|
48
54
|
}
|
|
49
|
-
const response = await fetch(streamingRequest(url.toString(),
|
|
55
|
+
const response = await fetch(streamingRequest(url.toString(), body, headers));
|
|
50
56
|
// What the gateway does to the provider's answer, so dev behaves alike.
|
|
51
57
|
return spec.normalizeResponse?.(path, response) ?? response;
|
|
52
58
|
};
|
|
53
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* `source` with `model` put into its JSON body where the app named none
|
|
62
|
+
* or named `default`, as the gateway's default route does. A body that
|
|
63
|
+
* isn't a JSON object goes through as it is.
|
|
64
|
+
*/
|
|
65
|
+
async function withModel(source, model, headers) {
|
|
66
|
+
if (!canIncludeBody(source.method) || !source.body)
|
|
67
|
+
return source;
|
|
68
|
+
const text = await source.clone().text();
|
|
69
|
+
let payload;
|
|
70
|
+
try {
|
|
71
|
+
payload = JSON.parse(text);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return source;
|
|
75
|
+
}
|
|
76
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
77
|
+
return source;
|
|
78
|
+
}
|
|
79
|
+
const record = payload;
|
|
80
|
+
if (record["model"] === undefined ||
|
|
81
|
+
record["model"] === null ||
|
|
82
|
+
record["model"] === AI_DEFAULT_MODEL) {
|
|
83
|
+
record["model"] = model;
|
|
84
|
+
}
|
|
85
|
+
headers.delete("content-length");
|
|
86
|
+
return new Request(source.url, {
|
|
87
|
+
method: source.method,
|
|
88
|
+
headers,
|
|
89
|
+
body: JSON.stringify(record),
|
|
90
|
+
signal: source.signal,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
54
93
|
/** A copy of `source` aimed at `url`, streaming its body rather than buffering it. */
|
|
55
94
|
export function streamingRequest(url, source, headers) {
|
|
56
95
|
const body = canIncludeBody(source.method) ? source.body : undefined;
|
|
@@ -82,19 +121,44 @@ function localProviders(env) {
|
|
|
82
121
|
}
|
|
83
122
|
return providers;
|
|
84
123
|
}
|
|
85
|
-
function directProviderPath(input) {
|
|
124
|
+
function directProviderPath(input, env) {
|
|
86
125
|
const incoming = new URL(input);
|
|
87
126
|
const match = incoming.pathname.match(/^\/api\/ai\/([a-z][a-z0-9-]*)(\/.*)?$/);
|
|
88
|
-
|
|
127
|
+
let provider = match?.[1];
|
|
128
|
+
let path = match?.[2] || "/";
|
|
129
|
+
let fillModel = null;
|
|
130
|
+
if (provider === AI_DEFAULT_PROVIDER) {
|
|
131
|
+
// The default in dev, by the gateway's rule on the developer's own
|
|
132
|
+
// `.dev.vars`: the first provider of the order with every setting set.
|
|
133
|
+
const values = env;
|
|
134
|
+
const resolution = resolveAiDefault({
|
|
135
|
+
choice: null,
|
|
136
|
+
isSet: (name) => typeof values[name] === "string" &&
|
|
137
|
+
values[name].trim().length > 0,
|
|
138
|
+
});
|
|
139
|
+
if (!resolution.configured) {
|
|
140
|
+
throw new ConfigurationError(`Set ${resolution.settings.join(" and ")} (or another model provider's key) in .dev.vars to call the default model in local development.`);
|
|
141
|
+
}
|
|
142
|
+
const route = path === AI_DEFAULT_ROUTES.chat
|
|
143
|
+
? resolution.chat
|
|
144
|
+
: path === AI_DEFAULT_ROUTES.embeddings
|
|
145
|
+
? resolution.embeddings
|
|
146
|
+
: undefined;
|
|
147
|
+
if (!route) {
|
|
148
|
+
throw new ConfigurationError(`The default model serves ${AI_DEFAULT_ROUTES.chat} and ${AI_DEFAULT_ROUTES.embeddings} only; call /api/ai/<provider>/… for anything else.`);
|
|
149
|
+
}
|
|
150
|
+
provider = resolution.provider;
|
|
151
|
+
path = route.path;
|
|
152
|
+
fillModel = path === resolution.chat.path ? resolution.model : route.model;
|
|
153
|
+
}
|
|
89
154
|
const spec = provider ? devAiProvider(provider) : undefined;
|
|
90
155
|
if (!provider || !spec) {
|
|
91
|
-
throw new ConfigurationError(`Direct local provider fallback only supports ${listOf(Object.keys(DEV_AI_PROVIDERS).map((name) => `${AI_PROXY_PREFIX}${name}`), "and")} paths.`);
|
|
156
|
+
throw new ConfigurationError(`Direct local provider fallback only supports ${listOf([AI_DEFAULT_PROVIDER, ...Object.keys(DEV_AI_PROVIDERS)].map((name) => `${AI_PROXY_PREFIX}${name}`), "and")} paths.`);
|
|
92
157
|
}
|
|
93
|
-
const path = match?.[2] || "/";
|
|
94
158
|
if (path.startsWith("//") || path.includes("\\")) {
|
|
95
159
|
throw new ConfigurationError("Invalid provider proxy path.");
|
|
96
160
|
}
|
|
97
|
-
return { provider, spec, path, search: incoming.search };
|
|
161
|
+
return { provider, spec, path, search: incoming.search, fillModel };
|
|
98
162
|
}
|
|
99
163
|
/** A provider's settings as a person reads them: `KEY`, or `KEY and SETTING`. */
|
|
100
164
|
function settingsNames(spec, conjunction = "and") {
|
package/dist/server/index.d.ts
CHANGED
|
@@ -6,13 +6,15 @@
|
|
|
6
6
|
export { ConfigurationError, IdentityError, everyApp, getEveryAppUser, hasScope, requireEveryAppUser, type EveryAppOptions, type EveryAppManifestLike, type EveryAppHandler, type EveryAppUser, type IdentityResult, } from "./everyApp.js";
|
|
7
7
|
export { AttributionError, type GatewayCallFor } from "./attribution.js";
|
|
8
8
|
export { authorizeUrl, type AuthorizeUrlOptions } from "./authorizeUrl.js";
|
|
9
|
+
export { connectPath, connectUrl, type ConnectUrlOptions, } from "./connectUrl.js";
|
|
9
10
|
export { createGatewayFetch, type CreateGatewayFetchOptions, type GatewayFetchEnv, } from "./gatewayFetch.js";
|
|
10
|
-
export {
|
|
11
|
+
export { ai, AI_DEFAULT_BASE_URL, type AiClient } from "./ai.js";
|
|
12
|
+
export { GatewayRefusalError, gatewayRefusal, devAccessTokenName, integrationFetch, integrationStatus, type EmailIntegrationStatus, type GatewayRefusal, type IntegrationFetchOptions, type IntegrationStatus, type IntegrationStatusOf, type OAuthClientIntegrationStatus, } from "./integrationFetch.js";
|
|
11
13
|
export { nodeServerHandler, type NodeServer, type NodeServerHandlerOptions, } from "./nodeServer.js";
|
|
12
14
|
export { sendEmail, type SendEmailOptions } from "./sendEmail.js";
|
|
13
15
|
export { listMembers, type ListMembersOptions } from "./listMembers.js";
|
|
14
16
|
export { emit, type EmitOptions } from "./emit.js";
|
|
15
|
-
export type { ApiKeyCapabilityId, CapabilityId, OAuthClientCapabilityId, EmailAddressInput, EmailAttachmentInput, SendEmailMessage, SendEmailResult, ListMembersResult, OrganizationMember, OrganizationMemberRole, EmitEventResult, } from "../internal/index.js";
|
|
17
|
+
export type { ApiKeyCapabilityId, CapabilityId, OAuthClientCapabilityId, ConnectionAccount, EmailAddressInput, EmailAttachmentInput, SendEmailMessage, SendEmailResult, ListMembersResult, OrganizationMember, OrganizationMemberRole, EmitEventResult, } from "../internal/index.js";
|
|
16
18
|
export { ToolError, defineTools, toolResult, type DefineToolsOptions, type PlainToolSchema, type StandardSchemaWithJSON, type ToolContext, type ToolDefinition, type ToolResult, type ToolSchema, type ToolSet, } from "./tools.js";
|
|
17
19
|
export type { ToolRisk } from "../internal/index.js";
|
|
18
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,GAClC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,wBAAwB,GAC9B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,SAAS,EACT,WAAW,EACX,UAAU,EACV,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,OAAO,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EACL,WAAW,EACX,UAAU,EACV,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,GAClC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,wBAAwB,GAC9B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,SAAS,EACT,WAAW,EACX,UAAU,EACV,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,OAAO,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
export { ConfigurationError, IdentityError, everyApp, getEveryAppUser, hasScope, requireEveryAppUser, } from "./everyApp.js";
|
|
7
7
|
export { AttributionError } from "./attribution.js";
|
|
8
8
|
export { authorizeUrl } from "./authorizeUrl.js";
|
|
9
|
+
export { connectPath, connectUrl, } from "./connectUrl.js";
|
|
9
10
|
export { createGatewayFetch, } from "./gatewayFetch.js";
|
|
10
|
-
export {
|
|
11
|
+
export { ai, AI_DEFAULT_BASE_URL } from "./ai.js";
|
|
12
|
+
export { GatewayRefusalError, gatewayRefusal, devAccessTokenName, integrationFetch, integrationStatus, } from "./integrationFetch.js";
|
|
11
13
|
export { nodeServerHandler, } from "./nodeServer.js";
|
|
12
14
|
export { sendEmail } from "./sendEmail.js";
|
|
13
15
|
export { listMembers } from "./listMembers.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ApiKeyCapabilityId, type CapabilityId, type EmailCapabilityStatus, type OAuthClientCapabilityId } from "../internal/index.js";
|
|
1
|
+
import { type ApiKeyCapabilityId, type CapabilityId, type ConnectionAccount, type EmailCapabilityStatus, type OAuthClientCapabilityId } from "../internal/index.js";
|
|
2
2
|
import { type GatewayCallFor } from "./attribution.js";
|
|
3
3
|
export interface IntegrationFetchOptions {
|
|
4
4
|
/**
|
|
@@ -24,6 +24,13 @@ export interface IntegrationFetchOptions {
|
|
|
24
24
|
* pass one or the other ({@link AttributionError}).
|
|
25
25
|
*/
|
|
26
26
|
for?: GatewayCallFor;
|
|
27
|
+
/**
|
|
28
|
+
* For an OAuth provider the gateway holds connections for: whose
|
|
29
|
+
* connection the call uses, the person's (`user`, the default when a
|
|
30
|
+
* person is behind the call) or the organization's (`organization`,
|
|
31
|
+
* the default for background work). Sent as `x-everyapp-account`.
|
|
32
|
+
*/
|
|
33
|
+
account?: ConnectionAccount;
|
|
27
34
|
}
|
|
28
35
|
/**
|
|
29
36
|
* A `fetch` for one of the gateway's capabilities. Call the provider's real
|
|
@@ -47,7 +54,14 @@ export interface IntegrationFetchOptions {
|
|
|
47
54
|
* provider show <id> --save` writes it), put on the call as the gateway's
|
|
48
55
|
* spec says.
|
|
49
56
|
*/
|
|
50
|
-
export declare function integrationFetch({ env, provider, for: target, }: IntegrationFetchOptions): typeof fetch;
|
|
57
|
+
export declare function integrationFetch({ env, provider, for: target, account, }: IntegrationFetchOptions): typeof fetch;
|
|
58
|
+
/**
|
|
59
|
+
* The `.dev.vars` name of a held token for `provider` in local dev
|
|
60
|
+
* (`GOOGLE_WORKSPACE_ACCESS_TOKEN`, `GITHUB_ACCESS_TOKEN`): a token the
|
|
61
|
+
* developer obtained themselves, standing in for the connection the
|
|
62
|
+
* gateway would hold. Dev-only: the gateway never reads it.
|
|
63
|
+
*/
|
|
64
|
+
export declare function devAccessTokenName(provider: string): string;
|
|
51
65
|
export interface IntegrationStatus {
|
|
52
66
|
/** The app's manifest lists the capability. */
|
|
53
67
|
requested: boolean;
|
|
@@ -92,6 +106,29 @@ export interface OAuthClientIntegrationStatus extends IntegrationStatus {
|
|
|
92
106
|
scopes?: readonly string[];
|
|
93
107
|
/** Slack's `user_scope` strings, when the sets name any. */
|
|
94
108
|
userScopes?: readonly string[];
|
|
109
|
+
/**
|
|
110
|
+
* Which flows the client supports: `app` (the app runs authorize and
|
|
111
|
+
* callback itself and keeps the tokens, the social networks), `gateway`
|
|
112
|
+
* (the Gateway holds the connection; API calls go through
|
|
113
|
+
* `integrationFetch` with the token injected) or `both` (Google,
|
|
114
|
+
* Microsoft, Slack, Discord and every registered OAuth provider).
|
|
115
|
+
*/
|
|
116
|
+
flow?: "app" | "gateway" | "both";
|
|
117
|
+
/** Where a person connects on the Gateway: `/connect/<id>`; see `connectUrl()`. */
|
|
118
|
+
connectPath?: string;
|
|
119
|
+
/**
|
|
120
|
+
* The connection the caller's account would use (the person's, or the
|
|
121
|
+
* organization's for background work), or null when there is none yet;
|
|
122
|
+
* `reconnect` when it exists but lacks a set the app declares or has
|
|
123
|
+
* expired, so the person has to connect again.
|
|
124
|
+
*/
|
|
125
|
+
connection?: {
|
|
126
|
+
account: ConnectionAccount;
|
|
127
|
+
label: string | null;
|
|
128
|
+
scopeSets: readonly string[];
|
|
129
|
+
ready: boolean;
|
|
130
|
+
reconnect?: boolean;
|
|
131
|
+
} | null;
|
|
95
132
|
}
|
|
96
133
|
/** The status of a capability: email's carries its senders, an OAuth client's its id. */
|
|
97
134
|
export type IntegrationStatusOf<P extends string> = P extends "email" ? EmailIntegrationStatus : P extends OAuthClientCapabilityId ? OAuthClientIntegrationStatus : IntegrationStatus;
|