@aotter/mantle-cloudflare 0.0.11-alpha.11
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 +202 -0
- package/README.md +10 -0
- package/dist/assets/aotterFavicon.d.ts +2 -0
- package/dist/assets/aotterFavicon.d.ts.map +1 -0
- package/dist/assets/aotterFavicon.js +5 -0
- package/dist/assets/aotterFavicon.js.map +1 -0
- package/dist/auth/ConsoleEmailSender.d.ts +15 -0
- package/dist/auth/ConsoleEmailSender.d.ts.map +1 -0
- package/dist/auth/ConsoleEmailSender.js +19 -0
- package/dist/auth/ConsoleEmailSender.js.map +1 -0
- package/dist/auth/appleClientSecret.d.ts +70 -0
- package/dist/auth/appleClientSecret.d.ts.map +1 -0
- package/dist/auth/appleClientSecret.js +111 -0
- package/dist/auth/appleClientSecret.js.map +1 -0
- package/dist/auth/createAuth.d.ts +176 -0
- package/dist/auth/createAuth.d.ts.map +1 -0
- package/dist/auth/createAuth.js +360 -0
- package/dist/auth/createAuth.js.map +1 -0
- package/dist/bindings/AssetsAssetServer.d.ts +14 -0
- package/dist/bindings/AssetsAssetServer.d.ts.map +1 -0
- package/dist/bindings/AssetsAssetServer.js +20 -0
- package/dist/bindings/AssetsAssetServer.js.map +1 -0
- package/dist/bindings/D1DatabaseDriver.d.ts +21 -0
- package/dist/bindings/D1DatabaseDriver.d.ts.map +1 -0
- package/dist/bindings/D1DatabaseDriver.js +126 -0
- package/dist/bindings/D1DatabaseDriver.js.map +1 -0
- package/dist/bindings/KvCacheBinding.d.ts +14 -0
- package/dist/bindings/KvCacheBinding.d.ts.map +1 -0
- package/dist/bindings/KvCacheBinding.js +27 -0
- package/dist/bindings/KvCacheBinding.js.map +1 -0
- package/dist/bindings/R2MediaStorage.d.ts +80 -0
- package/dist/bindings/R2MediaStorage.d.ts.map +1 -0
- package/dist/bindings/R2MediaStorage.js +189 -0
- package/dist/bindings/R2MediaStorage.js.map +1 -0
- package/dist/bindings/WorkersQueueHookDispatcher.d.ts +38 -0
- package/dist/bindings/WorkersQueueHookDispatcher.d.ts.map +1 -0
- package/dist/bindings/WorkersQueueHookDispatcher.js +68 -0
- package/dist/bindings/WorkersQueueHookDispatcher.js.map +1 -0
- package/dist/bindings/index.d.ts +6 -0
- package/dist/bindings/index.d.ts.map +1 -0
- package/dist/bindings/index.js +6 -0
- package/dist/bindings/index.js.map +1 -0
- package/dist/handlers/index.d.ts +2 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +2 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/turnstile.d.ts +43 -0
- package/dist/handlers/turnstile.d.ts.map +1 -0
- package/dist/handlers/turnstile.js +71 -0
- package/dist/handlers/turnstile.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/mount/bootRuntimeOnce.d.ts +17 -0
- package/dist/mount/bootRuntimeOnce.d.ts.map +1 -0
- package/dist/mount/bootRuntimeOnce.js +35 -0
- package/dist/mount/bootRuntimeOnce.js.map +1 -0
- package/dist/mount/cmsConfig.d.ts +33 -0
- package/dist/mount/cmsConfig.d.ts.map +1 -0
- package/dist/mount/cmsConfig.js +2 -0
- package/dist/mount/cmsConfig.js.map +1 -0
- package/dist/mount/index.d.ts +6 -0
- package/dist/mount/index.d.ts.map +1 -0
- package/dist/mount/index.js +5 -0
- package/dist/mount/index.js.map +1 -0
- package/dist/mount/mountMcp.d.ts +32 -0
- package/dist/mount/mountMcp.d.ts.map +1 -0
- package/dist/mount/mountMcp.js +107 -0
- package/dist/mount/mountMcp.js.map +1 -0
- package/dist/mount/mountPublicRoutes.d.ts +82 -0
- package/dist/mount/mountPublicRoutes.d.ts.map +1 -0
- package/dist/mount/mountPublicRoutes.js +243 -0
- package/dist/mount/mountPublicRoutes.js.map +1 -0
- package/dist/mount/mountServerEndpoints.d.ts +10 -0
- package/dist/mount/mountServerEndpoints.d.ts.map +1 -0
- package/dist/mount/mountServerEndpoints.js +503 -0
- package/dist/mount/mountServerEndpoints.js.map +1 -0
- package/dist/oauth/consentHtml.d.ts +15 -0
- package/dist/oauth/consentHtml.d.ts.map +1 -0
- package/dist/oauth/consentHtml.js +89 -0
- package/dist/oauth/consentHtml.js.map +1 -0
- package/dist/oauth/index.d.ts +4 -0
- package/dist/oauth/index.d.ts.map +1 -0
- package/dist/oauth/index.js +4 -0
- package/dist/oauth/index.js.map +1 -0
- package/dist/oauth/mountOAuth.d.ts +29 -0
- package/dist/oauth/mountOAuth.d.ts.map +1 -0
- package/dist/oauth/mountOAuth.js +105 -0
- package/dist/oauth/mountOAuth.js.map +1 -0
- package/dist/oauth/oauthConstants.d.ts +15 -0
- package/dist/oauth/oauthConstants.d.ts.map +1 -0
- package/dist/oauth/oauthConstants.js +15 -0
- package/dist/oauth/oauthConstants.js.map +1 -0
- package/dist/oauth/oauthSingleton.d.ts +34 -0
- package/dist/oauth/oauthSingleton.d.ts.map +1 -0
- package/dist/oauth/oauthSingleton.js +22 -0
- package/dist/oauth/oauthSingleton.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,GAEpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,cAAc,GAGf,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Hono } from "hono";
|
|
2
|
+
import type { Auth } from "../auth/createAuth.js";
|
|
3
|
+
export interface MountAuthorizeOptions {
|
|
4
|
+
/** Better Auth-backed identity used to gate the consent UI. */
|
|
5
|
+
readonly auth: Auth;
|
|
6
|
+
/** Path that anonymous /authorize visitors get redirected to.
|
|
7
|
+
* Defaults to `/admin/sign-in`. The original `/authorize?...` URL
|
|
8
|
+
* is appended as `?return_to=...` so the sign-in page can bounce
|
|
9
|
+
* back after Better Auth completes. */
|
|
10
|
+
readonly loginPath?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Mount the `/authorize` consent UI on the consumer's Hono app. The
|
|
14
|
+
* Hono app must be passed to `createOAuthProvider({ defaultHandler })`;
|
|
15
|
+
* the lib injects `OAUTH_PROVIDER` helpers onto env BEFORE forwarding
|
|
16
|
+
* the request here, so we read `c.env.OAUTH_PROVIDER` directly.
|
|
17
|
+
*
|
|
18
|
+
* `/token` + `/register` + `/.well-known/oauth-*` are intercepted by
|
|
19
|
+
* the OAuthProvider itself and never reach defaultHandler — do not
|
|
20
|
+
* mount them here.
|
|
21
|
+
*/
|
|
22
|
+
export declare function mountAuthorize(app: Hono, options: MountAuthorizeOptions): void;
|
|
23
|
+
/** Props that mountAuthorize stashes during completeAuthorization and
|
|
24
|
+
* that `createMcpApiHandler` reads from `ctx.props`. */
|
|
25
|
+
export interface OAuthApiProps {
|
|
26
|
+
readonly userId: string;
|
|
27
|
+
readonly role: string | null;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=mountOAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mountOAuth.d.ts","sourceRoot":"","sources":["../../src/oauth/mountOAuth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAOlD,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB;;;4CAGwC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAsG9E;AA4BD;yDACyD;AACzD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { detectConsentLocale, renderConsentHtml, } from "./consentHtml.js";
|
|
2
|
+
/**
|
|
3
|
+
* Mount the `/authorize` consent UI on the consumer's Hono app. The
|
|
4
|
+
* Hono app must be passed to `createOAuthProvider({ defaultHandler })`;
|
|
5
|
+
* the lib injects `OAUTH_PROVIDER` helpers onto env BEFORE forwarding
|
|
6
|
+
* the request here, so we read `c.env.OAUTH_PROVIDER` directly.
|
|
7
|
+
*
|
|
8
|
+
* `/token` + `/register` + `/.well-known/oauth-*` are intercepted by
|
|
9
|
+
* the OAuthProvider itself and never reach defaultHandler — do not
|
|
10
|
+
* mount them here.
|
|
11
|
+
*/
|
|
12
|
+
export function mountAuthorize(app, options) {
|
|
13
|
+
const { auth, loginPath = "/admin/sign-in" } = options;
|
|
14
|
+
const consentHandler = async (c) => {
|
|
15
|
+
const locale = detectConsentLocale(c.req.header("accept-language") ?? null);
|
|
16
|
+
const helpers = c.env.OAUTH_PROVIDER;
|
|
17
|
+
if (!helpers) {
|
|
18
|
+
return new Response("OAUTH_PROVIDER missing on env — is the worker exported via createOAuthProvider()?", { status: 500 });
|
|
19
|
+
}
|
|
20
|
+
const session = await auth.getSession(c.req.raw);
|
|
21
|
+
if (!session) {
|
|
22
|
+
if (c.req.method !== "GET") {
|
|
23
|
+
return new Response("unauthenticated", { status: 401 });
|
|
24
|
+
}
|
|
25
|
+
const u = new URL(c.req.url);
|
|
26
|
+
const returnTo = encodeURIComponent(u.pathname + u.search);
|
|
27
|
+
return new Response(null, {
|
|
28
|
+
status: 302,
|
|
29
|
+
headers: { location: `${loginPath}?return_to=${returnTo}` },
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (c.req.method === "POST") {
|
|
33
|
+
const form = await c.req.raw.formData();
|
|
34
|
+
const oauthRequestJson = form.get("oauth_request");
|
|
35
|
+
if (typeof oauthRequestJson !== "string") {
|
|
36
|
+
return new Response("missing oauth_request", { status: 400 });
|
|
37
|
+
}
|
|
38
|
+
if (form.get("decision") !== "approve") {
|
|
39
|
+
return new Response("authorization denied", { status: 400 });
|
|
40
|
+
}
|
|
41
|
+
let reqInfo;
|
|
42
|
+
try {
|
|
43
|
+
reqInfo = JSON.parse(oauthRequestJson);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return new Response("invalid oauth_request json", { status: 400 });
|
|
47
|
+
}
|
|
48
|
+
// The form-field oauth_request is caller-editable — a malicious
|
|
49
|
+
// submit could swap redirectUri / scope post-consent. Re-validate
|
|
50
|
+
// clientId + redirectUri against the registered client record;
|
|
51
|
+
// refuse if either drifted. Fail closed when no registered URIs
|
|
52
|
+
// exist — a misconfigured client with no allowlist must not get
|
|
53
|
+
// a free pass.
|
|
54
|
+
const registered = await helpers.lookupClient(reqInfo.clientId);
|
|
55
|
+
if (!registered) {
|
|
56
|
+
return new Response("unknown client", { status: 400 });
|
|
57
|
+
}
|
|
58
|
+
if (!Array.isArray(registered.redirectUris) ||
|
|
59
|
+
registered.redirectUris.length === 0 ||
|
|
60
|
+
!registered.redirectUris.includes(reqInfo.redirectUri)) {
|
|
61
|
+
return new Response("redirect_uri mismatch", { status: 400 });
|
|
62
|
+
}
|
|
63
|
+
const role = await auth.getUserRole(session.user.id);
|
|
64
|
+
// If claude.ai forgets to request a scope, default to ["mcp"]
|
|
65
|
+
// so the token grant is non-empty (claude.ai post-token
|
|
66
|
+
// verification rejects empty-scope tokens in some flows).
|
|
67
|
+
const grantedScope = reqInfo.scope && reqInfo.scope.length > 0 ? reqInfo.scope : ["mcp"];
|
|
68
|
+
const { redirectTo } = await helpers.completeAuthorization({
|
|
69
|
+
request: reqInfo,
|
|
70
|
+
userId: session.user.id,
|
|
71
|
+
metadata: {},
|
|
72
|
+
scope: grantedScope,
|
|
73
|
+
// Stash role on props so apiHandler can enforce staff gating
|
|
74
|
+
// via D1 lookup. ctx.props is what the lib hands to
|
|
75
|
+
// apiHandler.fetch after token verification.
|
|
76
|
+
props: {
|
|
77
|
+
userId: session.user.id,
|
|
78
|
+
role: role ?? null,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
return new Response(null, { status: 302, headers: { location: redirectTo } });
|
|
82
|
+
}
|
|
83
|
+
let model = null;
|
|
84
|
+
try {
|
|
85
|
+
const reqInfo = await helpers.parseAuthRequest(c.req.raw);
|
|
86
|
+
const clientInfo = await helpers.lookupClient(reqInfo.clientId);
|
|
87
|
+
model = {
|
|
88
|
+
clientName: clientInfo?.clientName ?? "(unknown client)",
|
|
89
|
+
redirectUri: reqInfo.redirectUri,
|
|
90
|
+
scopes: reqInfo.scope ?? [],
|
|
91
|
+
oauthRequestJson: JSON.stringify(reqInfo),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// parseAuthRequest throws on malformed requests; fall through to
|
|
96
|
+
// the "invalid authorization request" branch in renderConsentHtml.
|
|
97
|
+
}
|
|
98
|
+
return new Response(renderConsentHtml(locale, model), {
|
|
99
|
+
headers: { "content-type": "text/html; charset=utf-8" },
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
app.get("/oauth/authorize", consentHandler);
|
|
103
|
+
app.post("/oauth/authorize", consentHandler);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=mountOAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mountOAuth.js","sourceRoot":"","sources":["../../src/oauth/mountOAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path constants shared between `oauthSingleton.ts` (which constructs
|
|
3
|
+
* `OAuthProvider`) and `mountOAuth.ts` (which mounts the `/authorize`
|
|
4
|
+
* consent handler against the consumer's Hono app).
|
|
5
|
+
*
|
|
6
|
+
* Namespaced under `/oauth/*` to avoid squatting on generic root
|
|
7
|
+
* paths (consumers might want `/register`, `/token`, `/authorize` for
|
|
8
|
+
* their own routes). claude.ai's MCP OAuth client reads AS metadata
|
|
9
|
+
* (RFC 8414) and follows whatever endpoints we advertise — verified
|
|
10
|
+
* 2026-05-15 against `cms.aotterclam.ai` with the namespaced paths.
|
|
11
|
+
*/
|
|
12
|
+
export declare const OAUTH_AUTHORIZE_PATH = "/oauth/authorize";
|
|
13
|
+
export declare const OAUTH_TOKEN_PATH = "/oauth/token";
|
|
14
|
+
export declare const OAUTH_REGISTER_PATH = "/oauth/register";
|
|
15
|
+
//# sourceMappingURL=oauthConstants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthConstants.d.ts","sourceRoot":"","sources":["../../src/oauth/oauthConstants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AACvD,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAC/C,eAAO,MAAM,mBAAmB,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path constants shared between `oauthSingleton.ts` (which constructs
|
|
3
|
+
* `OAuthProvider`) and `mountOAuth.ts` (which mounts the `/authorize`
|
|
4
|
+
* consent handler against the consumer's Hono app).
|
|
5
|
+
*
|
|
6
|
+
* Namespaced under `/oauth/*` to avoid squatting on generic root
|
|
7
|
+
* paths (consumers might want `/register`, `/token`, `/authorize` for
|
|
8
|
+
* their own routes). claude.ai's MCP OAuth client reads AS metadata
|
|
9
|
+
* (RFC 8414) and follows whatever endpoints we advertise — verified
|
|
10
|
+
* 2026-05-15 against `cms.aotterclam.ai` with the namespaced paths.
|
|
11
|
+
*/
|
|
12
|
+
export const OAUTH_AUTHORIZE_PATH = "/oauth/authorize";
|
|
13
|
+
export const OAUTH_TOKEN_PATH = "/oauth/token";
|
|
14
|
+
export const OAUTH_REGISTER_PATH = "/oauth/register";
|
|
15
|
+
//# sourceMappingURL=oauthConstants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthConstants.js","sourceRoot":"","sources":["../../src/oauth/oauthConstants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AACvD,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAC/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { OAuthProvider } from "@cloudflare/workers-oauth-provider";
|
|
2
|
+
export interface CreateOAuthProviderArgs {
|
|
3
|
+
/** Worker module shape for non-OAuth requests. Typically the
|
|
4
|
+
* consumer's Hono app: `{ fetch: app.fetch }`. The lib injects
|
|
5
|
+
* `OAUTH_PROVIDER` onto env BEFORE calling this, so the consumer's
|
|
6
|
+
* `/authorize` route can pull helpers via `c.env.OAUTH_PROVIDER`. */
|
|
7
|
+
readonly defaultHandler: ExportedHandler<Record<string, unknown>>;
|
|
8
|
+
/** Map of MCP resource path → worker handler. Lib verifies the
|
|
9
|
+
* bearer token, then dispatches to the matching handler with
|
|
10
|
+
* `ctx.props` set to whatever was passed to
|
|
11
|
+
* `completeAuthorization({ props })`. Use `createMcpApiHandler`
|
|
12
|
+
* to build the handler value for each entry. */
|
|
13
|
+
readonly apiHandlers: Record<string, ExportedHandler<Record<string, unknown>>>;
|
|
14
|
+
/** Scopes advertised in `scopes_supported` for both AS metadata
|
|
15
|
+
* (RFC 8414) and PRM (RFC 9728). Defaults to `["mcp"]` — a single
|
|
16
|
+
* non-colon-namespaced scope, which is what claude.ai's MCP OAuth
|
|
17
|
+
* client actually understands. Verified 2026-05-15: colon-shaped
|
|
18
|
+
* scopes (e.g. `mcp:read`, `mcp:staff`) cause claude.ai to omit
|
|
19
|
+
* `scope=` from /authorize, ending the flow with `ofid_*` post-token.
|
|
20
|
+
* Staff vs public differentiation should be enforced server-side
|
|
21
|
+
* in the apiHandler (D1 role lookup), not through OAuth scope. */
|
|
22
|
+
readonly scopesSupported?: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build the top-level OAuthProvider. **Export the result as the
|
|
26
|
+
* worker's `default`** so the lib gets every request first and can
|
|
27
|
+
* route OAuth endpoints internally, fan MCP requests to apiHandlers,
|
|
28
|
+
* and inject helpers onto env before forwarding to defaultHandler.
|
|
29
|
+
*
|
|
30
|
+
* Endpoint paths default to `/oauth/{authorize,token,register}` —
|
|
31
|
+
* see `oauthConstants.ts`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createOAuthProvider(args: CreateOAuthProviderArgs): OAuthProvider;
|
|
34
|
+
//# sourceMappingURL=oauthSingleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthSingleton.d.ts","sourceRoot":"","sources":["../../src/oauth/oauthSingleton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAOnE,MAAM,WAAW,uBAAuB;IACtC;;;0EAGsE;IACtE,QAAQ,CAAC,cAAc,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClE;;;;qDAIiD;IACjD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC/E;;;;;;;uEAOmE;IACnE,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,uBAAuB,GAAG,aAAa,CAShF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { OAuthProvider } from "@cloudflare/workers-oauth-provider";
|
|
2
|
+
import { OAUTH_AUTHORIZE_PATH, OAUTH_REGISTER_PATH, OAUTH_TOKEN_PATH, } from "./oauthConstants.js";
|
|
3
|
+
/**
|
|
4
|
+
* Build the top-level OAuthProvider. **Export the result as the
|
|
5
|
+
* worker's `default`** so the lib gets every request first and can
|
|
6
|
+
* route OAuth endpoints internally, fan MCP requests to apiHandlers,
|
|
7
|
+
* and inject helpers onto env before forwarding to defaultHandler.
|
|
8
|
+
*
|
|
9
|
+
* Endpoint paths default to `/oauth/{authorize,token,register}` —
|
|
10
|
+
* see `oauthConstants.ts`.
|
|
11
|
+
*/
|
|
12
|
+
export function createOAuthProvider(args) {
|
|
13
|
+
return new OAuthProvider({
|
|
14
|
+
apiHandlers: args.apiHandlers,
|
|
15
|
+
defaultHandler: args.defaultHandler,
|
|
16
|
+
authorizeEndpoint: OAUTH_AUTHORIZE_PATH,
|
|
17
|
+
tokenEndpoint: OAUTH_TOKEN_PATH,
|
|
18
|
+
clientRegistrationEndpoint: OAUTH_REGISTER_PATH,
|
|
19
|
+
scopesSupported: [...(args.scopesSupported ?? ["mcp"])],
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=oauthSingleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthSingleton.js","sourceRoot":"","sources":["../../src/oauth/oauthSingleton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAyB7B;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAA6B;IAC/D,OAAO,IAAI,aAAa,CAAC;QACvB,WAAW,EAAE,IAAI,CAAC,WAAoB;QACtC,cAAc,EAAE,IAAI,CAAC,cAAuB;QAC5C,iBAAiB,EAAE,oBAAoB;QACvC,aAAa,EAAE,gBAAgB;QAC/B,0BAA0B,EAAE,mBAAmB;QAC/C,eAAe,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;KACxD,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aotter/mantle-cloudflare",
|
|
3
|
+
"version": "0.0.11-alpha.11",
|
|
4
|
+
"description": "Cloudflare Workers adapter for mantle. Hono-based mountServerEndpoints / createMcpApiHandler / mountAuthorize / mountPublicRoutes. Better Auth for staff sign-in; @cloudflare/workers-oauth-provider for the MCP OAuth AS surface.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"homepage": "https://github.com/aotter/mantle/tree/develop/packages/adapters/cloudflare",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/aotter/mantle.git",
|
|
10
|
+
"directory": "packages/adapters/cloudflare"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"sideEffects": false,
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public",
|
|
16
|
+
"tag": "alpha",
|
|
17
|
+
"registry": "https://registry.npmjs.org"
|
|
18
|
+
},
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md"
|
|
30
|
+
],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@aotter/mantle-admin-ui": "0.0.11-alpha.11",
|
|
33
|
+
"@aotter/mantle-runtime": "0.0.11-alpha.11",
|
|
34
|
+
"@aotter/mantle-spec": "0.0.11-alpha.11"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"@cloudflare/workers-oauth-provider": "^0.6.0",
|
|
38
|
+
"aws4fetch": "^1.0.20",
|
|
39
|
+
"better-auth": "^1.6.0",
|
|
40
|
+
"hono": "^4.12.0",
|
|
41
|
+
"zod": "^4.0.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@cloudflare/workers-oauth-provider": "^0.6.0",
|
|
45
|
+
"@cloudflare/workers-types": "^4.20260518.1",
|
|
46
|
+
"@types/node": "^25",
|
|
47
|
+
"aws4fetch": "^1.0.20",
|
|
48
|
+
"better-auth": "^1.6.11",
|
|
49
|
+
"hono": "^4.12.19",
|
|
50
|
+
"typescript": "^6.0.3",
|
|
51
|
+
"vitest": "^4.1.6",
|
|
52
|
+
"wrangler": "^4.92.0",
|
|
53
|
+
"zod": "^4.4.2"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"prebuild": "rm -rf dist .tsbuildinfo",
|
|
57
|
+
"build": "tsc -b tsconfig.lib.json",
|
|
58
|
+
"typecheck": "tsc --noEmit -p tsconfig.lib.json",
|
|
59
|
+
"test": "vitest run"
|
|
60
|
+
}
|
|
61
|
+
}
|