@technomoron/api-server-base 1.1.13 → 2.0.0-beta.10

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 (116) hide show
  1. package/README.txt +25 -2
  2. package/dist/cjs/api-server-base.cjs +448 -111
  3. package/dist/cjs/api-server-base.d.ts +91 -34
  4. package/dist/cjs/auth-api/auth-module.d.ts +105 -0
  5. package/dist/cjs/auth-api/auth-module.js +1180 -0
  6. package/dist/cjs/auth-api/compat-auth-storage.d.ts +57 -0
  7. package/dist/cjs/auth-api/compat-auth-storage.js +128 -0
  8. package/dist/cjs/auth-api/mem-auth-store.d.ts +68 -0
  9. package/dist/cjs/auth-api/mem-auth-store.js +141 -0
  10. package/dist/cjs/{auth-module.d.ts → auth-api/module.d.ts} +7 -7
  11. package/dist/cjs/{auth-module.cjs → auth-api/module.js} +1 -1
  12. package/dist/cjs/auth-api/sql-auth-store.d.ts +77 -0
  13. package/dist/cjs/auth-api/sql-auth-store.js +172 -0
  14. package/dist/cjs/auth-api/storage.d.ts +38 -0
  15. package/dist/cjs/{auth-storage.cjs → auth-api/storage.js} +17 -7
  16. package/dist/cjs/auth-api/types.d.ts +34 -0
  17. package/dist/cjs/auth-api/types.js +2 -0
  18. package/dist/cjs/index.cjs +41 -7
  19. package/dist/cjs/index.d.ts +29 -5
  20. package/dist/cjs/oauth/base.d.ts +10 -0
  21. package/dist/cjs/oauth/base.js +6 -0
  22. package/dist/cjs/oauth/memory.d.ts +16 -0
  23. package/dist/cjs/oauth/memory.js +99 -0
  24. package/dist/cjs/oauth/models.d.ts +45 -0
  25. package/dist/cjs/oauth/models.js +58 -0
  26. package/dist/cjs/oauth/sequelize.d.ts +68 -0
  27. package/dist/cjs/oauth/sequelize.js +210 -0
  28. package/dist/cjs/oauth/types.d.ts +50 -0
  29. package/dist/cjs/oauth/types.js +3 -0
  30. package/dist/cjs/passkey/base.d.ts +16 -0
  31. package/dist/cjs/passkey/base.js +6 -0
  32. package/dist/cjs/passkey/memory.d.ts +27 -0
  33. package/dist/cjs/passkey/memory.js +86 -0
  34. package/dist/cjs/passkey/models.d.ts +25 -0
  35. package/dist/cjs/passkey/models.js +115 -0
  36. package/dist/cjs/passkey/sequelize.d.ts +55 -0
  37. package/dist/cjs/passkey/sequelize.js +220 -0
  38. package/dist/cjs/passkey/service.d.ts +20 -0
  39. package/dist/cjs/passkey/service.js +356 -0
  40. package/dist/cjs/passkey/types.d.ts +78 -0
  41. package/dist/cjs/passkey/types.js +2 -0
  42. package/dist/cjs/token/base.d.ts +38 -0
  43. package/dist/cjs/token/base.js +114 -0
  44. package/dist/cjs/token/memory.d.ts +19 -0
  45. package/dist/cjs/token/memory.js +149 -0
  46. package/dist/cjs/token/sequelize.d.ts +58 -0
  47. package/dist/cjs/token/sequelize.js +404 -0
  48. package/dist/cjs/token/types.d.ts +27 -0
  49. package/dist/cjs/token/types.js +2 -0
  50. package/dist/cjs/user/base.d.ts +26 -0
  51. package/dist/cjs/user/base.js +45 -0
  52. package/dist/cjs/user/memory.d.ts +35 -0
  53. package/dist/cjs/user/memory.js +173 -0
  54. package/dist/cjs/user/sequelize.d.ts +41 -0
  55. package/dist/cjs/user/sequelize.js +182 -0
  56. package/dist/cjs/user/types.d.ts +11 -0
  57. package/dist/cjs/user/types.js +2 -0
  58. package/dist/esm/api-server-base.d.ts +91 -34
  59. package/dist/esm/api-server-base.js +447 -110
  60. package/dist/esm/auth-api/auth-module.d.ts +105 -0
  61. package/dist/esm/auth-api/auth-module.js +1178 -0
  62. package/dist/esm/auth-api/compat-auth-storage.d.ts +57 -0
  63. package/dist/esm/auth-api/compat-auth-storage.js +124 -0
  64. package/dist/esm/auth-api/mem-auth-store.d.ts +68 -0
  65. package/dist/esm/auth-api/mem-auth-store.js +137 -0
  66. package/dist/esm/{auth-module.d.ts → auth-api/module.d.ts} +7 -7
  67. package/dist/esm/{auth-module.js → auth-api/module.js} +1 -1
  68. package/dist/esm/auth-api/sql-auth-store.d.ts +77 -0
  69. package/dist/esm/auth-api/sql-auth-store.js +168 -0
  70. package/dist/esm/auth-api/storage.d.ts +38 -0
  71. package/dist/esm/{auth-storage.js → auth-api/storage.js} +15 -5
  72. package/dist/esm/auth-api/types.d.ts +34 -0
  73. package/dist/esm/auth-api/types.js +1 -0
  74. package/dist/esm/index.d.ts +29 -5
  75. package/dist/esm/index.js +19 -2
  76. package/dist/esm/oauth/base.d.ts +10 -0
  77. package/dist/esm/oauth/base.js +2 -0
  78. package/dist/esm/oauth/memory.d.ts +16 -0
  79. package/dist/esm/oauth/memory.js +92 -0
  80. package/dist/esm/oauth/models.d.ts +45 -0
  81. package/dist/esm/oauth/models.js +51 -0
  82. package/dist/esm/oauth/sequelize.d.ts +68 -0
  83. package/dist/esm/oauth/sequelize.js +199 -0
  84. package/dist/esm/oauth/types.d.ts +50 -0
  85. package/dist/esm/oauth/types.js +2 -0
  86. package/dist/esm/passkey/base.d.ts +16 -0
  87. package/dist/esm/passkey/base.js +2 -0
  88. package/dist/esm/passkey/memory.d.ts +27 -0
  89. package/dist/esm/passkey/memory.js +82 -0
  90. package/dist/esm/passkey/models.d.ts +25 -0
  91. package/dist/esm/passkey/models.js +108 -0
  92. package/dist/esm/passkey/sequelize.d.ts +55 -0
  93. package/dist/esm/passkey/sequelize.js +216 -0
  94. package/dist/esm/passkey/service.d.ts +20 -0
  95. package/dist/esm/passkey/service.js +319 -0
  96. package/dist/esm/passkey/types.d.ts +78 -0
  97. package/dist/esm/passkey/types.js +1 -0
  98. package/dist/esm/token/base.d.ts +38 -0
  99. package/dist/esm/token/base.js +107 -0
  100. package/dist/esm/token/memory.d.ts +19 -0
  101. package/dist/esm/token/memory.js +145 -0
  102. package/dist/esm/token/sequelize.d.ts +58 -0
  103. package/dist/esm/token/sequelize.js +400 -0
  104. package/dist/esm/token/types.d.ts +27 -0
  105. package/dist/esm/token/types.js +1 -0
  106. package/dist/esm/user/base.d.ts +26 -0
  107. package/dist/esm/user/base.js +38 -0
  108. package/dist/esm/user/memory.d.ts +35 -0
  109. package/dist/esm/user/memory.js +169 -0
  110. package/dist/esm/user/sequelize.d.ts +41 -0
  111. package/dist/esm/user/sequelize.js +176 -0
  112. package/dist/esm/user/types.d.ts +11 -0
  113. package/dist/esm/user/types.js +1 -0
  114. package/package.json +13 -3
  115. package/dist/cjs/auth-storage.d.ts +0 -133
  116. package/dist/esm/auth-storage.d.ts +0 -133
@@ -0,0 +1,38 @@
1
+ import type { AuthAdapter, AuthIdentifier } from './types.js';
2
+ import type { AuthCodeData, AuthCodeRequest, OAuthClient } from '../oauth/types.js';
3
+ import type { PasskeyChallenge, PasskeyChallengeParams, PasskeyVerificationParams, PasskeyVerificationResult, StoredPasskeyCredential } from '../passkey/types.js';
4
+ import type { Token } from '../token/types.js';
5
+ export declare class BaseAuthAdapter<UserRow = unknown, SafeUser = unknown> implements AuthAdapter<UserRow, SafeUser> {
6
+ getUser(identifier: AuthIdentifier): Promise<UserRow | null>;
7
+ getUserPasswordHash(user: UserRow): string;
8
+ getUserId(user: UserRow): AuthIdentifier;
9
+ filterUser(user: UserRow): SafeUser;
10
+ verifyPassword(password: string, hash: string): Promise<boolean>;
11
+ storeToken(data: Token): Promise<void>;
12
+ getToken(query: Partial<Omit<Token, 'userId' | 'ruid'>> & {
13
+ userId?: string | number;
14
+ ruid?: string | number;
15
+ }, opts?: {
16
+ includeExpired?: boolean;
17
+ }): Promise<Token | null>;
18
+ deleteToken(query: Partial<Omit<Token, 'userId' | 'ruid'>> & {
19
+ userId?: string | number;
20
+ ruid?: string | number;
21
+ }): Promise<number>;
22
+ updateToken(updates: Partial<Token> & {
23
+ refreshToken: string;
24
+ }): Promise<boolean>;
25
+ createPasskeyChallenge(params: PasskeyChallengeParams): Promise<PasskeyChallenge>;
26
+ verifyPasskeyResponse(params: PasskeyVerificationParams): Promise<PasskeyVerificationResult>;
27
+ listUserCredentials(userId: AuthIdentifier): Promise<StoredPasskeyCredential[]>;
28
+ deletePasskeyCredential(credentialId: Buffer | string): Promise<boolean>;
29
+ getClient(clientId: string): Promise<OAuthClient | null>;
30
+ verifyClientSecret(client: OAuthClient, clientSecret: string | null): Promise<boolean>;
31
+ createAuthCode(request: AuthCodeRequest): Promise<AuthCodeData>;
32
+ consumeAuthCode(code: string, clientId: string): Promise<AuthCodeData | null>;
33
+ canImpersonate(params: {
34
+ realUserId: AuthIdentifier;
35
+ effectiveUserId: AuthIdentifier;
36
+ }): Promise<boolean>;
37
+ }
38
+ export declare const nullAuthAdapter: AuthAdapter<unknown, unknown>;
@@ -1,7 +1,6 @@
1
- // Numeric database id or lookup string such as username/email.
2
- // Handy base you can extend when wiring a real storage adapter. Every method
1
+ // Handy base you can extend when wiring a real auth adapter. Every method
3
2
  // throws by default so unimplemented hooks fail loudly.
4
- export class BaseAuthStorage {
3
+ export class BaseAuthAdapter {
5
4
  // Override to load a user record by identifier
6
5
  async getUser(identifier) {
7
6
  void identifier;
@@ -33,8 +32,9 @@ export class BaseAuthStorage {
33
32
  throw new Error('Auth storage not configured');
34
33
  }
35
34
  // Override to look up a stored token by query
36
- async getToken(query) {
35
+ async getToken(query, opts) {
37
36
  void query;
37
+ void opts;
38
38
  return null;
39
39
  }
40
40
  // Override to remove stored tokens that match the query
@@ -57,6 +57,16 @@ export class BaseAuthStorage {
57
57
  void params;
58
58
  throw new Error('Auth storage not configured');
59
59
  }
60
+ // Override to list passkey credentials for a user
61
+ async listUserCredentials(userId) {
62
+ void userId;
63
+ throw new Error('Auth storage not configured');
64
+ }
65
+ // Override to delete a passkey credential
66
+ async deletePasskeyCredential(credentialId) {
67
+ void credentialId;
68
+ throw new Error('Auth storage not configured');
69
+ }
60
70
  // Override to fetch an OAuth client by identifier
61
71
  async getClient(clientId) {
62
72
  void clientId;
@@ -85,4 +95,4 @@ export class BaseAuthStorage {
85
95
  return false;
86
96
  }
87
97
  }
88
- export const nullAuthStorage = new BaseAuthStorage();
98
+ export const nullAuthAdapter = new BaseAuthAdapter();
@@ -0,0 +1,34 @@
1
+ import type { AuthCodeData, AuthCodeRequest, OAuthClient } from '../oauth/types.js';
2
+ import type { PasskeyChallenge, PasskeyChallengeParams, PasskeyVerificationParams, PasskeyVerificationResult, StoredPasskeyCredential } from '../passkey/types.js';
3
+ import type { Token } from '../token/types.js';
4
+ export type AuthIdentifier = string | number;
5
+ /** @internal */
6
+ export interface AuthAdapter<UserRow, SafeUser> {
7
+ getUser(identifier: AuthIdentifier): Promise<UserRow | null>;
8
+ getUserPasswordHash(user: UserRow): string;
9
+ getUserId(user: UserRow): AuthIdentifier;
10
+ filterUser(user: UserRow): SafeUser;
11
+ verifyPassword(password: string, hash: string): Promise<boolean>;
12
+ storeToken(data: Token): Promise<void>;
13
+ getToken(query: Partial<Token>, opts?: {
14
+ includeExpired?: boolean;
15
+ }): Promise<Token | null>;
16
+ deleteToken(query: Partial<Token>): Promise<number>;
17
+ updateToken?(updates: Partial<Token> & {
18
+ refreshToken: string;
19
+ }): Promise<boolean>;
20
+ createPasskeyChallenge?(params: PasskeyChallengeParams): Promise<PasskeyChallenge>;
21
+ verifyPasskeyResponse?(params: PasskeyVerificationParams): Promise<PasskeyVerificationResult>;
22
+ listUserCredentials?(userId: AuthIdentifier): Promise<StoredPasskeyCredential[]>;
23
+ deletePasskeyCredential?(credentialId: Buffer | string): Promise<boolean>;
24
+ getClient?(clientId: string): Promise<OAuthClient | null>;
25
+ verifyClientSecret?(client: OAuthClient, clientSecret: string | null): Promise<boolean>;
26
+ createAuthCode?(request: AuthCodeRequest): Promise<AuthCodeData>;
27
+ consumeAuthCode?(code: string, clientId: string): Promise<AuthCodeData | null>;
28
+ canImpersonate?(params: {
29
+ realUserId: AuthIdentifier;
30
+ effectiveUserId: AuthIdentifier;
31
+ }): Promise<boolean>;
32
+ }
33
+ /** @internal */
34
+ export type AuthStorage<UserRow, SafeUser> = AuthAdapter<UserRow, SafeUser>;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,8 +1,32 @@
1
1
  export { default as ApiServer } from './api-server-base.js';
2
2
  export { ApiError } from './api-server-base.js';
3
3
  export { ApiModule } from './api-module.js';
4
- export type { ApiErrorParams, ApiHandler, ApiKey, ApiServerConf, ApiRequest, ApiRoute, ApiAuthType, ApiAuthClass, ApiTokenData, RequestWithStuff } from './api-server-base.js';
5
- export type { AuthIdentifier, AuthTokenMetadata, AuthTokenData, AuthTokenQuery, AuthTokenPair, AuthTokenPayload, PasskeyChallengeParams, PasskeyChallenge, PasskeyVerificationParams, PasskeyVerificationResult, OAuthClient, AuthCodeData, AuthCodeRequest, AuthStorage } from './auth-storage.js';
6
- export type { AuthProviderModule } from './auth-module.js';
7
- export { nullAuthStorage, BaseAuthStorage } from './auth-storage.js';
8
- export { nullAuthModule, BaseAuthModule } from './auth-module.js';
4
+ export type { ApiErrorParams, ApiHandler, ApiKey, ApiServerConf, ApiRequest, ApiRoute, ApiAuthType, ApiAuthClass, ApiTokenData, ExtendedReq, ExpressApiRequest, ExpressApiLocals } from './api-server-base.js';
5
+ export type { AuthIdentifier } from './auth-api/types.js';
6
+ export type { Token, TokenPair, TokenStatus } from './token/types.js';
7
+ export type { JwtSignResult, JwtVerifyResult, JwtDecodeResult } from './token/base.js';
8
+ export type { OAuthClient, AuthCodeData, AuthCodeRequest } from './oauth/types.js';
9
+ export type { AuthProviderModule } from './auth-api/module.js';
10
+ export { nullAuthAdapter, BaseAuthAdapter } from './auth-api/storage.js';
11
+ export { nullAuthModule, BaseAuthModule } from './auth-api/module.js';
12
+ export { CompositeAuthAdapter } from './auth-api/compat-auth-storage.js';
13
+ export { MemAuthStore } from './auth-api/mem-auth-store.js';
14
+ export { SqlAuthStore } from './auth-api/sql-auth-store.js';
15
+ export { default as AuthModule } from './auth-api/auth-module.js';
16
+ export type { OAuthStartParams, OAuthStartResult, OAuthCallbackParams, OAuthCallbackResult } from './oauth/types.js';
17
+ export type { BcryptHasherOptions, CreateUserInput, UpdateUserInput, PublicUserMapper } from './user/types.js';
18
+ export { UserStore } from './user/base.js';
19
+ export { MemoryUserStore } from './user/memory.js';
20
+ export { SequelizeUserStore } from './user/sequelize.js';
21
+ export type { MemoryUserAttributes, MemoryUserStoreOptions } from './user/memory.js';
22
+ export { TokenStore } from './token/base.js';
23
+ export { MemoryTokenStore } from './token/memory.js';
24
+ export { SequelizeTokenStore } from './token/sequelize.js';
25
+ export { PasskeyService } from './passkey/service.js';
26
+ export { PasskeyStore } from './passkey/base.js';
27
+ export { MemoryPasskeyStore } from './passkey/memory.js';
28
+ export { SequelizePasskeyStore } from './passkey/sequelize.js';
29
+ export type { PasskeyServiceConfig, PasskeyChallengeRecord, PasskeyUserDescriptor, StoredPasskeyCredential, PasskeyChallenge, PasskeyChallengeParams, PasskeyVerificationParams, PasskeyVerificationResult } from './passkey/types.js';
30
+ export { OAuthStore } from './oauth/base.js';
31
+ export { MemoryOAuthStore } from './oauth/memory.js';
32
+ export { SequelizeOAuthStore } from './oauth/sequelize.js';
package/dist/esm/index.js CHANGED
@@ -1,5 +1,22 @@
1
1
  export { default as ApiServer } from './api-server-base.js';
2
2
  export { ApiError } from './api-server-base.js';
3
3
  export { ApiModule } from './api-module.js';
4
- export { nullAuthStorage, BaseAuthStorage } from './auth-storage.js';
5
- export { nullAuthModule, BaseAuthModule } from './auth-module.js';
4
+ export { nullAuthAdapter, BaseAuthAdapter } from './auth-api/storage.js';
5
+ export { nullAuthModule, BaseAuthModule } from './auth-api/module.js';
6
+ export { CompositeAuthAdapter } from './auth-api/compat-auth-storage.js';
7
+ export { MemAuthStore } from './auth-api/mem-auth-store.js';
8
+ export { SqlAuthStore } from './auth-api/sql-auth-store.js';
9
+ export { default as AuthModule } from './auth-api/auth-module.js';
10
+ export { UserStore } from './user/base.js';
11
+ export { MemoryUserStore } from './user/memory.js';
12
+ export { SequelizeUserStore } from './user/sequelize.js';
13
+ export { TokenStore } from './token/base.js';
14
+ export { MemoryTokenStore } from './token/memory.js';
15
+ export { SequelizeTokenStore } from './token/sequelize.js';
16
+ export { PasskeyService } from './passkey/service.js';
17
+ export { PasskeyStore } from './passkey/base.js';
18
+ export { MemoryPasskeyStore } from './passkey/memory.js';
19
+ export { SequelizePasskeyStore } from './passkey/sequelize.js';
20
+ export { OAuthStore } from './oauth/base.js';
21
+ export { MemoryOAuthStore } from './oauth/memory.js';
22
+ export { SequelizeOAuthStore } from './oauth/sequelize.js';
@@ -0,0 +1,10 @@
1
+ import type { AuthCode, OAuthClient } from './types.js';
2
+ export declare abstract class OAuthStore {
3
+ abstract getClient(clientId: string): Promise<OAuthClient | null>;
4
+ abstract createClient(input: OAuthClient): Promise<OAuthClient>;
5
+ abstract verifyClientSecret(clientId: string, secret: string | null): Promise<boolean>;
6
+ abstract createAuthCode(code: AuthCode): Promise<void>;
7
+ abstract consumeAuthCode(code: string): Promise<AuthCode | null>;
8
+ abstract close(): Promise<void>;
9
+ }
10
+ export type { OAuthClient, AuthCode } from './types.js';
@@ -0,0 +1,2 @@
1
+ export class OAuthStore {
2
+ }
@@ -0,0 +1,16 @@
1
+ import { OAuthStore, type AuthCode, type OAuthClient } from './base.js';
2
+ export interface MemoryOAuthStoreOptions {
3
+ bcryptRounds?: number;
4
+ }
5
+ export declare class MemoryOAuthStore extends OAuthStore {
6
+ private readonly clients;
7
+ private readonly codes;
8
+ private readonly bcryptRounds;
9
+ constructor(options?: MemoryOAuthStoreOptions);
10
+ getClient(clientId: string): Promise<OAuthClient | null>;
11
+ createClient(input: OAuthClient): Promise<OAuthClient>;
12
+ verifyClientSecret(clientId: string, secret: string | null): Promise<boolean>;
13
+ createAuthCode(code: AuthCode): Promise<void>;
14
+ consumeAuthCode(code: string): Promise<AuthCode | null>;
15
+ close(): Promise<void>;
16
+ }
@@ -0,0 +1,92 @@
1
+ import bcrypt from 'bcryptjs';
2
+ import { OAuthStore } from './base.js';
3
+ function cloneClient(client) {
4
+ if (!client) {
5
+ return null;
6
+ }
7
+ return {
8
+ clientId: client.clientId,
9
+ clientSecret: client.clientSecret,
10
+ name: client.name,
11
+ redirectUris: [...client.redirectUris],
12
+ scope: client.scope ? [...client.scope] : undefined,
13
+ metadata: client.metadata ? { ...client.metadata } : undefined,
14
+ firstParty: client.firstParty
15
+ };
16
+ }
17
+ function cloneCode(code) {
18
+ return {
19
+ ...code,
20
+ scope: code.scope ? [...code.scope] : undefined,
21
+ expiresAt: new Date(code.expiresAt),
22
+ metadata: code.metadata ? { ...code.metadata } : undefined
23
+ };
24
+ }
25
+ function normalizeUserId(identifier) {
26
+ if (typeof identifier === 'number' && Number.isFinite(identifier)) {
27
+ return identifier;
28
+ }
29
+ if (typeof identifier === 'string' && /^\d+$/.test(identifier)) {
30
+ return Number(identifier);
31
+ }
32
+ throw new Error(`Unable to normalise user identifier: ${identifier}`);
33
+ }
34
+ export class MemoryOAuthStore extends OAuthStore {
35
+ constructor(options = {}) {
36
+ super();
37
+ this.clients = new Map();
38
+ this.codes = new Map();
39
+ this.bcryptRounds = options.bcryptRounds ?? 12;
40
+ }
41
+ async getClient(clientId) {
42
+ return cloneClient(this.clients.get(clientId));
43
+ }
44
+ async createClient(input) {
45
+ const clientSecret = input.clientSecret ? await bcrypt.hash(input.clientSecret, this.bcryptRounds) : '';
46
+ const stored = {
47
+ clientId: input.clientId,
48
+ clientSecret,
49
+ name: input.name,
50
+ redirectUris: [...input.redirectUris],
51
+ scope: input.scope ? [...input.scope] : undefined,
52
+ metadata: input.metadata ? { ...input.metadata } : undefined,
53
+ firstParty: input.firstParty
54
+ };
55
+ this.clients.set(stored.clientId, stored);
56
+ return cloneClient(stored);
57
+ }
58
+ async verifyClientSecret(clientId, secret) {
59
+ const client = this.clients.get(clientId);
60
+ if (!client) {
61
+ return false;
62
+ }
63
+ if (!client.clientSecret) {
64
+ return !secret || secret.length === 0;
65
+ }
66
+ if (!secret) {
67
+ return false;
68
+ }
69
+ return bcrypt.compare(secret, client.clientSecret);
70
+ }
71
+ async createAuthCode(code) {
72
+ const record = {
73
+ ...code,
74
+ userId: normalizeUserId(code.userId),
75
+ scope: code.scope ? [...code.scope] : undefined,
76
+ expiresAt: code.expiresAt,
77
+ metadata: code.metadata ? { ...code.metadata } : undefined
78
+ };
79
+ this.codes.set(record.code, record);
80
+ }
81
+ async consumeAuthCode(code) {
82
+ const record = this.codes.get(code);
83
+ if (!record) {
84
+ return null;
85
+ }
86
+ this.codes.delete(code);
87
+ return cloneCode(record);
88
+ }
89
+ async close() {
90
+ return;
91
+ }
92
+ }
@@ -0,0 +1,45 @@
1
+ import { Model, type Optional, type Sequelize } from 'sequelize';
2
+ export interface OAuthClientAttributes {
3
+ client_id: string;
4
+ client_secret: string;
5
+ name: string | null;
6
+ redirect_uris: string;
7
+ scope: string;
8
+ metadata: string | null;
9
+ first_party: boolean;
10
+ }
11
+ export type OAuthClientCreationAttributes = Optional<OAuthClientAttributes, 'client_secret' | 'name' | 'scope' | 'metadata' | 'first_party'>;
12
+ export declare class OAuthClientModel extends Model<OAuthClientAttributes, OAuthClientCreationAttributes> implements OAuthClientAttributes {
13
+ client_id: string;
14
+ client_secret: string;
15
+ name: string | null;
16
+ redirect_uris: string;
17
+ scope: string;
18
+ metadata: string | null;
19
+ first_party: boolean;
20
+ }
21
+ export declare function initOAuthClientModel(sequelize: Sequelize): typeof OAuthClientModel;
22
+ export interface OAuthCodeAttributes {
23
+ code: string;
24
+ client_id: string;
25
+ user_id: number;
26
+ redirect_uri: string;
27
+ scope: string;
28
+ code_challenge: string | null;
29
+ code_challenge_method: 'plain' | 'S256' | null;
30
+ expires: Date;
31
+ metadata: string | null;
32
+ }
33
+ export type OAuthCodeCreationAttributes = Optional<OAuthCodeAttributes, 'code_challenge' | 'code_challenge_method' | 'metadata'>;
34
+ export declare class OAuthCodeModel extends Model<OAuthCodeAttributes, OAuthCodeCreationAttributes> implements OAuthCodeAttributes {
35
+ code: string;
36
+ client_id: string;
37
+ user_id: number;
38
+ redirect_uri: string;
39
+ scope: string;
40
+ code_challenge: string | null;
41
+ code_challenge_method: 'plain' | 'S256' | null;
42
+ expires: Date;
43
+ metadata: string | null;
44
+ }
45
+ export declare function initOAuthCodeModel(sequelize: Sequelize): typeof OAuthCodeModel;
@@ -0,0 +1,51 @@
1
+ import { DataTypes, Model } from 'sequelize';
2
+ const DIALECTS_SUPPORTING_UNSIGNED = new Set(['mysql', 'mariadb']);
3
+ function integerIdType(sequelize) {
4
+ return DIALECTS_SUPPORTING_UNSIGNED.has(sequelize.getDialect()) ? DataTypes.INTEGER.UNSIGNED : DataTypes.INTEGER;
5
+ }
6
+ function tableOptions(sequelize, tableName, extra) {
7
+ const opts = { sequelize, tableName };
8
+ if (extra) {
9
+ Object.assign(opts, extra);
10
+ }
11
+ if (DIALECTS_SUPPORTING_UNSIGNED.has(sequelize.getDialect())) {
12
+ opts.charset = 'utf8mb4';
13
+ opts.collate = 'utf8mb4_unicode_ci';
14
+ }
15
+ return opts;
16
+ }
17
+ export class OAuthClientModel extends Model {
18
+ }
19
+ export function initOAuthClientModel(sequelize) {
20
+ OAuthClientModel.init({
21
+ client_id: { type: DataTypes.STRING(128), allowNull: false, primaryKey: true },
22
+ client_secret: { type: DataTypes.STRING(255), allowNull: false, defaultValue: '' },
23
+ name: { type: DataTypes.STRING(128), allowNull: true, defaultValue: null },
24
+ redirect_uris: { type: DataTypes.TEXT, allowNull: false, defaultValue: '[]' },
25
+ scope: { type: DataTypes.TEXT, allowNull: false, defaultValue: '[]' },
26
+ metadata: { type: DataTypes.TEXT, allowNull: true, defaultValue: null },
27
+ first_party: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false }
28
+ }, {
29
+ ...tableOptions(sequelize, 'oauth_clients', { timestamps: false })
30
+ });
31
+ return OAuthClientModel;
32
+ }
33
+ export class OAuthCodeModel extends Model {
34
+ }
35
+ export function initOAuthCodeModel(sequelize) {
36
+ const idType = integerIdType(sequelize);
37
+ OAuthCodeModel.init({
38
+ code: { type: DataTypes.STRING(128), allowNull: false, primaryKey: true },
39
+ client_id: { type: DataTypes.STRING(128), allowNull: false },
40
+ user_id: { type: idType, allowNull: false },
41
+ redirect_uri: { type: DataTypes.TEXT, allowNull: false },
42
+ scope: { type: DataTypes.TEXT, allowNull: false, defaultValue: '[]' },
43
+ code_challenge: { type: DataTypes.STRING(255), allowNull: true, defaultValue: null },
44
+ code_challenge_method: { type: DataTypes.STRING(10), allowNull: true, defaultValue: null },
45
+ expires: { type: DataTypes.DATE, allowNull: false },
46
+ metadata: { type: DataTypes.TEXT, allowNull: true, defaultValue: null }
47
+ }, {
48
+ ...tableOptions(sequelize, 'oauth_codes', { timestamps: false })
49
+ });
50
+ return OAuthCodeModel;
51
+ }
@@ -0,0 +1,68 @@
1
+ import { Model, type Optional, type Sequelize } from 'sequelize';
2
+ import { OAuthStore, type AuthCode, type OAuthClient } from './base.js';
3
+ export interface OAuthClientAttributes {
4
+ client_id: string;
5
+ client_secret: string;
6
+ name: string | null;
7
+ redirect_uris: string;
8
+ scope: string;
9
+ metadata: string | null;
10
+ first_party: boolean;
11
+ }
12
+ export type OAuthClientCreationAttributes = Optional<OAuthClientAttributes, 'client_secret' | 'name' | 'scope' | 'metadata' | 'first_party'>;
13
+ export declare class OAuthClientModel extends Model<OAuthClientAttributes, OAuthClientCreationAttributes> implements OAuthClientAttributes {
14
+ client_id: string;
15
+ client_secret: string;
16
+ name: string | null;
17
+ redirect_uris: string;
18
+ scope: string;
19
+ metadata: string | null;
20
+ first_party: boolean;
21
+ }
22
+ export declare function initOAuthClientModel(sequelize: Sequelize): typeof OAuthClientModel;
23
+ export interface OAuthCodeAttributes {
24
+ code: string;
25
+ client_id: string;
26
+ user_id: number;
27
+ redirect_uri: string;
28
+ scope: string;
29
+ code_challenge: string | null;
30
+ code_challenge_method: 'plain' | 'S256' | null;
31
+ expires: Date;
32
+ metadata: string | null;
33
+ }
34
+ export type OAuthCodeCreationAttributes = Optional<OAuthCodeAttributes, 'code_challenge' | 'code_challenge_method' | 'metadata'>;
35
+ export declare class OAuthCodeModel extends Model<OAuthCodeAttributes, OAuthCodeCreationAttributes> implements OAuthCodeAttributes {
36
+ code: string;
37
+ client_id: string;
38
+ user_id: number;
39
+ redirect_uri: string;
40
+ scope: string;
41
+ code_challenge: string | null;
42
+ code_challenge_method: 'plain' | 'S256' | null;
43
+ expires: Date;
44
+ metadata: string | null;
45
+ }
46
+ export declare function initOAuthCodeModel(sequelize: Sequelize): typeof OAuthCodeModel;
47
+ export interface SequelizeOAuthStoreOptions {
48
+ sequelize: Sequelize;
49
+ clientModel?: typeof OAuthClientModel;
50
+ codeModel?: typeof OAuthCodeModel;
51
+ clientModelFactory?: (sequelize: Sequelize) => typeof OAuthClientModel;
52
+ codeModelFactory?: (sequelize: Sequelize) => typeof OAuthCodeModel;
53
+ bcryptRounds?: number;
54
+ }
55
+ export declare class SequelizeOAuthStore extends OAuthStore {
56
+ private readonly clients;
57
+ private readonly codes;
58
+ private readonly bcryptRounds;
59
+ constructor(options: SequelizeOAuthStoreOptions);
60
+ getClient(clientId: string): Promise<OAuthClient | null>;
61
+ createClient(input: OAuthClient): Promise<OAuthClient>;
62
+ verifyClientSecret(clientId: string, clientSecret: string | null): Promise<boolean>;
63
+ createAuthCode(code: AuthCode): Promise<void>;
64
+ consumeAuthCode(code: string): Promise<AuthCode | null>;
65
+ close(): Promise<void>;
66
+ private toOAuthClient;
67
+ private toAuthCode;
68
+ }