@every-app/sdk 0.1.14 → 0.3.0-rc.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.
Files changed (167) hide show
  1. package/README.md +608 -2
  2. package/dist/cloudflare/index.d.ts +21 -1
  3. package/dist/cloudflare/index.d.ts.map +1 -1
  4. package/dist/cloudflare/index.js +21 -1
  5. package/dist/cloudflare/sentinel.d.ts +69 -0
  6. package/dist/cloudflare/sentinel.d.ts.map +1 -0
  7. package/dist/cloudflare/sentinel.js +50 -0
  8. package/dist/cloudflare/worker.d.ts +511 -0
  9. package/dist/cloudflare/worker.d.ts.map +1 -0
  10. package/dist/cloudflare/worker.js +738 -0
  11. package/dist/dev/index.d.ts +8 -0
  12. package/dist/dev/index.d.ts.map +1 -0
  13. package/dist/dev/index.js +7 -0
  14. package/dist/dev/keypair.d.ts +24 -0
  15. package/dist/dev/keypair.d.ts.map +1 -0
  16. package/dist/dev/keypair.js +60 -0
  17. package/dist/internal/aiProviders.d.ts +67 -0
  18. package/dist/internal/aiProviders.d.ts.map +1 -0
  19. package/dist/internal/aiProviders.js +220 -0
  20. package/dist/internal/appSettings.d.ts +237 -0
  21. package/dist/internal/appSettings.d.ts.map +1 -0
  22. package/dist/internal/appSettings.js +374 -0
  23. package/dist/internal/capabilities.d.ts +1344 -0
  24. package/dist/internal/capabilities.d.ts.map +1 -0
  25. package/dist/internal/capabilities.js +1521 -0
  26. package/dist/internal/devProviders.d.ts +49 -0
  27. package/dist/internal/devProviders.d.ts.map +1 -0
  28. package/dist/internal/devProviders.js +62 -0
  29. package/dist/internal/email.d.ts +280 -0
  30. package/dist/internal/email.d.ts.map +1 -0
  31. package/dist/internal/email.js +613 -0
  32. package/dist/internal/events.d.ts +182 -0
  33. package/dist/internal/events.d.ts.map +1 -0
  34. package/dist/internal/events.js +324 -0
  35. package/dist/internal/gatewaySettings.d.ts +82 -0
  36. package/dist/internal/gatewaySettings.d.ts.map +1 -0
  37. package/dist/internal/gatewaySettings.js +209 -0
  38. package/dist/internal/identity.d.ts +88 -0
  39. package/dist/internal/identity.d.ts.map +1 -0
  40. package/dist/internal/identity.js +231 -0
  41. package/dist/internal/index.d.ts +19 -0
  42. package/dist/internal/index.d.ts.map +1 -0
  43. package/dist/internal/index.js +18 -0
  44. package/dist/internal/members.d.ts +35 -0
  45. package/dist/internal/members.d.ts.map +1 -0
  46. package/dist/internal/members.js +7 -0
  47. package/dist/internal/oauthClient.d.ts +63 -0
  48. package/dist/internal/oauthClient.d.ts.map +1 -0
  49. package/dist/internal/oauthClient.js +194 -0
  50. package/dist/internal/oauthScopes.d.ts +117 -0
  51. package/dist/internal/oauthScopes.d.ts.map +1 -0
  52. package/dist/internal/oauthScopes.js +416 -0
  53. package/dist/internal/organizationName.d.ts +18 -0
  54. package/dist/internal/organizationName.d.ts.map +1 -0
  55. package/dist/internal/organizationName.js +24 -0
  56. package/dist/internal/protocol.d.ts +195 -0
  57. package/dist/internal/protocol.d.ts.map +1 -0
  58. package/dist/internal/protocol.js +250 -0
  59. package/dist/internal/providerApps.d.ts +75 -0
  60. package/dist/internal/providerApps.d.ts.map +1 -0
  61. package/dist/internal/providerApps.js +59 -0
  62. package/dist/internal/providerRegistry.d.ts +147 -0
  63. package/dist/internal/providerRegistry.d.ts.map +1 -0
  64. package/dist/internal/providerRegistry.js +262 -0
  65. package/dist/internal/providerSpec.d.ts +55 -0
  66. package/dist/internal/providerSpec.d.ts.map +1 -0
  67. package/dist/internal/providerSpec.js +746 -0
  68. package/dist/internal/remoteMcp.d.ts +188 -0
  69. package/dist/internal/remoteMcp.d.ts.map +1 -0
  70. package/dist/internal/remoteMcp.js +543 -0
  71. package/dist/internal/tools.d.ts +115 -0
  72. package/dist/internal/tools.d.ts.map +1 -0
  73. package/dist/internal/tools.js +80 -0
  74. package/dist/server/attribution.d.ts +39 -0
  75. package/dist/server/attribution.d.ts.map +1 -0
  76. package/dist/server/attribution.js +67 -0
  77. package/dist/server/authorizeUrl.d.ts +43 -0
  78. package/dist/server/authorizeUrl.d.ts.map +1 -0
  79. package/dist/server/authorizeUrl.js +110 -0
  80. package/dist/server/emit.d.ts +63 -0
  81. package/dist/server/emit.d.ts.map +1 -0
  82. package/dist/server/emit.js +101 -0
  83. package/dist/server/everyApp.d.ts +81 -0
  84. package/dist/server/everyApp.d.ts.map +1 -0
  85. package/dist/server/everyApp.js +185 -0
  86. package/dist/server/gatewayFetch.d.ts +37 -0
  87. package/dist/server/gatewayFetch.d.ts.map +1 -0
  88. package/dist/server/gatewayFetch.js +115 -0
  89. package/dist/server/index.d.ts +18 -0
  90. package/dist/server/index.d.ts.map +1 -0
  91. package/dist/server/index.js +15 -0
  92. package/dist/server/integrationFetch.d.ts +131 -0
  93. package/dist/server/integrationFetch.d.ts.map +1 -0
  94. package/dist/server/integrationFetch.js +526 -0
  95. package/dist/server/listMembers.d.ts +32 -0
  96. package/dist/server/listMembers.d.ts.map +1 -0
  97. package/dist/server/listMembers.js +74 -0
  98. package/dist/server/nodeServer.d.ts +48 -0
  99. package/dist/server/nodeServer.d.ts.map +1 -0
  100. package/dist/server/nodeServer.js +45 -0
  101. package/dist/server/sendEmail.d.ts +39 -0
  102. package/dist/server/sendEmail.d.ts.map +1 -0
  103. package/dist/server/sendEmail.js +114 -0
  104. package/dist/server/tools.d.ts +184 -0
  105. package/dist/server/tools.d.ts.map +1 -0
  106. package/dist/server/tools.js +347 -0
  107. package/dist/server/toolsEndpoint.d.ts +32 -0
  108. package/dist/server/toolsEndpoint.d.ts.map +1 -0
  109. package/dist/server/toolsEndpoint.js +231 -0
  110. package/package.json +21 -31
  111. package/dist/cloudflare/getLocalD1Url.d.ts +0 -2
  112. package/dist/cloudflare/getLocalD1Url.d.ts.map +0 -1
  113. package/dist/cloudflare/getLocalD1Url.js +0 -40
  114. package/dist/cloudflare/lazyInit.d.ts +0 -22
  115. package/dist/cloudflare/lazyInit.d.ts.map +0 -1
  116. package/dist/cloudflare/lazyInit.js +0 -65
  117. package/dist/cloudflare/server/gateway.d.ts +0 -29
  118. package/dist/cloudflare/server/gateway.d.ts.map +0 -1
  119. package/dist/cloudflare/server/gateway.js +0 -69
  120. package/dist/cloudflare/server/index.d.ts +0 -3
  121. package/dist/cloudflare/server/index.d.ts.map +0 -1
  122. package/dist/cloudflare/server/index.js +0 -2
  123. package/dist/core/authenticatedFetch.d.ts +0 -9
  124. package/dist/core/authenticatedFetch.d.ts.map +0 -1
  125. package/dist/core/authenticatedFetch.js +0 -31
  126. package/dist/core/index.d.ts +0 -4
  127. package/dist/core/index.d.ts.map +0 -1
  128. package/dist/core/index.js +0 -2
  129. package/dist/core/sessionManager.d.ts +0 -58
  130. package/dist/core/sessionManager.d.ts.map +0 -1
  131. package/dist/core/sessionManager.js +0 -357
  132. package/dist/shared/bypassGatewayLocalOnly.d.ts +0 -15
  133. package/dist/shared/bypassGatewayLocalOnly.d.ts.map +0 -1
  134. package/dist/shared/bypassGatewayLocalOnly.js +0 -45
  135. package/dist/shared/parseMessagePayload.d.ts +0 -3
  136. package/dist/shared/parseMessagePayload.d.ts.map +0 -1
  137. package/dist/shared/parseMessagePayload.js +0 -18
  138. package/dist/tanstack/EmbeddedAppProvider.d.ts +0 -30
  139. package/dist/tanstack/EmbeddedAppProvider.d.ts.map +0 -1
  140. package/dist/tanstack/EmbeddedAppProvider.js +0 -57
  141. package/dist/tanstack/GatewayRequiredError.d.ts +0 -20
  142. package/dist/tanstack/GatewayRequiredError.d.ts.map +0 -1
  143. package/dist/tanstack/GatewayRequiredError.js +0 -91
  144. package/dist/tanstack/_internal/useEveryAppSession.d.ts +0 -18
  145. package/dist/tanstack/_internal/useEveryAppSession.d.ts.map +0 -1
  146. package/dist/tanstack/_internal/useEveryAppSession.js +0 -47
  147. package/dist/tanstack/index.d.ts +0 -4
  148. package/dist/tanstack/index.d.ts.map +0 -1
  149. package/dist/tanstack/index.js +0 -3
  150. package/dist/tanstack/server/authConfig.d.ts +0 -3
  151. package/dist/tanstack/server/authConfig.d.ts.map +0 -1
  152. package/dist/tanstack/server/authConfig.js +0 -13
  153. package/dist/tanstack/server/authenticateRequest.d.ts +0 -31
  154. package/dist/tanstack/server/authenticateRequest.d.ts.map +0 -1
  155. package/dist/tanstack/server/authenticateRequest.js +0 -154
  156. package/dist/tanstack/server/index.d.ts +0 -4
  157. package/dist/tanstack/server/index.d.ts.map +0 -1
  158. package/dist/tanstack/server/index.js +0 -2
  159. package/dist/tanstack/server/types.d.ts +0 -5
  160. package/dist/tanstack/server/types.d.ts.map +0 -1
  161. package/dist/tanstack/server/types.js +0 -1
  162. package/dist/tanstack/useEveryAppRouter.d.ts +0 -7
  163. package/dist/tanstack/useEveryAppRouter.d.ts.map +0 -1
  164. package/dist/tanstack/useEveryAppRouter.js +0 -66
  165. package/dist/tanstack/useSessionTokenClientMiddleware.d.ts +0 -2
  166. package/dist/tanstack/useSessionTokenClientMiddleware.d.ts.map +0 -1
  167. package/dist/tanstack/useSessionTokenClientMiddleware.js +0 -29
@@ -0,0 +1,185 @@
1
+ /**
2
+ * `everyApp()` — the app-side identity boundary.
3
+ *
4
+ * export default everyApp(handler, { tools });
5
+ *
6
+ * The wrapper verifies the gateway-injected identity before app code runs,
7
+ * stores the result on the original Request, and then delegates to the
8
+ * worker-style handler. The expected audience is the Worker's own name in
9
+ * `env.EVERYAPP_AUDIENCE`, which `everyAppWorker()` sets at deploy (the
10
+ * gateway stamps every token it mints for the app with it); only in
11
+ * development, where `everyapp dev` mints for the app id, does the app id in
12
+ * `env.EVERYAPP_APP_ID` stand in. The Worker never imports
13
+ * `everyapp.config.ts` (the Cloudflare Vite plugin hides every file
14
+ * `cloudflare.config.ts` imports from the Worker in dev).
15
+ * It also answers the gateway's internal tools contract
16
+ * (`/__everyapp/tools/*`) for the app's `defineTools()` catalog.
17
+ */
18
+ import { APP_ID_ENV, AUDIENCE_ENV, ConfigurationError, DEV_ENV, IdentityError, ISSUER_ENV, PUBLIC_KEYS_ENV, getIdentityFromRequest, } from "../internal/index.js";
19
+ import { handleToolsRequest } from "./toolsEndpoint.js";
20
+ export { ConfigurationError, IdentityError };
21
+ const requestIdentities = new WeakMap();
22
+ function envValue(env, key) {
23
+ if (!env || typeof env !== "object")
24
+ return undefined;
25
+ const value = env[key];
26
+ return typeof value === "string" && value.length > 0 ? value : undefined;
27
+ }
28
+ function configFrom(manifest, options = {}) {
29
+ return {
30
+ manifestAppId: manifest?.id,
31
+ issuer: options.issuer,
32
+ keysEnvVar: options.keysEnvVar ?? PUBLIC_KEYS_ENV,
33
+ publicKeys: options.publicKeys,
34
+ allowDevIdentities: options.allowDevIdentities,
35
+ now: options.now,
36
+ };
37
+ }
38
+ /**
39
+ * The app id: EVERYAPP_APP_ID, or a manifest passed to everyApp() for
40
+ * Workers without it; the two must agree when both are present.
41
+ */
42
+ function appIdFor(env, config) {
43
+ const fromEnv = envValue(env, APP_ID_ENV);
44
+ if (fromEnv && config.manifestAppId && fromEnv !== config.manifestAppId) {
45
+ throw new ConfigurationError(`${APP_ID_ENV} ("${fromEnv}") does not match the manifest id ("${config.manifestAppId}").`);
46
+ }
47
+ return fromEnv ?? config.manifestAppId;
48
+ }
49
+ function devIdentitiesAllowed(env, config) {
50
+ const devEnv = envValue(env, DEV_ENV);
51
+ return (config.allowDevIdentities ??
52
+ (devEnv !== undefined &&
53
+ (devEnv === "1" || devEnv.toLowerCase() === "true")));
54
+ }
55
+ /**
56
+ * The audience identity tokens must carry: this Worker's name, from
57
+ * EVERYAPP_AUDIENCE. The gateway mints for the Worker, not the app id, so a
58
+ * token for one organization's copy of an app never opens another's. Only
59
+ * under the dev opt-in, where `everyapp dev` mints for the app id, does the
60
+ * app id stand in when EVERYAPP_AUDIENCE is unset.
61
+ */
62
+ function audienceFor(env, config) {
63
+ const appId = appIdFor(env, config);
64
+ const audience = envValue(env, AUDIENCE_ENV);
65
+ if (audience)
66
+ return audience;
67
+ if (appId && devIdentitiesAllowed(env, config))
68
+ return appId;
69
+ throw new ConfigurationError(`${AUDIENCE_ENV} is not set — the app's cloudflare.config.ts must declare it (everyAppWorker() does at deploy).`);
70
+ }
71
+ function unauthorized(message) {
72
+ return Response.json({ error: "unauthenticated", message }, { status: 401 });
73
+ }
74
+ function misconfigured(message) {
75
+ return Response.json({ error: "misconfigured", message }, { status: 500 });
76
+ }
77
+ function identityOptions(env, config, audience) {
78
+ return {
79
+ audience,
80
+ issuer: config.issuer ?? envValue(env, ISSUER_ENV),
81
+ publicKeys: config.publicKeys,
82
+ env: env,
83
+ keysEnvVar: config.keysEnvVar,
84
+ allowDevIdentities: devIdentitiesAllowed(env, config),
85
+ now: config.now,
86
+ };
87
+ }
88
+ async function resolveIdentity(request, env, config) {
89
+ return getIdentityFromRequest(request, identityOptions(env, config, audienceFor(env, config)));
90
+ }
91
+ function rememberIdentity(request, identity) {
92
+ requestIdentities.set(request, identity);
93
+ }
94
+ /**
95
+ * Return the verified Every App user for this request, or null for a declared
96
+ * public request. Uses the request cache first, then verifies the identity
97
+ * headers from the app id and public keys configured in env.
98
+ */
99
+ export async function getEveryAppUser(request, env) {
100
+ const cached = requestIdentities.get(request);
101
+ if (cached)
102
+ return cached.user;
103
+ const identity = await resolveIdentity(request, env, {
104
+ keysEnvVar: PUBLIC_KEYS_ENV,
105
+ });
106
+ rememberIdentity(request, identity);
107
+ return identity.user;
108
+ }
109
+ /**
110
+ * Return the verified user, or throw the same 401 JSON Response shape as
111
+ * everyApp() when the request is public or unauthenticated.
112
+ */
113
+ export async function requireEveryAppUser(request, env) {
114
+ try {
115
+ const user = await getEveryAppUser(request, env);
116
+ if (!user) {
117
+ throw new IdentityError("this request does not have an authenticated user");
118
+ }
119
+ return user;
120
+ }
121
+ catch (error) {
122
+ if (error instanceof IdentityError) {
123
+ throw unauthorized(error.message);
124
+ }
125
+ throw error;
126
+ }
127
+ }
128
+ export function hasScope(user, scope) {
129
+ return user.scopes.includes("*") || user.scopes.includes(scope);
130
+ }
131
+ function isManifest(value) {
132
+ return (typeof value === "object" &&
133
+ value !== null &&
134
+ typeof value.id === "string");
135
+ }
136
+ export function everyApp(handler, manifestOrOptions, legacyOptions = {}) {
137
+ const manifest = isManifest(manifestOrOptions)
138
+ ? manifestOrOptions
139
+ : undefined;
140
+ const options = manifest || manifestOrOptions === undefined
141
+ ? legacyOptions
142
+ : manifestOrOptions;
143
+ const config = configFrom(manifest, options);
144
+ return {
145
+ async fetch(request, env, ctx) {
146
+ let audience;
147
+ let appId;
148
+ try {
149
+ audience = audienceFor(env, config);
150
+ appId = appIdFor(env, config) ?? audience;
151
+ }
152
+ catch (err) {
153
+ if (err instanceof ConfigurationError) {
154
+ console.error(err);
155
+ return misconfigured(err.message);
156
+ }
157
+ throw err;
158
+ }
159
+ // The reserved tools contract carries its own gateway-minted tokens and
160
+ // never reaches the app's handler.
161
+ const toolsResponse = await handleToolsRequest(request, env, ctx, {
162
+ toolSet: options.tools,
163
+ appId,
164
+ identity: identityOptions(env, config, audience),
165
+ });
166
+ if (toolsResponse)
167
+ return toolsResponse;
168
+ let identity;
169
+ try {
170
+ identity = await getIdentityFromRequest(request, identityOptions(env, config, audience));
171
+ rememberIdentity(request, identity);
172
+ }
173
+ catch (err) {
174
+ if (err instanceof ConfigurationError) {
175
+ console.error(err);
176
+ return misconfigured(err.message);
177
+ }
178
+ if (err instanceof IdentityError)
179
+ return unauthorized(err.message);
180
+ throw err;
181
+ }
182
+ return handler(request, env, ctx, identity.user);
183
+ },
184
+ };
185
+ }
@@ -0,0 +1,37 @@
1
+ import { type GatewayCallFor } from "./attribution.js";
2
+ export declare const BINDING_ORIGIN = "http://every-app-gateway.internal";
3
+ export interface GatewayServiceBinding {
4
+ fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
5
+ }
6
+ export interface GatewayFetchEnv {
7
+ EVERY_APP_GATEWAY?: GatewayServiceBinding;
8
+ EVERYAPP_DEV?: string | boolean;
9
+ /** `1` on a shared app's Workers (`everyAppWorker()` sets it). */
10
+ EVERYAPP_SHARED?: string;
11
+ OPENAI_API_KEY?: string;
12
+ OPENROUTER_API_KEY?: string;
13
+ /** Workers AI: an API token (Workers AI Read and Edit) and the account it bills. */
14
+ WORKERS_AI_API_TOKEN?: string;
15
+ CLOUDFLARE_ACCOUNT_ID?: string;
16
+ }
17
+ export interface CreateGatewayFetchOptions {
18
+ env: GatewayFetchEnv;
19
+ /**
20
+ * Whom the call is for: the inbound request (its user), or
21
+ * `{ background: true, organizationId }` for work no person started
22
+ * (crons, Workflows, queues). An organization's own app may omit it for
23
+ * background work, which is then the app's; a shared app's Worker must
24
+ * pass one or the other ({@link AttributionError}).
25
+ */
26
+ for?: GatewayCallFor;
27
+ }
28
+ /**
29
+ * Create a fetch for the gateway's AI providers (`/api/ai/<provider>/…`),
30
+ * backed by the private gateway service binding. In local dev only, the
31
+ * developer's own provider key from `.dev.vars` is a direct-provider
32
+ * fallback when no binding exists.
33
+ */
34
+ export declare function createGatewayFetch({ env, for: target, }: CreateGatewayFetchOptions): typeof fetch;
35
+ /** A copy of `source` aimed at `url`, streaming its body rather than buffering it. */
36
+ export declare function streamingRequest(url: string, source: Request, headers: Headers): Request;
37
+ //# sourceMappingURL=gatewayFetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gatewayFetch.d.ts","sourceRoot":"","sources":["../../src/server/gatewayFetch.ts"],"names":[],"mappings":"AASA,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,CA8D1C;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,OAAO,GACf,OAAO,CAUT"}
@@ -0,0 +1,115 @@
1
+ import { aiProviderSettings, authorizationOf, ConfigurationError, DEV_AI_PROVIDERS, devAiProvider, joinProviderUrl, } from "../internal/index.js";
2
+ import { applyAttribution, checkAttribution, } from "./attribution.js";
3
+ export const BINDING_ORIGIN = "http://every-app-gateway.internal";
4
+ const AI_PROXY_PREFIX = "/api/ai/";
5
+ /**
6
+ * Create a fetch for the gateway's AI providers (`/api/ai/<provider>/…`),
7
+ * backed by the private gateway service binding. In local dev only, the
8
+ * developer's own provider key from `.dev.vars` is a direct-provider
9
+ * fallback when no binding exists.
10
+ */
11
+ export function createGatewayFetch({ env, for: target, }) {
12
+ checkAttribution(env, target, "createGatewayFetch");
13
+ const binding = env.EVERY_APP_GATEWAY;
14
+ const devProviders = env.EVERYAPP_DEV ? localProviders(env) : {};
15
+ if (binding && typeof binding.fetch !== "function") {
16
+ throw new ConfigurationError("EVERY_APP_GATEWAY is configured but is not a valid service binding.");
17
+ }
18
+ if (!binding && Object.keys(devProviders).length === 0) {
19
+ throw new ConfigurationError(`AI gateway unavailable: deploy with the EVERY_APP_GATEWAY binding, or set the provider's key (${listOf(Object.values(DEV_AI_PROVIDERS).map((spec) => settingsNames(spec, "with")), "or")}) in .dev.vars for direct local development.`);
20
+ }
21
+ return async (input, init) => {
22
+ const outbound = new Request(input, init);
23
+ const headers = new Headers(outbound.headers);
24
+ headers.delete("authorization");
25
+ if (binding) {
26
+ applyAttribution(headers, target);
27
+ const url = new URL(outbound.url);
28
+ const bindingRequest = streamingRequest(`${BINDING_ORIGIN}${url.pathname}${url.search}`, outbound, headers);
29
+ return binding.fetch(bindingRequest);
30
+ }
31
+ const { provider, spec, path, search } = directProviderPath(outbound.url);
32
+ const dev = devProviders[provider];
33
+ if (!dev) {
34
+ throw new ConfigurationError(`Set ${settingsNames(spec)} in .dev.vars to call ${provider} in local development.`);
35
+ }
36
+ const url = joinProviderUrl(`${spec.origin}${dev.basePath}`, path, search);
37
+ if (!url)
38
+ throw new ConfigurationError("Invalid provider proxy path.");
39
+ applyAttribution(headers, undefined);
40
+ // The developer's key, put where the provider's entry says (a bearer
41
+ // token for the three today), as the gateway would put its own.
42
+ const auth = authorizationOf(spec.auth, { [spec.keyEnv]: dev.key });
43
+ for (const [name, value] of Object.entries(auth?.headers ?? {})) {
44
+ headers.set(name, value);
45
+ }
46
+ for (const [name, value] of Object.entries(auth?.query ?? {})) {
47
+ url.searchParams.set(name, value);
48
+ }
49
+ const response = await fetch(streamingRequest(url.toString(), outbound, headers));
50
+ // What the gateway does to the provider's answer, so dev behaves alike.
51
+ return spec.normalizeResponse?.(path, response) ?? response;
52
+ };
53
+ }
54
+ /** A copy of `source` aimed at `url`, streaming its body rather than buffering it. */
55
+ export function streamingRequest(url, source, headers) {
56
+ const body = canIncludeBody(source.method) ? source.body : undefined;
57
+ const init = {
58
+ method: source.method,
59
+ headers,
60
+ body,
61
+ signal: source.signal,
62
+ ...(body ? { duplex: "half" } : {}),
63
+ };
64
+ return new Request(url, init);
65
+ }
66
+ /** The providers `.dev.vars` sets every setting of, with their key and base path. */
67
+ function localProviders(env) {
68
+ const providers = {};
69
+ for (const [provider, spec] of Object.entries(DEV_AI_PROVIDERS)) {
70
+ const settings = {};
71
+ for (const name of aiProviderSettings(spec)) {
72
+ const value = env[name];
73
+ if (typeof value === "string" && value.trim()) {
74
+ settings[name] = value.trim();
75
+ }
76
+ }
77
+ const key = settings[spec.keyEnv];
78
+ // A provider is reachable only with every setting it needs.
79
+ if (!key || Object.keys(settings).length < aiProviderSettings(spec).length)
80
+ continue;
81
+ providers[provider] = { key, basePath: spec.basePath?.(settings) ?? "" };
82
+ }
83
+ return providers;
84
+ }
85
+ function directProviderPath(input) {
86
+ const incoming = new URL(input);
87
+ const match = incoming.pathname.match(/^\/api\/ai\/([a-z][a-z0-9-]*)(\/.*)?$/);
88
+ const provider = match?.[1];
89
+ const spec = provider ? devAiProvider(provider) : undefined;
90
+ 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.`);
92
+ }
93
+ const path = match?.[2] || "/";
94
+ if (path.startsWith("//") || path.includes("\\")) {
95
+ throw new ConfigurationError("Invalid provider proxy path.");
96
+ }
97
+ return { provider, spec, path, search: incoming.search };
98
+ }
99
+ /** A provider's settings as a person reads them: `KEY`, or `KEY and SETTING`. */
100
+ function settingsNames(spec, conjunction = "and") {
101
+ const [key, ...others] = aiProviderSettings(spec);
102
+ return others.length
103
+ ? `${key} ${conjunction} ${listOf(others, "and")}`
104
+ : key;
105
+ }
106
+ /** `a`, `a and b`, `a, b and c`. */
107
+ function listOf(items, conjunction) {
108
+ return items.length < 2
109
+ ? (items[0] ?? "")
110
+ : `${items.slice(0, -1).join(", ")} ${conjunction} ${items.at(-1)}`;
111
+ }
112
+ function canIncludeBody(method) {
113
+ const normalized = method.toUpperCase();
114
+ return normalized !== "GET" && normalized !== "HEAD";
115
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @every-app/sdk/server — the server-side surface.
3
+ *
4
+ * There is intentionally no client-side export.
5
+ */
6
+ export { ConfigurationError, IdentityError, everyApp, getEveryAppUser, hasScope, requireEveryAppUser, type EveryAppOptions, type EveryAppManifestLike, type EveryAppHandler, type EveryAppUser, type IdentityResult, } from "./everyApp.js";
7
+ export { AttributionError, type GatewayCallFor } from "./attribution.js";
8
+ export { authorizeUrl, type AuthorizeUrlOptions } from "./authorizeUrl.js";
9
+ export { createGatewayFetch, type CreateGatewayFetchOptions, type GatewayFetchEnv, } from "./gatewayFetch.js";
10
+ export { GatewayRefusalError, gatewayRefusal, integrationFetch, integrationStatus, type EmailIntegrationStatus, type GatewayRefusal, type IntegrationFetchOptions, type IntegrationStatus, type IntegrationStatusOf, type OAuthClientIntegrationStatus, } from "./integrationFetch.js";
11
+ export { nodeServerHandler, type NodeServer, type NodeServerHandlerOptions, } from "./nodeServer.js";
12
+ export { sendEmail, type SendEmailOptions } from "./sendEmail.js";
13
+ export { listMembers, type ListMembersOptions } from "./listMembers.js";
14
+ 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";
16
+ export { ToolError, defineTools, toolResult, type DefineToolsOptions, type PlainToolSchema, type StandardSchemaWithJSON, type ToolContext, type ToolDefinition, type ToolResult, type ToolSchema, type ToolSet, } from "./tools.js";
17
+ export type { ToolRisk } from "../internal/index.js";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @every-app/sdk/server — the server-side surface.
3
+ *
4
+ * There is intentionally no client-side export.
5
+ */
6
+ export { ConfigurationError, IdentityError, everyApp, getEveryAppUser, hasScope, requireEveryAppUser, } from "./everyApp.js";
7
+ export { AttributionError } from "./attribution.js";
8
+ export { authorizeUrl } from "./authorizeUrl.js";
9
+ export { createGatewayFetch, } from "./gatewayFetch.js";
10
+ export { GatewayRefusalError, gatewayRefusal, integrationFetch, integrationStatus, } from "./integrationFetch.js";
11
+ export { nodeServerHandler, } from "./nodeServer.js";
12
+ export { sendEmail } from "./sendEmail.js";
13
+ export { listMembers } from "./listMembers.js";
14
+ export { emit } from "./emit.js";
15
+ export { ToolError, defineTools, toolResult, } from "./tools.js";
@@ -0,0 +1,131 @@
1
+ import { type ApiKeyCapabilityId, type CapabilityId, type EmailCapabilityStatus, type OAuthClientCapabilityId } from "../internal/index.js";
2
+ import { type GatewayCallFor } from "./attribution.js";
3
+ export interface IntegrationFetchOptions {
4
+ /**
5
+ * The Worker env: the EVERY_APP_GATEWAY binding when deployed, or in local
6
+ * dev EVERYAPP_DEV and the provider's key (e.g. DATAFORSEO_API_KEY in
7
+ * `.dev.vars`).
8
+ */
9
+ env: object;
10
+ /**
11
+ * A provider the app lists in its manifest's `capabilities`: one whose
12
+ * key the gateway holds, or one whose OAuth client it holds (its token
13
+ * endpoints only). The built-in catalog's ids complete; a provider
14
+ * registered on the gateway (`everyapp provider add`) is any other id,
15
+ * reached through the binding, which checks it. The `email` capability
16
+ * is sent with `sendEmail()` instead.
17
+ */
18
+ provider: ApiKeyCapabilityId | OAuthClientCapabilityId | (string & {});
19
+ /**
20
+ * Whom the call is for: the inbound request (its user), or
21
+ * `{ background: true, organizationId }` for work no person started
22
+ * (crons, Workflows, queues). An organization's own app may omit it for
23
+ * background work, which is then the app's; a shared app's Worker must
24
+ * pass one or the other ({@link AttributionError}).
25
+ */
26
+ for?: GatewayCallFor;
27
+ }
28
+ /**
29
+ * A `fetch` for one of the gateway's capabilities. Call the provider's real
30
+ * URLs (`https://api.dataforseo.com/v3/…`); this sends them over the
31
+ * AppGateway binding, which checks the app's manifest lists the capability,
32
+ * injects the key the gateway holds and forwards the call. The app never
33
+ * sees the key. A refusal the gateway makes itself comes back as a response
34
+ * {@link gatewayRefusal} recognizes; anything else is the provider's answer.
35
+ *
36
+ * For an OAuth client (`linkedin`, `mastodon`, ...) it reaches the
37
+ * provider's token endpoints only, and the gateway puts its client on the
38
+ * request: send the code (or refresh token) without `client_id` or
39
+ * `client_secret`. Build the authorize URL with {@link authorizeUrl} from
40
+ * {@link integrationStatus}, and call the provider's API with the user's
41
+ * token directly.
42
+ *
43
+ * In local dev only, with no binding, the developer's own key or client
44
+ * from `.dev.vars` reaches the provider directly, under the gateway's names:
45
+ * a catalog provider's from the catalog, a provider registered on the
46
+ * gateway from its spec in `.everyapp/providers/<id>.json` (`everyapp
47
+ * provider show <id> --save` writes it), put on the call as the gateway's
48
+ * spec says.
49
+ */
50
+ export declare function integrationFetch({ env, provider, for: target, }: IntegrationFetchOptions): typeof fetch;
51
+ export interface IntegrationStatus {
52
+ /** The app's manifest lists the capability. */
53
+ requested: boolean;
54
+ /** The gateway holds a key for it (in local dev: `.dev.vars` sets one). */
55
+ configured: boolean;
56
+ /** Calls would go through. */
57
+ ready: boolean;
58
+ }
59
+ /**
60
+ * The email capability's status: as {@link IntegrationStatus}, plus the
61
+ * From a message without `from` gets, the `from` patterns the gateway
62
+ * accepts from this app (its installation's senders, `everyapp email set
63
+ * --sender`) and the provider mail goes out with (`cloudflare` or `resend`).
64
+ */
65
+ export type EmailIntegrationStatus = IntegrationStatus & Pick<EmailCapabilityStatus, "sender" | "senders" | "provider">;
66
+ /**
67
+ * An OAuth client's status: as {@link IntegrationStatus}, plus what the app
68
+ * needs to send people to the provider's authorize page, present only when
69
+ * the app lists the capability and the gateway holds the client.
70
+ */
71
+ export interface OAuthClientIntegrationStatus extends IntegrationStatus {
72
+ /** The client's public id, for the authorize URL (and Twitch's `Client-Id`). */
73
+ clientId?: string;
74
+ /**
75
+ * The provider's origin when the operator chose it (Mastodon's instance,
76
+ * `MASTODON_URL`): the authorize page, token endpoint and API are on it.
77
+ */
78
+ origin?: string;
79
+ /**
80
+ * For a client with scope sets (`google-workspace`, `microsoft-365`): the
81
+ * set names the app's manifest entry declares, `[]` when the entry voids
82
+ * its grant (no `scopes`, or a set this gateway doesn't offer), in which
83
+ * case `ready` is false and no token call can complete.
84
+ */
85
+ scopeSets?: readonly string[];
86
+ /**
87
+ * The provider's scope strings those sets ask for, in the provider's
88
+ * spelling and the registry's order, for the authorize URL
89
+ * ({@link authorizeUrl} puts them on). The gateway refuses a token that
90
+ * carries more.
91
+ */
92
+ scopes?: readonly string[];
93
+ /** Slack's `user_scope` strings, when the sets name any. */
94
+ userScopes?: readonly string[];
95
+ }
96
+ /** The status of a capability: email's carries its senders, an OAuth client's its id. */
97
+ export type IntegrationStatusOf<P extends string> = P extends "email" ? EmailIntegrationStatus : P extends OAuthClientCapabilityId ? OAuthClientIntegrationStatus : IntegrationStatus;
98
+ /**
99
+ * Whether the app can use an integration right now, without calling the
100
+ * provider: show "an admin needs to set up DataForSEO" (or "sending isn't
101
+ * set up") up front instead of failing mid-task. An OAuth client's status
102
+ * carries its public `clientId` for the authorize URL.
103
+ */
104
+ export declare function integrationStatus<P extends CapabilityId | (string & {})>({ env, provider, }: {
105
+ env: object;
106
+ provider: P;
107
+ }): Promise<IntegrationStatusOf<P>>;
108
+ /** A refusal the AppGateway binding made itself, not the provider. */
109
+ export interface GatewayRefusal {
110
+ status: number;
111
+ /** e.g. `capability_not_requested`, `integration_not_configured`. */
112
+ code: string;
113
+ message: string;
114
+ }
115
+ /**
116
+ * A refusal the AppGateway binding made, thrown: what `sendEmail()` throws
117
+ * when the gateway won't send (`email_sender_not_allowed`,
118
+ * `email_budget_exhausted`, ...). The thrown twin of {@link gatewayRefusal}.
119
+ */
120
+ export declare class GatewayRefusalError extends Error implements GatewayRefusal {
121
+ readonly status: number;
122
+ readonly code: string;
123
+ constructor({ status, code, message }: GatewayRefusal);
124
+ }
125
+ /**
126
+ * The gateway's own refusal in `response`, or null when the response is the
127
+ * provider's answer (which may be an error of its own). Reads the body only
128
+ * for a refusal, so call it before reading the body yourself.
129
+ */
130
+ export declare function gatewayRefusal(response: Response): Promise<GatewayRefusal | null>;
131
+ //# sourceMappingURL=integrationFetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrationFetch.d.ts","sourceRoot":"","sources":["../../src/server/integrationFetch.ts"],"names":[],"mappings":"AAAA,OAAO,EA2BL,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAE1B,KAAK,uBAAuB,EAO7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAO1B,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;OAOG;IACH,QAAQ,EAAE,kBAAkB,GAAG,uBAAuB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACvE;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,QAAQ,EACR,GAAG,EAAE,MAAM,GACZ,EAAE,uBAAuB,GAAG,OAAO,KAAK,CAkGxC;AA+XD,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,UAAU,EAAE,OAAO,CAAC;IACpB,8BAA8B;IAC9B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,iBAAiB,GACpD,IAAI,CAAC,qBAAqB,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC,CAAC;AAEjE;;;;GAIG;AACH,MAAM,WAAW,4BAA6B,SAAQ,iBAAiB;IACrE,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,4DAA4D;IAC5D,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,yFAAyF;AACzF,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,OAAO,GACjE,sBAAsB,GACtB,CAAC,SAAS,uBAAuB,GAC/B,4BAA4B,GAC5B,iBAAiB,CAAC;AAExB;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,CAAC,SAAS,YAAY,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,EACtC,EACA,GAAG,EACH,QAAQ,GACT,EAAE;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,CAAC,CAAC;CACb,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAoElC;AA2FD,sEAAsE;AACtE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,KAAM,YAAW,cAAc;IACtE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,cAAc;CAMtD;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAWhC"}