| 481 | } |
| 482 | |
| 483 | static #parseUnixURL(url: string): AnyRedisClientOptions & { |
| 484 | socket: Exclude<AnyRedisClientOptions['socket'], undefined> & { |
| 485 | tls: boolean |
| 486 | } |
| 487 | } { |
| 488 | // unix://[user[:password]@]/path/to/sock[?db=N] |
| 489 | const match = /^unix:\/\/(?:([^:@/]*)(?::([^@/]*))?@)?(\/[^?#]*)(?:\?([^#]*))?(?:#.*)?$/.exec(url); |
| 490 | if (!match || match[3] === '/') { |
| 491 | throw new TypeError('Invalid unix URL'); |
| 492 | } |
| 493 | |
| 494 | const [, username, password, rawPath, rawQuery] = match, |
| 495 | parsed: AnyRedisClientOptions & { |
| 496 | socket: Exclude<AnyRedisClientOptions['socket'], undefined> & { |
| 497 | tls: boolean |
| 498 | } |
| 499 | } = { |
| 500 | socket: { |
| 501 | path: decodeURIComponent(rawPath), |
| 502 | tls: false |
| 503 | } |
| 504 | }; |
| 505 | |
| 506 | if (username) { |
| 507 | parsed.username = decodeURIComponent(username); |
| 508 | } |
| 509 | |
| 510 | if (password) { |
| 511 | parsed.password = decodeURIComponent(password); |
| 512 | } |
| 513 | |
| 514 | if (username || password) { |
| 515 | parsed.credentialsProvider = { |
| 516 | type: 'async-credentials-provider', |
| 517 | credentials: async () => ( |
| 518 | { |
| 519 | username: username ? decodeURIComponent(username) : undefined, |
| 520 | password: password ? decodeURIComponent(password) : undefined |
| 521 | }) |
| 522 | }; |
| 523 | } |
| 524 | |
| 525 | if (rawQuery) { |
| 526 | const db = new URLSearchParams(rawQuery).get('db'); |
| 527 | if (db !== null) { |
| 528 | const database = Number(db); |
| 529 | if (isNaN(database)) { |
| 530 | throw new TypeError('Invalid db query parameter'); |
| 531 | } |
| 532 | parsed.database = database; |
| 533 | } |
| 534 | } |
| 535 | |
| 536 | return parsed; |
| 537 | } |
| 538 | |
| 539 | readonly #options: RedisClientOptions<M, F, S, RESP, TYPE_MAPPING>; |
| 540 | #socket: RedisSocket; |