@absolutejs/auth 0.22.5 → 0.22.6

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 (69) hide show
  1. package/dist/example/components/auth/AuthContainer.d.ts +1 -0
  2. package/dist/example/components/auth/OAuthButton.d.ts +7 -0
  3. package/dist/example/components/auth/OAuthButtons.d.ts +5 -0
  4. package/dist/example/components/hamburger/HamburgerDropdown.d.ts +10 -0
  5. package/dist/example/components/hamburger/HamburgerHeader.d.ts +5 -0
  6. package/dist/example/components/hamburger/HamburgerMenu.d.ts +14 -0
  7. package/dist/example/components/hamburger/HamburgerUserButtons.d.ts +8 -0
  8. package/dist/example/components/navbar/DropdownContainer.d.ts +17 -0
  9. package/dist/example/components/navbar/Navbar.d.ts +7 -0
  10. package/dist/example/components/navbar/NavbarDropdown.d.ts +10 -0
  11. package/dist/example/components/navbar/NavbarLink.d.ts +8 -0
  12. package/dist/example/components/navbar/NavbarLinks.d.ts +6 -0
  13. package/dist/example/components/navbar/NavbarUserButtons.d.ts +7 -0
  14. package/dist/example/components/page/Head.d.ts +6 -0
  15. package/dist/example/components/protected/AccountOverview.d.ts +6 -0
  16. package/dist/example/components/protected/DeleteAccountSection.d.ts +5 -0
  17. package/dist/example/components/protected/LinkedAuthIdentitiesPanel.d.ts +1 -0
  18. package/dist/example/components/protected/LinkedProvidersPanel.d.ts +1 -0
  19. package/dist/example/components/protected/ProviderButtons.d.ts +1 -0
  20. package/dist/example/components/protected/SettingsNoticeToast.d.ts +1 -0
  21. package/dist/example/components/protected/UserInfo.d.ts +7 -0
  22. package/dist/example/components/utils/AnimatedComponents.d.ts +1 -0
  23. package/dist/example/components/utils/Divider.d.ts +7 -0
  24. package/dist/example/components/utils/HighlightedJson.d.ts +5 -0
  25. package/dist/example/components/utils/JsonLine.d.ts +6 -0
  26. package/dist/example/components/utils/Modal.d.ts +9 -0
  27. package/dist/example/components/utils/ProfilePicture.d.ts +8 -0
  28. package/dist/example/components/utils/ProviderDropdown.d.ts +8 -0
  29. package/dist/example/components/utils/Toast.d.ts +14 -0
  30. package/dist/example/components/utils/ToastProvider.d.ts +30 -0
  31. package/dist/example/db/schema.d.ts +2570 -0
  32. package/dist/example/eden/treaty.d.ts +1 -0
  33. package/dist/example/handlers/userHandlers.d.ts +254 -0
  34. package/dist/example/hooks/useAuthIdentityPayload.d.ts +37 -0
  35. package/dist/example/hooks/useAuthStatus.d.ts +19 -0
  36. package/dist/example/hooks/useContainerQuery.d.ts +10 -0
  37. package/dist/example/hooks/useMediaQuery.d.ts +11 -0
  38. package/dist/example/linkedProviders/persistCallbackAuthorization.d.ts +30 -0
  39. package/dist/example/linkedProviders/resolver.d.ts +1 -0
  40. package/dist/example/linkedProviders/stores.d.ts +9 -0
  41. package/dist/example/pages/Connectors.d.ts +1 -0
  42. package/dist/example/pages/Home.d.ts +1 -0
  43. package/dist/example/pages/NotAuthorized.d.ts +1 -0
  44. package/dist/example/pages/Protected.d.ts +1 -0
  45. package/dist/example/pages/Settings.d.ts +1 -0
  46. package/dist/example/server.d.ts +902 -0
  47. package/dist/example/styles/authModalStyles.d.ts +22 -0
  48. package/dist/example/styles/navbarStyles.d.ts +15 -0
  49. package/dist/example/styles/styles.d.ts +15 -0
  50. package/dist/example/utils/absoluteAuthConfig.d.ts +4 -0
  51. package/dist/example/utils/constants.d.ts +1 -0
  52. package/dist/example/utils/navbarData.d.ts +2 -0
  53. package/dist/example/utils/providerData.d.ts +9 -0
  54. package/dist/example/utils/providersConfiguration.d.ts +1 -0
  55. package/dist/example/utils/typeGuards.d.ts +1 -0
  56. package/dist/example/utils/types.d.ts +26 -0
  57. package/dist/index.d.ts +1 -0
  58. package/dist/index.js +360 -246
  59. package/dist/index.js.map +7 -6
  60. package/dist/src/index.d.ts +1 -0
  61. package/dist/src/neonAuthSessionStore.d.ts +563 -0
  62. package/package.json +86 -74
  63. package/.claude/settings.local.json +0 -5
  64. package/.env.example +0 -212
  65. package/.prettierignore +0 -4
  66. package/.prettierrc.json +0 -9
  67. package/CLAUDE.md +0 -91
  68. package/drizzle.config.ts +0 -14
  69. package/eslint.config.mjs +0 -251
package/dist/index.js CHANGED
@@ -3289,251 +3289,6 @@ var createInMemoryAuthSessionStore = (input = {}) => {
3289
3289
  listUnregisteredSessionIds: async () => [...unregisteredSessions.keys()]
3290
3290
  };
3291
3291
  };
3292
- // src/linkedProviderResolver.ts
3293
- var uniqueStrings = (values) => [...new Set(values)];
3294
- var getEffectiveScopes = (grant, binding) => {
3295
- if (binding.availableScopes.length === 0) {
3296
- return uniqueStrings(grant.grantedScopes);
3297
- }
3298
- const bindingScopeSet = new Set(binding.availableScopes);
3299
- return uniqueStrings(grant.grantedScopes.filter((scope) => bindingScopeSet.has(scope)));
3300
- };
3301
- var hasRequiredScopes = (availableScopes, requiredScopes) => (requiredScopes ?? []).every((scope) => availableScopes.includes(scope));
3302
- var isGrantUsable = (grant) => grant.status === "active" || grant.status === "refresh_required";
3303
- var isBindingUsable = (binding) => binding.status === "active";
3304
- var needsRefresh = (lease, now, minValidityMs) => {
3305
- if (!lease)
3306
- return true;
3307
- if (lease.expiresAt === undefined)
3308
- return false;
3309
- return lease.expiresAt <= now + (minValidityMs ?? 0);
3310
- };
3311
- var ensureLeaseScopes = (lease, requiredScopes) => {
3312
- if (!hasRequiredScopes(lease.grantedScopes, requiredScopes)) {
3313
- throw new Error("Linked provider access token lease is missing required scopes");
3314
- }
3315
- };
3316
- var ensureLeaseValidity = (lease, now, minValidityMs) => {
3317
- if (lease.expiresAt === undefined)
3318
- return;
3319
- if (lease.expiresAt <= now + (minValidityMs ?? 0)) {
3320
- throw new Error("Linked provider access token lease does not satisfy minimum validity");
3321
- }
3322
- };
3323
- var buildResolvedCredential = (grant, binding) => ({
3324
- bindingId: binding.id,
3325
- grantId: grant.id,
3326
- ownerRef: grant.ownerRef,
3327
- connectorProvider: binding.connectorProvider,
3328
- providerFamily: grant.providerFamily,
3329
- authProviderKey: grant.authProviderKey,
3330
- externalAccountId: binding.externalAccountId,
3331
- externalAccountType: binding.externalAccountType,
3332
- scopes: getEffectiveScopes(grant, binding),
3333
- capabilities: binding.capabilities ? [...binding.capabilities] : undefined,
3334
- label: binding.label,
3335
- username: binding.username,
3336
- email: binding.email,
3337
- metadata: {
3338
- ...grant.metadata ?? {},
3339
- ...binding.metadata ?? {}
3340
- }
3341
- });
3342
- var annotateFailureMetadata = (metadata, report, now) => ({
3343
- ...metadata ?? {},
3344
- lastCredentialFailureAt: now,
3345
- lastCredentialFailureCode: report.code,
3346
- lastCredentialFailureMessage: report.message,
3347
- lastCredentialFailureRetryAt: report.retryAt
3348
- });
3349
- var sortNewestFirst = (items) => [...items].sort((left, right) => right.updatedAt - left.updatedAt);
3350
- var createLinkedProviderCredentialResolver = ({
3351
- grantStore,
3352
- bindingStore,
3353
- loadAccessTokenLease,
3354
- refreshAccessTokenLease,
3355
- now = () => Date.now(),
3356
- onReportFailure
3357
- }) => ({
3358
- listBindings: async ({ ownerRef, connectorProvider, status }) => sortNewestFirst(await bindingStore.listBindingsByOwner(ownerRef)).filter((binding) => (connectorProvider === undefined || binding.connectorProvider === connectorProvider) && (status === undefined || binding.status === status)),
3359
- resolveCredential: async (input) => {
3360
- const bindings = sortNewestFirst(await bindingStore.listBindingsByOwner(input.ownerRef)).filter((binding) => binding.connectorProvider === input.connectorProvider && isBindingUsable(binding) && (input.bindingId === undefined || binding.id === input.bindingId) && (input.externalAccountId === undefined || binding.externalAccountId === input.externalAccountId));
3361
- for (const binding of bindings) {
3362
- const grant = await grantStore.getGrant(binding.grantId);
3363
- if (!grant || grant.ownerRef !== input.ownerRef || !isGrantUsable(grant)) {
3364
- continue;
3365
- }
3366
- const effectiveScopes = getEffectiveScopes(grant, binding);
3367
- if (!hasRequiredScopes(effectiveScopes, input.requiredScopes)) {
3368
- continue;
3369
- }
3370
- return buildResolvedCredential(grant, binding);
3371
- }
3372
- return null;
3373
- },
3374
- getAccessToken: async (credential, input) => {
3375
- const binding = await bindingStore.getBinding(credential.bindingId);
3376
- if (!binding || !isBindingUsable(binding)) {
3377
- throw new Error("Linked provider binding is unavailable");
3378
- }
3379
- const grant = await grantStore.getGrant(credential.grantId);
3380
- if (!grant || !isGrantUsable(grant)) {
3381
- throw new Error("Linked provider grant is unavailable");
3382
- }
3383
- const requiredScopes = input?.requiredScopes;
3384
- const effectiveScopes = getEffectiveScopes(grant, binding);
3385
- if (!hasRequiredScopes(effectiveScopes, requiredScopes)) {
3386
- throw new Error("Linked provider credential is missing required scopes");
3387
- }
3388
- const currentTime = now();
3389
- let lease = await loadAccessTokenLease(grant);
3390
- if (needsRefresh(lease, currentTime, input?.minValidityMs)) {
3391
- if (!refreshAccessTokenLease) {
3392
- throw new Error("Linked provider access token lease requires refresh");
3393
- }
3394
- const refreshed = await refreshAccessTokenLease(grant, input);
3395
- if (!refreshed) {
3396
- throw new Error("Linked provider access token refresh failed");
3397
- }
3398
- await grantStore.saveGrant(refreshed.grant);
3399
- lease = refreshed.lease;
3400
- }
3401
- if (!lease) {
3402
- throw new Error("Linked provider access token lease is unavailable");
3403
- }
3404
- ensureLeaseScopes(lease, requiredScopes);
3405
- ensureLeaseValidity(lease, currentTime, input?.minValidityMs);
3406
- return lease;
3407
- },
3408
- reportFailure: async (credential, report) => {
3409
- const currentTime = now();
3410
- const grant = await grantStore.getGrant(credential.grantId);
3411
- const binding = await bindingStore.getBinding(credential.bindingId);
3412
- if (grant) {
3413
- const nextGrant = {
3414
- ...grant,
3415
- updatedAt: currentTime,
3416
- lastRefreshError: report.message ?? report.code,
3417
- metadata: annotateFailureMetadata(grant.metadata, report, currentTime)
3418
- };
3419
- if (report.code === "unauthorized" || report.code === "revoked") {
3420
- nextGrant.status = "revoked";
3421
- }
3422
- await grantStore.saveGrant(nextGrant);
3423
- }
3424
- if (binding) {
3425
- const nextBinding = {
3426
- ...binding,
3427
- updatedAt: currentTime,
3428
- metadata: annotateFailureMetadata(binding.metadata, report, currentTime)
3429
- };
3430
- if (report.code === "unauthorized" || report.code === "revoked") {
3431
- nextBinding.status = "disconnected";
3432
- } else if (report.code === "insufficient_scope") {
3433
- nextBinding.status = "restricted";
3434
- }
3435
- await bindingStore.saveBinding(nextBinding);
3436
- }
3437
- await onReportFailure?.({
3438
- credential,
3439
- report,
3440
- grant: grant ?? undefined,
3441
- binding: binding ?? undefined
3442
- });
3443
- }
3444
- });
3445
- // src/oauthLinkedProviderResolver.ts
3446
- var getGrantedScopes = (scopeValue, fallbackScopes) => {
3447
- if (typeof scopeValue === "string" && scopeValue.trim().length > 0) {
3448
- return [...new Set(scopeValue.split(/\s+/).filter(Boolean))];
3449
- }
3450
- return [...new Set(fallbackScopes.filter(Boolean))];
3451
- };
3452
- var getExpiresAt = (tokenResponse) => {
3453
- const expiresIn = tokenResponse.expires_in;
3454
- const expiresInSeconds = typeof expiresIn === "number" ? expiresIn : typeof expiresIn === "string" && expiresIn.trim().length > 0 ? Number(expiresIn) : Number.NaN;
3455
- if (!Number.isFinite(expiresInSeconds) || expiresInSeconds <= 0) {
3456
- return;
3457
- }
3458
- return Date.now() + expiresInSeconds * 1000;
3459
- };
3460
- var createOAuthLinkedProviderCredentialResolver = async ({
3461
- bindingStore,
3462
- grantStore,
3463
- now,
3464
- providersConfiguration
3465
- }) => {
3466
- const clientEntries = [];
3467
- for (const [providerName, providerConfig] of Object.entries(providersConfiguration)) {
3468
- if (!isValidProviderOption(providerName)) {
3469
- continue;
3470
- }
3471
- const resolvedProviderClientConfiguration = resolveProviderClientConfiguration({
3472
- providerName,
3473
- providersConfiguration
3474
- });
3475
- if ("error" in resolvedProviderClientConfiguration || !resolvedProviderClientConfiguration.config) {
3476
- continue;
3477
- }
3478
- clientEntries.push(createOAuth2Client(providerName, resolvedProviderClientConfiguration.config.credentials).then((providerInstance) => [providerName, providerInstance]));
3479
- }
3480
- const clients = new Map(await Promise.all(clientEntries));
3481
- return createLinkedProviderCredentialResolver({
3482
- bindingStore,
3483
- grantStore,
3484
- now,
3485
- loadAccessTokenLease: async (grant) => grant.accessTokenCiphertext ? {
3486
- accessToken: grant.accessTokenCiphertext,
3487
- expiresAt: grant.expiresAt,
3488
- grantedScopes: grant.grantedScopes,
3489
- tokenType: grant.tokenType
3490
- } : null,
3491
- refreshAccessTokenLease: async (grant) => {
3492
- if (!isValidProviderOption(grant.authProviderKey) || !grant.refreshTokenCiphertext) {
3493
- return null;
3494
- }
3495
- const providerKey = grant.authProviderKey;
3496
- const providerClientName = typeof grant.metadata?.providerClient === "string" && grant.metadata.providerClient.trim().length > 0 ? grant.metadata.providerClient.trim() : undefined;
3497
- const resolvedProviderClientConfiguration = resolveProviderClientConfiguration({
3498
- clientName: providerClientName,
3499
- providerName: providerKey,
3500
- providersConfiguration
3501
- });
3502
- if ("error" in resolvedProviderClientConfiguration || !resolvedProviderClientConfiguration.config) {
3503
- return null;
3504
- }
3505
- const providerClient = await createOAuth2Client(providerKey, resolvedProviderClientConfiguration.config.credentials);
3506
- if (!providerClient || !isRefreshableOAuth2Client(providerKey, providerClient)) {
3507
- return null;
3508
- }
3509
- const tokenResponse = await providerClient.refreshAccessToken(grant.refreshTokenCiphertext);
3510
- const refreshedAt = Date.now();
3511
- const grantedScopes = getGrantedScopes(Reflect.get(tokenResponse, "scope"), grant.grantedScopes);
3512
- const tokenType = Reflect.get(tokenResponse, "token_type");
3513
- const refreshedGrant = {
3514
- ...grant,
3515
- accessTokenCiphertext: tokenResponse.access_token,
3516
- expiresAt: getExpiresAt(tokenResponse),
3517
- grantedScopes,
3518
- lastRefreshError: undefined,
3519
- lastRefreshedAt: refreshedAt,
3520
- refreshTokenCiphertext: tokenResponse.refresh_token ?? grant.refreshTokenCiphertext,
3521
- status: "active",
3522
- tokenType: typeof tokenType === "string" ? tokenType : grant.tokenType,
3523
- updatedAt: refreshedAt
3524
- };
3525
- return {
3526
- grant: refreshedGrant,
3527
- lease: {
3528
- accessToken: refreshedGrant.accessTokenCiphertext ?? "",
3529
- expiresAt: refreshedGrant.expiresAt,
3530
- grantedScopes: refreshedGrant.grantedScopes,
3531
- tokenType: refreshedGrant.tokenType
3532
- }
3533
- };
3534
- }
3535
- });
3536
- };
3537
3292
  // node_modules/@neondatabase/serverless/index.mjs
3538
3293
  var vo = Object.create;
3539
3294
  var Te = Object.defineProperty;
@@ -13227,6 +12982,364 @@ function drizzle(...params) {
13227
12982
  drizzle2.mock = mock;
13228
12983
  })(drizzle || (drizzle = {}));
13229
12984
 
12985
+ // src/neonAuthSessionStore.ts
12986
+ var authSessionsTable = pgTable("auth_sessions", {
12987
+ id: varchar("id", { length: 255 }).primaryKey(),
12988
+ access_token: text("access_token").notNull(),
12989
+ refresh_token: text("refresh_token"),
12990
+ expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
12991
+ user_json: jsonb("user_json").$type().notNull(),
12992
+ created_at: timestamp("created_at").notNull().defaultNow(),
12993
+ updated_at: timestamp("updated_at").notNull().defaultNow()
12994
+ });
12995
+ var authUnregisteredSessionsTable = pgTable("auth_unregistered_sessions", {
12996
+ id: varchar("id", { length: 255 }).primaryKey(),
12997
+ access_token: text("access_token"),
12998
+ refresh_token: text("refresh_token"),
12999
+ expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
13000
+ user_identity_json: jsonb("user_identity_json").$type(),
13001
+ session_information_json: jsonb("session_information_json").$type(),
13002
+ created_at: timestamp("created_at").notNull().defaultNow(),
13003
+ updated_at: timestamp("updated_at").notNull().defaultNow()
13004
+ });
13005
+ var authSessionSchema = {
13006
+ authSessions: authSessionsTable,
13007
+ authUnregisteredSessions: authUnregisteredSessionsTable
13008
+ };
13009
+ var cloneUser = (value) => {
13010
+ if (value === null || value === undefined)
13011
+ return value;
13012
+ return structuredClone(value);
13013
+ };
13014
+ var cloneRecord = (value) => value ? structuredClone(value) : undefined;
13015
+ var toSessionData = (row) => ({
13016
+ accessToken: row.access_token,
13017
+ expiresAt: row.expires_at_ms,
13018
+ refreshToken: row.refresh_token ?? undefined,
13019
+ user: cloneUser(row.user_json)
13020
+ });
13021
+ var toUnregisteredSessionData = (row) => ({
13022
+ accessToken: row.access_token ?? undefined,
13023
+ expiresAt: row.expires_at_ms,
13024
+ refreshToken: row.refresh_token ?? undefined,
13025
+ sessionInformation: cloneRecord(row.session_information_json ?? undefined),
13026
+ userIdentity: cloneRecord(row.user_identity_json ?? undefined)
13027
+ });
13028
+ var createNeonAuthSessionStore = (databaseUrl) => {
13029
+ const sql2 = as(databaseUrl);
13030
+ const db = drizzle(sql2, {
13031
+ schema: authSessionSchema
13032
+ });
13033
+ return {
13034
+ getSession: async (id) => {
13035
+ const [row] = await db.select().from(authSessionsTable).where(eq(authSessionsTable.id, id)).limit(1);
13036
+ return row ? toSessionData(row) : undefined;
13037
+ },
13038
+ setSession: async (id, value) => {
13039
+ await db.insert(authSessionsTable).values({
13040
+ id,
13041
+ access_token: value.accessToken,
13042
+ refresh_token: value.refreshToken ?? null,
13043
+ expires_at_ms: value.expiresAt,
13044
+ user_json: value.user ?? {},
13045
+ updated_at: new Date
13046
+ }).onConflictDoUpdate({
13047
+ target: authSessionsTable.id,
13048
+ set: {
13049
+ access_token: value.accessToken,
13050
+ refresh_token: value.refreshToken ?? null,
13051
+ expires_at_ms: value.expiresAt,
13052
+ user_json: value.user ?? {},
13053
+ updated_at: new Date
13054
+ }
13055
+ });
13056
+ },
13057
+ removeSession: async (id) => {
13058
+ await db.delete(authSessionsTable).where(eq(authSessionsTable.id, id));
13059
+ },
13060
+ getUnregisteredSession: async (id) => {
13061
+ const [row] = await db.select().from(authUnregisteredSessionsTable).where(eq(authUnregisteredSessionsTable.id, id)).limit(1);
13062
+ return row ? toUnregisteredSessionData(row) : undefined;
13063
+ },
13064
+ setUnregisteredSession: async (id, value) => {
13065
+ await db.insert(authUnregisteredSessionsTable).values({
13066
+ id,
13067
+ access_token: value.accessToken ?? null,
13068
+ refresh_token: value.refreshToken ?? null,
13069
+ expires_at_ms: value.expiresAt,
13070
+ user_identity_json: value.userIdentity ?? null,
13071
+ session_information_json: value.sessionInformation ?? null,
13072
+ updated_at: new Date
13073
+ }).onConflictDoUpdate({
13074
+ target: authUnregisteredSessionsTable.id,
13075
+ set: {
13076
+ access_token: value.accessToken ?? null,
13077
+ refresh_token: value.refreshToken ?? null,
13078
+ expires_at_ms: value.expiresAt,
13079
+ user_identity_json: value.userIdentity ?? null,
13080
+ session_information_json: value.sessionInformation ?? null,
13081
+ updated_at: new Date
13082
+ }
13083
+ });
13084
+ },
13085
+ removeUnregisteredSession: async (id) => {
13086
+ await db.delete(authUnregisteredSessionsTable).where(eq(authUnregisteredSessionsTable.id, id));
13087
+ },
13088
+ listSessionIds: async () => {
13089
+ const rows = await db.select({ id: authSessionsTable.id }).from(authSessionsTable);
13090
+ return rows.map((row) => row.id);
13091
+ },
13092
+ listUnregisteredSessionIds: async () => {
13093
+ const rows = await db.select({ id: authUnregisteredSessionsTable.id }).from(authUnregisteredSessionsTable);
13094
+ return rows.map((row) => row.id);
13095
+ }
13096
+ };
13097
+ };
13098
+ // src/linkedProviderResolver.ts
13099
+ var uniqueStrings = (values) => [...new Set(values)];
13100
+ var getEffectiveScopes = (grant, binding) => {
13101
+ if (binding.availableScopes.length === 0) {
13102
+ return uniqueStrings(grant.grantedScopes);
13103
+ }
13104
+ const bindingScopeSet = new Set(binding.availableScopes);
13105
+ return uniqueStrings(grant.grantedScopes.filter((scope) => bindingScopeSet.has(scope)));
13106
+ };
13107
+ var hasRequiredScopes = (availableScopes, requiredScopes) => (requiredScopes ?? []).every((scope) => availableScopes.includes(scope));
13108
+ var isGrantUsable = (grant) => grant.status === "active" || grant.status === "refresh_required";
13109
+ var isBindingUsable = (binding) => binding.status === "active";
13110
+ var needsRefresh = (lease, now, minValidityMs) => {
13111
+ if (!lease)
13112
+ return true;
13113
+ if (lease.expiresAt === undefined)
13114
+ return false;
13115
+ return lease.expiresAt <= now + (minValidityMs ?? 0);
13116
+ };
13117
+ var ensureLeaseScopes = (lease, requiredScopes) => {
13118
+ if (!hasRequiredScopes(lease.grantedScopes, requiredScopes)) {
13119
+ throw new Error("Linked provider access token lease is missing required scopes");
13120
+ }
13121
+ };
13122
+ var ensureLeaseValidity = (lease, now, minValidityMs) => {
13123
+ if (lease.expiresAt === undefined)
13124
+ return;
13125
+ if (lease.expiresAt <= now + (minValidityMs ?? 0)) {
13126
+ throw new Error("Linked provider access token lease does not satisfy minimum validity");
13127
+ }
13128
+ };
13129
+ var buildResolvedCredential = (grant, binding) => ({
13130
+ bindingId: binding.id,
13131
+ grantId: grant.id,
13132
+ ownerRef: grant.ownerRef,
13133
+ connectorProvider: binding.connectorProvider,
13134
+ providerFamily: grant.providerFamily,
13135
+ authProviderKey: grant.authProviderKey,
13136
+ externalAccountId: binding.externalAccountId,
13137
+ externalAccountType: binding.externalAccountType,
13138
+ scopes: getEffectiveScopes(grant, binding),
13139
+ capabilities: binding.capabilities ? [...binding.capabilities] : undefined,
13140
+ label: binding.label,
13141
+ username: binding.username,
13142
+ email: binding.email,
13143
+ metadata: {
13144
+ ...grant.metadata ?? {},
13145
+ ...binding.metadata ?? {}
13146
+ }
13147
+ });
13148
+ var annotateFailureMetadata = (metadata, report, now) => ({
13149
+ ...metadata ?? {},
13150
+ lastCredentialFailureAt: now,
13151
+ lastCredentialFailureCode: report.code,
13152
+ lastCredentialFailureMessage: report.message,
13153
+ lastCredentialFailureRetryAt: report.retryAt
13154
+ });
13155
+ var sortNewestFirst = (items) => [...items].sort((left, right) => right.updatedAt - left.updatedAt);
13156
+ var createLinkedProviderCredentialResolver = ({
13157
+ grantStore,
13158
+ bindingStore,
13159
+ loadAccessTokenLease,
13160
+ refreshAccessTokenLease,
13161
+ now = () => Date.now(),
13162
+ onReportFailure
13163
+ }) => ({
13164
+ listBindings: async ({ ownerRef, connectorProvider, status }) => sortNewestFirst(await bindingStore.listBindingsByOwner(ownerRef)).filter((binding) => (connectorProvider === undefined || binding.connectorProvider === connectorProvider) && (status === undefined || binding.status === status)),
13165
+ resolveCredential: async (input) => {
13166
+ const bindings = sortNewestFirst(await bindingStore.listBindingsByOwner(input.ownerRef)).filter((binding) => binding.connectorProvider === input.connectorProvider && isBindingUsable(binding) && (input.bindingId === undefined || binding.id === input.bindingId) && (input.externalAccountId === undefined || binding.externalAccountId === input.externalAccountId));
13167
+ for (const binding of bindings) {
13168
+ const grant = await grantStore.getGrant(binding.grantId);
13169
+ if (!grant || grant.ownerRef !== input.ownerRef || !isGrantUsable(grant)) {
13170
+ continue;
13171
+ }
13172
+ const effectiveScopes = getEffectiveScopes(grant, binding);
13173
+ if (!hasRequiredScopes(effectiveScopes, input.requiredScopes)) {
13174
+ continue;
13175
+ }
13176
+ return buildResolvedCredential(grant, binding);
13177
+ }
13178
+ return null;
13179
+ },
13180
+ getAccessToken: async (credential, input) => {
13181
+ const binding = await bindingStore.getBinding(credential.bindingId);
13182
+ if (!binding || !isBindingUsable(binding)) {
13183
+ throw new Error("Linked provider binding is unavailable");
13184
+ }
13185
+ const grant = await grantStore.getGrant(credential.grantId);
13186
+ if (!grant || !isGrantUsable(grant)) {
13187
+ throw new Error("Linked provider grant is unavailable");
13188
+ }
13189
+ const requiredScopes = input?.requiredScopes;
13190
+ const effectiveScopes = getEffectiveScopes(grant, binding);
13191
+ if (!hasRequiredScopes(effectiveScopes, requiredScopes)) {
13192
+ throw new Error("Linked provider credential is missing required scopes");
13193
+ }
13194
+ const currentTime = now();
13195
+ let lease = await loadAccessTokenLease(grant);
13196
+ if (needsRefresh(lease, currentTime, input?.minValidityMs)) {
13197
+ if (!refreshAccessTokenLease) {
13198
+ throw new Error("Linked provider access token lease requires refresh");
13199
+ }
13200
+ const refreshed = await refreshAccessTokenLease(grant, input);
13201
+ if (!refreshed) {
13202
+ throw new Error("Linked provider access token refresh failed");
13203
+ }
13204
+ await grantStore.saveGrant(refreshed.grant);
13205
+ lease = refreshed.lease;
13206
+ }
13207
+ if (!lease) {
13208
+ throw new Error("Linked provider access token lease is unavailable");
13209
+ }
13210
+ ensureLeaseScopes(lease, requiredScopes);
13211
+ ensureLeaseValidity(lease, currentTime, input?.minValidityMs);
13212
+ return lease;
13213
+ },
13214
+ reportFailure: async (credential, report) => {
13215
+ const currentTime = now();
13216
+ const grant = await grantStore.getGrant(credential.grantId);
13217
+ const binding = await bindingStore.getBinding(credential.bindingId);
13218
+ if (grant) {
13219
+ const nextGrant = {
13220
+ ...grant,
13221
+ updatedAt: currentTime,
13222
+ lastRefreshError: report.message ?? report.code,
13223
+ metadata: annotateFailureMetadata(grant.metadata, report, currentTime)
13224
+ };
13225
+ if (report.code === "unauthorized" || report.code === "revoked") {
13226
+ nextGrant.status = "revoked";
13227
+ }
13228
+ await grantStore.saveGrant(nextGrant);
13229
+ }
13230
+ if (binding) {
13231
+ const nextBinding = {
13232
+ ...binding,
13233
+ updatedAt: currentTime,
13234
+ metadata: annotateFailureMetadata(binding.metadata, report, currentTime)
13235
+ };
13236
+ if (report.code === "unauthorized" || report.code === "revoked") {
13237
+ nextBinding.status = "disconnected";
13238
+ } else if (report.code === "insufficient_scope") {
13239
+ nextBinding.status = "restricted";
13240
+ }
13241
+ await bindingStore.saveBinding(nextBinding);
13242
+ }
13243
+ await onReportFailure?.({
13244
+ credential,
13245
+ report,
13246
+ grant: grant ?? undefined,
13247
+ binding: binding ?? undefined
13248
+ });
13249
+ }
13250
+ });
13251
+ // src/oauthLinkedProviderResolver.ts
13252
+ var getGrantedScopes = (scopeValue, fallbackScopes) => {
13253
+ if (typeof scopeValue === "string" && scopeValue.trim().length > 0) {
13254
+ return [...new Set(scopeValue.split(/\s+/).filter(Boolean))];
13255
+ }
13256
+ return [...new Set(fallbackScopes.filter(Boolean))];
13257
+ };
13258
+ var getExpiresAt = (tokenResponse) => {
13259
+ const expiresIn = tokenResponse.expires_in;
13260
+ const expiresInSeconds = typeof expiresIn === "number" ? expiresIn : typeof expiresIn === "string" && expiresIn.trim().length > 0 ? Number(expiresIn) : Number.NaN;
13261
+ if (!Number.isFinite(expiresInSeconds) || expiresInSeconds <= 0) {
13262
+ return;
13263
+ }
13264
+ return Date.now() + expiresInSeconds * 1000;
13265
+ };
13266
+ var createOAuthLinkedProviderCredentialResolver = async ({
13267
+ bindingStore,
13268
+ grantStore,
13269
+ now,
13270
+ providersConfiguration
13271
+ }) => {
13272
+ const clientEntries = [];
13273
+ for (const [providerName, providerConfig] of Object.entries(providersConfiguration)) {
13274
+ if (!isValidProviderOption(providerName)) {
13275
+ continue;
13276
+ }
13277
+ const resolvedProviderClientConfiguration = resolveProviderClientConfiguration({
13278
+ providerName,
13279
+ providersConfiguration
13280
+ });
13281
+ if ("error" in resolvedProviderClientConfiguration || !resolvedProviderClientConfiguration.config) {
13282
+ continue;
13283
+ }
13284
+ clientEntries.push(createOAuth2Client(providerName, resolvedProviderClientConfiguration.config.credentials).then((providerInstance) => [providerName, providerInstance]));
13285
+ }
13286
+ const clients = new Map(await Promise.all(clientEntries));
13287
+ return createLinkedProviderCredentialResolver({
13288
+ bindingStore,
13289
+ grantStore,
13290
+ now,
13291
+ loadAccessTokenLease: async (grant) => grant.accessTokenCiphertext ? {
13292
+ accessToken: grant.accessTokenCiphertext,
13293
+ expiresAt: grant.expiresAt,
13294
+ grantedScopes: grant.grantedScopes,
13295
+ tokenType: grant.tokenType
13296
+ } : null,
13297
+ refreshAccessTokenLease: async (grant) => {
13298
+ if (!isValidProviderOption(grant.authProviderKey) || !grant.refreshTokenCiphertext) {
13299
+ return null;
13300
+ }
13301
+ const providerKey = grant.authProviderKey;
13302
+ const providerClientName = typeof grant.metadata?.providerClient === "string" && grant.metadata.providerClient.trim().length > 0 ? grant.metadata.providerClient.trim() : undefined;
13303
+ const resolvedProviderClientConfiguration = resolveProviderClientConfiguration({
13304
+ clientName: providerClientName,
13305
+ providerName: providerKey,
13306
+ providersConfiguration
13307
+ });
13308
+ if ("error" in resolvedProviderClientConfiguration || !resolvedProviderClientConfiguration.config) {
13309
+ return null;
13310
+ }
13311
+ const providerClient = await createOAuth2Client(providerKey, resolvedProviderClientConfiguration.config.credentials);
13312
+ if (!providerClient || !isRefreshableOAuth2Client(providerKey, providerClient)) {
13313
+ return null;
13314
+ }
13315
+ const tokenResponse = await providerClient.refreshAccessToken(grant.refreshTokenCiphertext);
13316
+ const refreshedAt = Date.now();
13317
+ const grantedScopes = getGrantedScopes(Reflect.get(tokenResponse, "scope"), grant.grantedScopes);
13318
+ const tokenType = Reflect.get(tokenResponse, "token_type");
13319
+ const refreshedGrant = {
13320
+ ...grant,
13321
+ accessTokenCiphertext: tokenResponse.access_token,
13322
+ expiresAt: getExpiresAt(tokenResponse),
13323
+ grantedScopes,
13324
+ lastRefreshError: undefined,
13325
+ lastRefreshedAt: refreshedAt,
13326
+ refreshTokenCiphertext: tokenResponse.refresh_token ?? grant.refreshTokenCiphertext,
13327
+ status: "active",
13328
+ tokenType: typeof tokenType === "string" ? tokenType : grant.tokenType,
13329
+ updatedAt: refreshedAt
13330
+ };
13331
+ return {
13332
+ grant: refreshedGrant,
13333
+ lease: {
13334
+ accessToken: refreshedGrant.accessTokenCiphertext ?? "",
13335
+ expiresAt: refreshedGrant.expiresAt,
13336
+ grantedScopes: refreshedGrant.grantedScopes,
13337
+ tokenType: refreshedGrant.tokenType
13338
+ }
13339
+ };
13340
+ }
13341
+ });
13342
+ };
13230
13343
  // src/neonLinkedProviders.ts
13231
13344
  var linkedProviderGrantsTable = pgTable("linked_provider_grants", {
13232
13345
  id: varchar("id", { length: 255 }).primaryKey(),
@@ -13753,6 +13866,7 @@ export {
13753
13866
  createOAuthLinkedProviderCredentialResolver,
13754
13867
  createNeonOAuthLinkedProviderCredentialResolver,
13755
13868
  createNeonLinkedProviderStores,
13869
+ createNeonAuthSessionStore,
13756
13870
  createLinkedProviderCredentialResolver,
13757
13871
  createInMemoryLinkedProviderStores,
13758
13872
  createInMemoryAuthSessionStore,
@@ -13765,5 +13879,5 @@ export {
13765
13879
  AbsoluteAuthIdentityConflictError
13766
13880
  };
13767
13881
 
13768
- //# debugId=A110EE8D76C9D5C964756E2164756E21
13882
+ //# debugId=A6C23409DC7CDF3964756E2164756E21
13769
13883
  //# sourceMappingURL=index.js.map