@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":"createAuth.d.ts","sourceRoot":"","sources":["../../src/auth/createAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { betterAuth } from "better-auth";
|
|
2
|
+
import { admin, emailOTP, magicLink } from "better-auth/plugins";
|
|
3
|
+
import { createAccessControl } from "better-auth/plugins/access";
|
|
4
|
+
import { defaultStatements } from "better-auth/plugins/admin/access";
|
|
5
|
+
export const ADMIN_ROLES = ["contributor", "editor", "owner"];
|
|
6
|
+
export const ADMIN_ROLE_SET = new Set(ADMIN_ROLES);
|
|
7
|
+
const ac = createAccessControl(defaultStatements);
|
|
8
|
+
const ownerAc = ac.newRole({
|
|
9
|
+
user: defaultStatements.user,
|
|
10
|
+
session: defaultStatements.session,
|
|
11
|
+
});
|
|
12
|
+
const editorAc = ac.newRole({
|
|
13
|
+
user: ["list", "ban", "get", "update"],
|
|
14
|
+
session: ["list", "revoke"],
|
|
15
|
+
});
|
|
16
|
+
const contributorAc = ac.newRole({
|
|
17
|
+
user: ["list", "get"],
|
|
18
|
+
session: [],
|
|
19
|
+
});
|
|
20
|
+
const userAc = ac.newRole({
|
|
21
|
+
user: [],
|
|
22
|
+
session: [],
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Keys that `extras` MUST NOT contain — they have first-class fields
|
|
26
|
+
* on `AuthMethodConfig` and / or are managed by this adapter (the
|
|
27
|
+
* github `mapProfileToUser` shim). Allowing them through would let a
|
|
28
|
+
* stray entry shadow credentials or break bootstrap promotion.
|
|
29
|
+
*/
|
|
30
|
+
const SOCIAL_EXTRAS_RESERVED_KEYS = new Set([
|
|
31
|
+
"clientId",
|
|
32
|
+
"clientSecret",
|
|
33
|
+
"redirectURI",
|
|
34
|
+
"scope",
|
|
35
|
+
"mapProfileToUser",
|
|
36
|
+
]);
|
|
37
|
+
/** @internal exported for unit tests; not part of the public API. */
|
|
38
|
+
export function buildSocialProviders(methods) {
|
|
39
|
+
// Better Auth's typed `socialProviders` shape names every provider
|
|
40
|
+
// key individually; assigning by computed string requires an index
|
|
41
|
+
// signature, so we build through a plain map and cast once at the
|
|
42
|
+
// return. The runtime shape matches Better Auth's expectations.
|
|
43
|
+
const out = {};
|
|
44
|
+
for (const method of methods) {
|
|
45
|
+
if (method.kind !== "social")
|
|
46
|
+
continue;
|
|
47
|
+
if (method.extras) {
|
|
48
|
+
for (const key of Object.keys(method.extras)) {
|
|
49
|
+
if (SOCIAL_EXTRAS_RESERVED_KEYS.has(key)) {
|
|
50
|
+
throw new Error(`createAuth: social method '${method.provider}' has reserved key '${key}' in \`extras\`. ` +
|
|
51
|
+
`Use the first-class field instead — \`extras\` is for provider-specific options only.`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// GitHub-specific: stash the github login on `user.githubLogin`
|
|
56
|
+
// so `bootstrapOwner: { match: "github-login" }` keeps working.
|
|
57
|
+
// Other providers don't need an analogous shim because bootstrap
|
|
58
|
+
// matches on email for them.
|
|
59
|
+
const githubProfileMapper = method.provider === "github"
|
|
60
|
+
? {
|
|
61
|
+
mapProfileToUser: (profile) => ({
|
|
62
|
+
githubLogin: profile.login,
|
|
63
|
+
}),
|
|
64
|
+
}
|
|
65
|
+
: {};
|
|
66
|
+
out[method.provider] = {
|
|
67
|
+
clientId: method.clientId,
|
|
68
|
+
clientSecret: method.clientSecret,
|
|
69
|
+
...(method.redirectURI ? { redirectURI: method.redirectURI } : {}),
|
|
70
|
+
...(method.scope ? { scope: [...method.scope] } : {}),
|
|
71
|
+
...(method.extras ?? {}),
|
|
72
|
+
...githubProfileMapper,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* First tag off `Accept-Language`, quality values ignored. Locale
|
|
79
|
+
* contract lives in `EmailSender.ts`.
|
|
80
|
+
*/
|
|
81
|
+
/** @internal exported for unit tests; not part of the public API. */
|
|
82
|
+
export function pickLocale(req, fallback) {
|
|
83
|
+
const header = req?.headers.get("accept-language");
|
|
84
|
+
if (!header)
|
|
85
|
+
return fallback;
|
|
86
|
+
const first = header.split(",")[0]?.split(";")[0]?.trim();
|
|
87
|
+
return first && first.length > 0 ? first : fallback;
|
|
88
|
+
}
|
|
89
|
+
// Magic-link defaults override Better Auth's tighter built-ins:
|
|
90
|
+
// - 900s (15 min) link TTL — corporate mail (Outlook + Exchange,
|
|
91
|
+
// Mimecast, Proofpoint URL Defense) often has 30-60s delivery
|
|
92
|
+
// lag and users batch-check; 300s shipped too many "expired"
|
|
93
|
+
// receipts. Industry baseline: Slack 60min, Notion / Vercel
|
|
94
|
+
// 24h. We split the difference and let adopters override.
|
|
95
|
+
// - 3 allowed verification attempts — mail prefetchers (Outlook
|
|
96
|
+
// Safe Links, Mimecast URL Protect, Proofpoint URL Defense)
|
|
97
|
+
// routinely consume URLs once before the user opens the email.
|
|
98
|
+
// 1 attempt is genuinely broken on those inboxes.
|
|
99
|
+
const MAGIC_LINK_DEFAULT_EXPIRES_SECONDS = 900;
|
|
100
|
+
const MAGIC_LINK_DEFAULT_ALLOWED_ATTEMPTS = 3;
|
|
101
|
+
function buildMagicLinkPlugin(method) {
|
|
102
|
+
const fallback = method.fallbackLocale ?? "en";
|
|
103
|
+
return magicLink({
|
|
104
|
+
expiresIn: method.expiresInSeconds ?? MAGIC_LINK_DEFAULT_EXPIRES_SECONDS,
|
|
105
|
+
allowedAttempts: method.allowedAttempts ?? MAGIC_LINK_DEFAULT_ALLOWED_ATTEMPTS,
|
|
106
|
+
// Returned synchronously — same fire-and-forget contract as
|
|
107
|
+
// email-otp via `advanced.backgroundTasks.handler`. The body
|
|
108
|
+
// carries the click-URL; SDK doesn't ship a template, the
|
|
109
|
+
// sender can render plain text or richer HTML.
|
|
110
|
+
sendMagicLink: (data, ctx) => {
|
|
111
|
+
const locale = pickLocale(ctx?.request, fallback);
|
|
112
|
+
return method.sender.send({
|
|
113
|
+
to: data.email,
|
|
114
|
+
subject: "Your sign-in link",
|
|
115
|
+
text: `Click to sign in: ${data.url}\nThe link expires shortly. If you didn't request this, ignore this email.`,
|
|
116
|
+
locale,
|
|
117
|
+
category: "auth.magic-link.sign-in",
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function buildEmailOTPPlugin(method) {
|
|
123
|
+
const fallback = method.fallbackLocale ?? "en";
|
|
124
|
+
return emailOTP({
|
|
125
|
+
...(method.otpLength !== undefined ? { otpLength: method.otpLength } : {}),
|
|
126
|
+
...(method.expiresInSeconds !== undefined
|
|
127
|
+
? { expiresIn: method.expiresInSeconds }
|
|
128
|
+
: {}),
|
|
129
|
+
...(method.allowedAttempts !== undefined
|
|
130
|
+
? { allowedAttempts: method.allowedAttempts }
|
|
131
|
+
: {}),
|
|
132
|
+
// Return synchronously — the promise is fire-and-forget via the
|
|
133
|
+
// `advanced.backgroundTasks.handler` we wire in `buildAuth`. For
|
|
134
|
+
// `email-verification` / `forget-password` types Better Auth only
|
|
135
|
+
// calls this when the user exists, so awaiting would leak account
|
|
136
|
+
// existence through response latency. See Better Auth's own
|
|
137
|
+
// sendVerificationOTP docstring + reviewer finding in PR #161.
|
|
138
|
+
sendVerificationOTP: (data, ctx) => {
|
|
139
|
+
const locale = pickLocale(ctx?.request, fallback);
|
|
140
|
+
return method.sender.send({
|
|
141
|
+
to: data.email,
|
|
142
|
+
subject: `Your sign-in code: ${data.otp}`,
|
|
143
|
+
text: `Your one-time code is ${data.otp}. It expires shortly. If you didn't request this, ignore this email.`,
|
|
144
|
+
locale,
|
|
145
|
+
category: `auth.email-otp.${data.type}`,
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Cross-check bootstrap rule against registered methods. Catches the
|
|
152
|
+
* silent-no-op case where the rule's discriminator can never match
|
|
153
|
+
* any signal a registered method actually produces — e.g.
|
|
154
|
+
* `match: "github-login"` with no `github` method registered. Throws
|
|
155
|
+
* at construction so vibe-coders see the mistake before the first
|
|
156
|
+
* sign-in attempt.
|
|
157
|
+
*
|
|
158
|
+
* `match: "email"` is permissive — every Better Auth method that
|
|
159
|
+
* creates a user populates `email`, including GitHub (via the
|
|
160
|
+
* upstream profile). No registration constraint to enforce.
|
|
161
|
+
*/
|
|
162
|
+
/** @internal exported for unit tests; not part of the public API. */
|
|
163
|
+
export function validateBootstrap(rule, methods) {
|
|
164
|
+
if (rule.match === "github-login") {
|
|
165
|
+
const hasGithub = methods.some((m) => m.kind === "social" && m.provider === "github");
|
|
166
|
+
if (!hasGithub) {
|
|
167
|
+
throw new Error("createAuth: bootstrapOwner.match='github-login' but no `social` method with provider='github' is registered. " +
|
|
168
|
+
"Either register a github social method or switch to `bootstrapOwner: { match: 'email', value: '…' }`.");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/** @internal exported for unit tests; not part of the public API. */
|
|
173
|
+
export function shouldPromoteToOwner(rule, user) {
|
|
174
|
+
const target = rule.value.trim().toLowerCase();
|
|
175
|
+
switch (rule.match) {
|
|
176
|
+
case "github-login":
|
|
177
|
+
return !!user.githubLogin && user.githubLogin.toLowerCase() === target;
|
|
178
|
+
case "email":
|
|
179
|
+
return !!user.email && user.email.toLowerCase() === target;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Find the at-most-one method of `kind`. Throws when adopters register
|
|
184
|
+
* the same kind twice — Better Auth's plugin layer accepts duplicates
|
|
185
|
+
* silently, which would mask the intent at boot. One helper covers
|
|
186
|
+
* every singleton-shaped method (email-otp, magic-link, future ones).
|
|
187
|
+
*/
|
|
188
|
+
function pickSingleton(methods, kind) {
|
|
189
|
+
const matches = methods.filter((m) => m.kind === kind);
|
|
190
|
+
if (matches.length > 1) {
|
|
191
|
+
throw new Error(`createAuth: more than one \`${kind}\` method registered. Combine into one.`);
|
|
192
|
+
}
|
|
193
|
+
return matches[0];
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Origins each registered social provider needs in
|
|
197
|
+
* `trustedOrigins`. Adding a provider that demands an extra
|
|
198
|
+
* `trustedOrigins` entry = adding a row here. Apple is the only one
|
|
199
|
+
* in 1.6.9 that hard-requires this; if Better Auth ever drops the
|
|
200
|
+
* requirement, the entry stays harmless (Better Auth dedupes).
|
|
201
|
+
*/
|
|
202
|
+
const SOCIAL_PROVIDER_TRUSTED_ORIGINS = {
|
|
203
|
+
apple: ["https://appleid.apple.com"],
|
|
204
|
+
};
|
|
205
|
+
function autoTrustedOriginsFor(methods) {
|
|
206
|
+
const origins = methods.flatMap((m) => m.kind === "social" ? SOCIAL_PROVIDER_TRUSTED_ORIGINS[m.provider] ?? [] : []);
|
|
207
|
+
return [...new Set(origins)];
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Apple uses `response_mode=form_post` — Apple POSTs cross-site to
|
|
211
|
+
* our callback. The OAuth state cookie must have `sameSite: "none"`
|
|
212
|
+
* (and `secure: true`, which browsers require alongside) or the
|
|
213
|
+
* cookie won't ride the POST and Better Auth raises a state mismatch.
|
|
214
|
+
* Other providers don't need this. We only auto-set when Apple is
|
|
215
|
+
* registered AND the adopter hasn't already specified
|
|
216
|
+
* `defaultCookieAttributes.sameSite` themselves.
|
|
217
|
+
*/
|
|
218
|
+
function methodsRequireSameSiteNone(methods) {
|
|
219
|
+
return methods.some((m) => m.kind === "social" && m.provider === "apple");
|
|
220
|
+
}
|
|
221
|
+
function buildAuth(config) {
|
|
222
|
+
if (config.methods.length === 0) {
|
|
223
|
+
throw new Error("createAuth: methods[] is empty — register at least one AuthMethodConfig so staff can sign in.");
|
|
224
|
+
}
|
|
225
|
+
if (config.bootstrapOwner) {
|
|
226
|
+
validateBootstrap(config.bootstrapOwner, config.methods);
|
|
227
|
+
}
|
|
228
|
+
const socialProviders = buildSocialProviders(config.methods);
|
|
229
|
+
const bootstrap = config.bootstrapOwner;
|
|
230
|
+
const emailOtpMethod = pickSingleton(config.methods, "email-otp");
|
|
231
|
+
const magicLinkMethod = pickSingleton(config.methods, "magic-link");
|
|
232
|
+
// Rate limit: Better Auth's per-route limits gate on
|
|
233
|
+
// `process.env.NODE_ENV === "production"`, which is unset on
|
|
234
|
+
// Cloudflare Workers — leaving the limits silently off. When any
|
|
235
|
+
// email-shaped method is wired (free email-send-to-any-address
|
|
236
|
+
// surface) we ALWAYS turn limits on; adopter can override
|
|
237
|
+
// window/max via `config.rateLimit`.
|
|
238
|
+
const hasEmailMethod = !!(emailOtpMethod || magicLinkMethod);
|
|
239
|
+
const rateLimitDefault = hasEmailMethod
|
|
240
|
+
? { window: 60, max: 10, enabled: true }
|
|
241
|
+
: null;
|
|
242
|
+
const rateLimit = config.rateLimit
|
|
243
|
+
? { ...config.rateLimit, enabled: true }
|
|
244
|
+
: rateLimitDefault;
|
|
245
|
+
// `trustedOrigins`: per-provider auto-origins (Apple needs
|
|
246
|
+
// `https://appleid.apple.com`). No adopter override — Better Auth
|
|
247
|
+
// configuration is fully owned by the SDK (no escape hatch).
|
|
248
|
+
const trustedOrigins = autoTrustedOriginsFor(config.methods);
|
|
249
|
+
const sdkPlugins = [
|
|
250
|
+
admin({
|
|
251
|
+
defaultRole: "user",
|
|
252
|
+
adminRoles: [...ADMIN_ROLES],
|
|
253
|
+
ac,
|
|
254
|
+
roles: {
|
|
255
|
+
owner: ownerAc,
|
|
256
|
+
editor: editorAc,
|
|
257
|
+
contributor: contributorAc,
|
|
258
|
+
user: userAc,
|
|
259
|
+
},
|
|
260
|
+
}),
|
|
261
|
+
...(emailOtpMethod ? [buildEmailOTPPlugin(emailOtpMethod)] : []),
|
|
262
|
+
...(magicLinkMethod ? [buildMagicLinkPlugin(magicLinkMethod)] : []),
|
|
263
|
+
];
|
|
264
|
+
// `user.additionalFields`: SDK owns `githubLogin` only.
|
|
265
|
+
const userConfig = {
|
|
266
|
+
additionalFields: {
|
|
267
|
+
githubLogin: {
|
|
268
|
+
type: "string",
|
|
269
|
+
required: false,
|
|
270
|
+
input: false,
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
// `advanced`: SDK owns `backgroundTasks`. Apple auto-injects
|
|
275
|
+
// `defaultCookieAttributes.sameSite: "none"` because Apple's
|
|
276
|
+
// `form_post` callback is cross-site and a `lax` cookie won't ride
|
|
277
|
+
// it (Better Auth's default raises a state-mismatch).
|
|
278
|
+
const appleNeedsCrossSite = methodsRequireSameSiteNone(config.methods);
|
|
279
|
+
const advancedConfig = {
|
|
280
|
+
...(appleNeedsCrossSite
|
|
281
|
+
? {
|
|
282
|
+
// Browsers require `secure: true` whenever `sameSite: "none"`.
|
|
283
|
+
defaultCookieAttributes: { secure: true, sameSite: "none" },
|
|
284
|
+
}
|
|
285
|
+
: {}),
|
|
286
|
+
// Fire-and-forget hook closes the user-existence timing oracle
|
|
287
|
+
// on OTP send — see § "Auth as contract" notes in ADR-0014.
|
|
288
|
+
backgroundTasks: {
|
|
289
|
+
handler: (p) => {
|
|
290
|
+
p.catch((err) => {
|
|
291
|
+
// eslint-disable-next-line no-console
|
|
292
|
+
console.error("[better-auth backgroundTask]", err);
|
|
293
|
+
});
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
// `databaseHooks`: SDK owns `user.create.after` for bootstrap-owner
|
|
298
|
+
// promotion (when `bootstrapOwner` is configured).
|
|
299
|
+
const sdkUserCreateAfter = async (user) => {
|
|
300
|
+
if (!bootstrap)
|
|
301
|
+
return;
|
|
302
|
+
const u = user;
|
|
303
|
+
if (!shouldPromoteToOwner(bootstrap, u))
|
|
304
|
+
return;
|
|
305
|
+
// Atomic check-then-promote: the `NOT EXISTS` is a GLOBAL guard —
|
|
306
|
+
// it asks "does any user already hold an admin role?". The whole
|
|
307
|
+
// statement runs as one D1 op, so two concurrent first signups
|
|
308
|
+
// can't both win: the loser's UPDATE finds an admin in the
|
|
309
|
+
// subquery and silently writes zero rows.
|
|
310
|
+
const placeholders = ADMIN_ROLES.map(() => "?").join(",");
|
|
311
|
+
const result = await config.database
|
|
312
|
+
.prepare(`UPDATE user SET role = ? WHERE id = ? AND NOT EXISTS (SELECT 1 FROM user WHERE role IN (${placeholders}))`)
|
|
313
|
+
.bind("owner", u.id, ...ADMIN_ROLES)
|
|
314
|
+
.run();
|
|
315
|
+
if ((result.meta?.changes ?? 0) === 0) {
|
|
316
|
+
// Operator-visible signal that the rule matched but a prior
|
|
317
|
+
// admin already exists — otherwise the silent no-op makes a
|
|
318
|
+
// misconfigured bootstrap rule indistinguishable from a working
|
|
319
|
+
// first-promotion.
|
|
320
|
+
console.warn(`[bootstrap] user ${u.id} matched bootstrapOwner rule but promotion was blocked — an admin user already exists.`);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
const databaseHooks = {
|
|
324
|
+
user: {
|
|
325
|
+
create: { after: sdkUserCreateAfter },
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
return betterAuth({
|
|
329
|
+
database: config.database,
|
|
330
|
+
secret: config.secret,
|
|
331
|
+
baseURL: config.baseURL,
|
|
332
|
+
socialProviders,
|
|
333
|
+
user: userConfig,
|
|
334
|
+
...(rateLimit ? { rateLimit } : {}),
|
|
335
|
+
trustedOrigins,
|
|
336
|
+
advanced: advancedConfig,
|
|
337
|
+
plugins: sdkPlugins,
|
|
338
|
+
databaseHooks,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
export function createAuth(config) {
|
|
342
|
+
const auth = buildAuth(config);
|
|
343
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
344
|
+
const api = auth.api;
|
|
345
|
+
return {
|
|
346
|
+
handler: (request) => auth.handler(request),
|
|
347
|
+
getSession: (request) => api.getSession({ headers: request.headers }).then((r) => r ?? null),
|
|
348
|
+
getUserRole: async (userId) => {
|
|
349
|
+
const row = await config.database
|
|
350
|
+
.prepare("SELECT role FROM user WHERE id = ? LIMIT 1")
|
|
351
|
+
.bind(userId)
|
|
352
|
+
.first();
|
|
353
|
+
return row?.role ?? null;
|
|
354
|
+
},
|
|
355
|
+
methods: config.methods.map((m) => m.kind === "social"
|
|
356
|
+
? { kind: "social", provider: m.provider }
|
|
357
|
+
: { kind: m.kind }),
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=createAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createAuth.js","sourceRoot":"","sources":["../../src/auth/createAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AssetServer } from "@aotter/mantle-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `AssetServer` impl wrapping Cloudflare's `ASSETS` binding (a
|
|
4
|
+
* `Fetcher` that serves the worker's bundled static assets). Returns
|
|
5
|
+
* the asset Response, or `null` when the asset is not found so the
|
|
6
|
+
* runtime's HTTP layer can fall back to the SPA's `index.html`
|
|
7
|
+
* catchall (React Router model).
|
|
8
|
+
*/
|
|
9
|
+
export declare class AssetsAssetServer implements AssetServer {
|
|
10
|
+
private readonly assets;
|
|
11
|
+
constructor(assets: Fetcher);
|
|
12
|
+
fetch(req: Request): Promise<Response | null>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=AssetsAssetServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssetsAssetServer.d.ts","sourceRoot":"","sources":["../../src/bindings/AssetsAssetServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D;;;;;;GAMG;AACH,qBAAa,iBAAkB,YAAW,WAAW;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,OAAO;IAEtC,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;CAKpD"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `AssetServer` impl wrapping Cloudflare's `ASSETS` binding (a
|
|
3
|
+
* `Fetcher` that serves the worker's bundled static assets). Returns
|
|
4
|
+
* the asset Response, or `null` when the asset is not found so the
|
|
5
|
+
* runtime's HTTP layer can fall back to the SPA's `index.html`
|
|
6
|
+
* catchall (React Router model).
|
|
7
|
+
*/
|
|
8
|
+
export class AssetsAssetServer {
|
|
9
|
+
assets;
|
|
10
|
+
constructor(assets) {
|
|
11
|
+
this.assets = assets;
|
|
12
|
+
}
|
|
13
|
+
async fetch(req) {
|
|
14
|
+
const res = await this.assets.fetch(req);
|
|
15
|
+
if (res.status === 404)
|
|
16
|
+
return null;
|
|
17
|
+
return res;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=AssetsAssetServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssetsAssetServer.js","sourceRoot":"","sources":["../../src/bindings/AssetsAssetServer.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,OAAO,iBAAiB;IACC;IAA7B,YAA6B,MAAe;QAAf,WAAM,GAAN,MAAM,CAAS;IAAG,CAAC;IAEhD,KAAK,CAAC,KAAK,CAAC,GAAY;QACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACpC,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BatchResult, DatabaseDriver, MigrationRunner, PreparedStatement } from "@aotter/mantle-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `DatabaseDriver` impl wrapping Cloudflare's `D1Database` binding.
|
|
4
|
+
*
|
|
5
|
+
* The runtime port shape is intentionally close to D1's API (which is
|
|
6
|
+
* itself close to the SQLite C API), so this wrapper is mostly a
|
|
7
|
+
* type-narrowing pass-through. The notable behaviour is the
|
|
8
|
+
* `D1Migrations` runner: it records applied migrations in a
|
|
9
|
+
* `_clam_migrations` table so subsequent boots are idempotent.
|
|
10
|
+
*
|
|
11
|
+
* Per ADR-0011 the runtime never imports `D1Database` itself — this
|
|
12
|
+
* file is the only place in the codebase that does.
|
|
13
|
+
*/
|
|
14
|
+
export declare class D1DatabaseDriver implements DatabaseDriver {
|
|
15
|
+
private readonly db;
|
|
16
|
+
readonly migrations: MigrationRunner;
|
|
17
|
+
constructor(db: D1Database);
|
|
18
|
+
prepare(sql: string): PreparedStatement;
|
|
19
|
+
batch(stmts: ReadonlyArray<PreparedStatement>): Promise<readonly BatchResult[]>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=D1DatabaseDriver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"D1DatabaseDriver.d.ts","sourceRoot":"","sources":["../../src/bindings/D1DatabaseDriver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAEd,eAAe,EACf,iBAAiB,EAElB,MAAM,wBAAwB,CAAC;AAEhC;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAiB,YAAW,cAAc;IAGzC,OAAO,CAAC,QAAQ,CAAC,EAAE;IAF/B,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;gBAER,EAAE,EAAE,UAAU;IAI3C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB;IAIjC,KAAK,CAAC,KAAK,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC;CAStF"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `DatabaseDriver` impl wrapping Cloudflare's `D1Database` binding.
|
|
3
|
+
*
|
|
4
|
+
* The runtime port shape is intentionally close to D1's API (which is
|
|
5
|
+
* itself close to the SQLite C API), so this wrapper is mostly a
|
|
6
|
+
* type-narrowing pass-through. The notable behaviour is the
|
|
7
|
+
* `D1Migrations` runner: it records applied migrations in a
|
|
8
|
+
* `_clam_migrations` table so subsequent boots are idempotent.
|
|
9
|
+
*
|
|
10
|
+
* Per ADR-0011 the runtime never imports `D1Database` itself — this
|
|
11
|
+
* file is the only place in the codebase that does.
|
|
12
|
+
*/
|
|
13
|
+
export class D1DatabaseDriver {
|
|
14
|
+
db;
|
|
15
|
+
migrations;
|
|
16
|
+
constructor(db) {
|
|
17
|
+
this.db = db;
|
|
18
|
+
this.migrations = new D1Migrations(db);
|
|
19
|
+
}
|
|
20
|
+
prepare(sql) {
|
|
21
|
+
return wrap(this.db.prepare(sql));
|
|
22
|
+
}
|
|
23
|
+
async batch(stmts) {
|
|
24
|
+
const native = stmts.map((s) => unwrap(s));
|
|
25
|
+
const results = await this.db.batch(native);
|
|
26
|
+
return results.map((r) => ({
|
|
27
|
+
success: r.success,
|
|
28
|
+
meta: { changes: r.meta.changes ?? 0 },
|
|
29
|
+
results: r.results,
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const NATIVE = new WeakMap();
|
|
34
|
+
function wrap(native) {
|
|
35
|
+
const stmt = {
|
|
36
|
+
bind: (...params) => wrap(native.bind(...params)),
|
|
37
|
+
first: () => native.first().then((v) => v ?? null),
|
|
38
|
+
all: async () => {
|
|
39
|
+
const r = await native.all();
|
|
40
|
+
return (r.results ?? []);
|
|
41
|
+
},
|
|
42
|
+
run: async () => {
|
|
43
|
+
const r = await native.run();
|
|
44
|
+
return {
|
|
45
|
+
success: r.success,
|
|
46
|
+
meta: { changes: r.meta.changes ?? 0, lastRowId: r.meta.last_row_id },
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
NATIVE.set(stmt, native);
|
|
51
|
+
return stmt;
|
|
52
|
+
}
|
|
53
|
+
function unwrap(stmt) {
|
|
54
|
+
const native = NATIVE.get(stmt);
|
|
55
|
+
if (!native) {
|
|
56
|
+
throw new Error("D1DatabaseDriver.batch received a statement not produced by this driver. " +
|
|
57
|
+
"Build statements via `db.prepare(...)` on the same DatabaseDriver instance.");
|
|
58
|
+
}
|
|
59
|
+
return native;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Migration runner. Each migration runs in its own batch — the batch
|
|
63
|
+
* includes the migration's SQL plus the `_clam_migrations` row insert,
|
|
64
|
+
* so a single migration is all-or-nothing. Migrations across boots are
|
|
65
|
+
* NOT transactional: a worker restart between migration N and N+1
|
|
66
|
+
* leaves N applied, N+1 retried on the next boot. Authors must keep
|
|
67
|
+
* each migration's SQL idempotent on retry (use `IF NOT EXISTS`,
|
|
68
|
+
* `INSERT … ON CONFLICT DO NOTHING`, etc.).
|
|
69
|
+
*/
|
|
70
|
+
class D1Migrations {
|
|
71
|
+
db;
|
|
72
|
+
constructor(db) {
|
|
73
|
+
this.db = db;
|
|
74
|
+
}
|
|
75
|
+
async runAll(migrations) {
|
|
76
|
+
await this.db
|
|
77
|
+
.prepare(`CREATE TABLE IF NOT EXISTS _migrations (id TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)`)
|
|
78
|
+
.run();
|
|
79
|
+
// One-time copy from pre-rename `_clam_migrations`: idempotent
|
|
80
|
+
// via `INSERT OR IGNORE` + `IF EXISTS`, so re-running on every
|
|
81
|
+
// boot is harmless after the rows have landed. We deliberately
|
|
82
|
+
// DON'T drop the legacy table — codex CX1 showed that any
|
|
83
|
+
// copy-then-drop ordering races between concurrent boots
|
|
84
|
+
// (Worker B's INSERT runs after Worker A's DROP succeeds and
|
|
85
|
+
// crashes with `no such table`). Leaving the legacy table
|
|
86
|
+
// around costs a few KB; eliminating it isn't worth the race
|
|
87
|
+
// class. A standalone op (`mantle migrate drop-legacy`) can
|
|
88
|
+
// remove it later under operator control if desired.
|
|
89
|
+
const legacy = await this.db
|
|
90
|
+
.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='_clam_migrations'`)
|
|
91
|
+
.first();
|
|
92
|
+
if (legacy) {
|
|
93
|
+
await this.db
|
|
94
|
+
.prepare(`INSERT OR IGNORE INTO _migrations (id, applied_at) SELECT id, applied_at FROM _clam_migrations`)
|
|
95
|
+
.run();
|
|
96
|
+
}
|
|
97
|
+
const applied = await this.db
|
|
98
|
+
.prepare(`SELECT id FROM _migrations`)
|
|
99
|
+
.all();
|
|
100
|
+
const seen = new Set((applied.results ?? []).map((r) => r.id));
|
|
101
|
+
for (const m of migrations) {
|
|
102
|
+
if (seen.has(m.id))
|
|
103
|
+
continue;
|
|
104
|
+
const statements = splitSql(m.sql);
|
|
105
|
+
const ops = statements.map((s) => this.db.prepare(s));
|
|
106
|
+
ops.push(this.db
|
|
107
|
+
.prepare(`INSERT INTO _migrations (id, applied_at) VALUES (?, ?)`)
|
|
108
|
+
.bind(m.id, Date.now()));
|
|
109
|
+
await this.db.batch(ops);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* D1 / SQLite accept multi-statement SQL on the wire, but `.batch`
|
|
115
|
+
* expects each statement separately. Splitting on `;` is correct for
|
|
116
|
+
* our migration corpus (DDL + INSERT seeds, no string literals
|
|
117
|
+
* containing `;`). When that ever stops being true, switch to a
|
|
118
|
+
* lexer-aware split.
|
|
119
|
+
*/
|
|
120
|
+
function splitSql(sql) {
|
|
121
|
+
return sql
|
|
122
|
+
.split(";")
|
|
123
|
+
.map((s) => s.trim())
|
|
124
|
+
.filter((s) => s.length > 0);
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=D1DatabaseDriver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"D1DatabaseDriver.js","sourceRoot":"","sources":["../../src/bindings/D1DatabaseDriver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { KvCache, KvListResult, KvPutOptions } from "@aotter/mantle-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `KvCache` impl wrapping Cloudflare Workers KV. Pure pass-through —
|
|
4
|
+
* the port shape is a strict subset of the KV namespace API.
|
|
5
|
+
*/
|
|
6
|
+
export declare class KvCacheBinding implements KvCache {
|
|
7
|
+
private readonly kv;
|
|
8
|
+
constructor(kv: KVNamespace);
|
|
9
|
+
get(key: string): Promise<string | null>;
|
|
10
|
+
put(key: string, value: string, opts?: KvPutOptions): Promise<void>;
|
|
11
|
+
delete(key: string): Promise<void>;
|
|
12
|
+
list(prefix: string, cursor?: string | null): Promise<KvListResult>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=KvCacheBinding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KvCacheBinding.d.ts","sourceRoot":"","sources":["../../src/bindings/KvCacheBinding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAElF;;;GAGG;AACH,qBAAa,cAAe,YAAW,OAAO;IAChC,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,WAAW;IAE5C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;CAO1E"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `KvCache` impl wrapping Cloudflare Workers KV. Pure pass-through —
|
|
3
|
+
* the port shape is a strict subset of the KV namespace API.
|
|
4
|
+
*/
|
|
5
|
+
export class KvCacheBinding {
|
|
6
|
+
kv;
|
|
7
|
+
constructor(kv) {
|
|
8
|
+
this.kv = kv;
|
|
9
|
+
}
|
|
10
|
+
get(key) {
|
|
11
|
+
return this.kv.get(key, "text");
|
|
12
|
+
}
|
|
13
|
+
put(key, value, opts) {
|
|
14
|
+
return this.kv.put(key, value, opts ? { expirationTtl: opts.expirationTtl } : undefined);
|
|
15
|
+
}
|
|
16
|
+
delete(key) {
|
|
17
|
+
return this.kv.delete(key);
|
|
18
|
+
}
|
|
19
|
+
async list(prefix, cursor) {
|
|
20
|
+
const r = await this.kv.list({ prefix, cursor: cursor ?? undefined });
|
|
21
|
+
return {
|
|
22
|
+
keys: r.keys.map((k) => k.name),
|
|
23
|
+
cursor: r.list_complete ? null : r.cursor ?? null,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=KvCacheBinding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KvCacheBinding.js","sourceRoot":"","sources":["../../src/bindings/KvCacheBinding.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,OAAO,cAAc;IACI;IAA7B,YAA6B,EAAe;QAAf,OAAE,GAAF,EAAE,CAAa;IAAG,CAAC;IAEhD,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,IAAmB;QACjD,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC3F,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAsB;QAC/C,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;QACtE,OAAO;YACL,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAC/B,MAAM,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI;SAClD,CAAC;IACJ,CAAC;CACF"}
|