* Find model instance
(id: string)
| 248 | * Find model instance |
| 249 | */ |
| 250 | async find(id: string): Promise<any> { |
| 251 | log('[%s] find called - id: %s', this.name, id); |
| 252 | |
| 253 | const table = this.getTable(); |
| 254 | if (!table) { |
| 255 | log('[%s] find - No table for model, returning undefined', this.name); |
| 256 | return undefined; |
| 257 | } |
| 258 | |
| 259 | try { |
| 260 | log('[%s] Executing find DB query', this.name); |
| 261 | const result = await this.db |
| 262 | .select() |
| 263 | .from(table) |
| 264 | .where(eq((table as any).id, id)) |
| 265 | .limit(1); |
| 266 | |
| 267 | log('[%s] Find query results: %O', this.name, result); |
| 268 | |
| 269 | if (!result || result.length === 0) { |
| 270 | log('[%s] No record found for id: %s', this.name, id); |
| 271 | return undefined; |
| 272 | } |
| 273 | |
| 274 | const model = result[0] as any; |
| 275 | |
| 276 | // Special handling for client model |
| 277 | if (this.name === 'Client') { |
| 278 | log('[Client] Converting client record to expected format'); |
| 279 | return { |
| 280 | application_type: model.applicationType, |
| 281 | client_id: model.id, |
| 282 | client_secret: model.clientSecret, |
| 283 | client_uri: model.clientUri, |
| 284 | grant_types: model.grants, |
| 285 | isFirstParty: model.isFirstParty, |
| 286 | logo_uri: model.logoUri, |
| 287 | policy_uri: model.policyUri, |
| 288 | redirect_uris: model.redirectUris, |
| 289 | response_types: model.responseTypes, |
| 290 | scope: model.scopes.join(' '), |
| 291 | token_endpoint_auth_method: model.tokenEndpointAuthMethod, |
| 292 | tos_uri: model.tosUri, |
| 293 | }; |
| 294 | } |
| 295 | |
| 296 | // If record has expired, return undefined |
| 297 | if (model.expiresAt && new Date() > new Date(model.expiresAt)) { |
| 298 | log('[%s] Record expired (expiresAt: %s), returning undefined', this.name, model.expiresAt); |
| 299 | return undefined; |
| 300 | } |
| 301 | |
| 302 | // If record has been consumed, check if within grace period |
| 303 | if (model.consumedAt) { |
| 304 | // For RefreshToken, allow reuse within grace period |
| 305 | if (this.name === 'RefreshToken') { |
| 306 | const consumedAt = new Date(model.consumedAt); |
| 307 | const gracePeriodEnd = new Date( |