| author | |
| committer | |
| log | d87ec967bf5ef884486479e887e74307276d3e74 |
| tree | b3e5da709a275a09822ed33f4939fa42df098493 |
| parent | e55dd0067dde55770a4f7f7d1720615fcfd56389 |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: codex <codex@users.noreply.github.com>2 files changed, 18 insertions(+), 3 deletions(-)
apps/mobile/src/features/connection/pairing.test.ts+7-2| ... | @@ -1,6 +1,10 @@ | ... | @@ -1,6 +1,10 @@ |
| 1 | import { describe, expect, it } from "vite-plus/test"; | 1 | import { describe, expect, it } from "vite-plus/test"; |
| 2 | 2 | ||
| 3 | import { extractPairingUrlFromQrPayload, parsePairingUrl } from "./pairing"; | 3 | import { |
| 4 | extractPairingUrlFromQrPayload, | ||
| 5 | PairingQrPayloadEmptyError, | ||
| 6 | parsePairingUrl, | ||
| 7 | } from "./pairing"; | ||
| 4 | 8 | ||
| 5 | describe("extractPairingUrlFromQrPayload", () => { | 9 | describe("extractPairingUrlFromQrPayload", () => { |
| 6 | it("trims raw pairing urls from qr payloads", () => { | 10 | it("trims raw pairing urls from qr payloads", () => { |
| ... | @@ -18,7 +22,8 @@ describe("extractPairingUrlFromQrPayload", () => { | ... | @@ -18,7 +22,8 @@ describe("extractPairingUrlFromQrPayload", () => { |
| 18 | }); | 22 | }); |
| 19 | 23 | ||
| 20 | it("rejects empty qr payloads", () => { | 24 | it("rejects empty qr payloads", () => { |
| 21 | expect(() => extractPairingUrlFromQrPayload(" ")).toThrow( | 25 | expect(() => extractPairingUrlFromQrPayload(" ")).toThrowError(PairingQrPayloadEmptyError); |
| 26 | expect(() => extractPairingUrlFromQrPayload(" ")).toThrowError( | ||
| 22 | "Scanned QR code did not contain a pairing URL.", | 27 | "Scanned QR code did not contain a pairing URL.", |
| 23 | ); | 28 | ); |
| 24 | }); | 29 | }); |
apps/mobile/src/features/connection/pairing.ts+11-1| ... | @@ -1,7 +1,17 @@ | ... | @@ -1,7 +1,17 @@ |
| 1 | import { readHostedPairingRequest } from "@t3tools/shared/remote"; | 1 | import { readHostedPairingRequest } from "@t3tools/shared/remote"; |
| 2 | import * as Schema from "effect/Schema"; | ||
| 2 | 3 | ||
| 3 | const MOBILE_PAIRING_URL_PARAM = "pairingUrl"; | 4 | const MOBILE_PAIRING_URL_PARAM = "pairingUrl"; |
| 4 | 5 | ||
| 6 | export class PairingQrPayloadEmptyError extends Schema.TaggedErrorClass<PairingQrPayloadEmptyError>()( | ||
| 7 | "PairingQrPayloadEmptyError", | ||
| 8 | {}, | ||
| 9 | ) { | ||
| 10 | override get message(): string { | ||
| 11 | return "Scanned QR code did not contain a pairing URL."; | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 5 | export function buildPairingUrl(host: string, code: string): string { | 15 | export function buildPairingUrl(host: string, code: string): string { |
| 6 | const h = host.trim(); | 16 | const h = host.trim(); |
| 7 | const c = code.trim(); | 17 | const c = code.trim(); |
| ... | @@ -48,7 +58,7 @@ export function parsePairingUrl(url: string): { host: string; code: string } { | ... | @@ -48,7 +58,7 @@ export function parsePairingUrl(url: string): { host: string; code: string } { |
| 48 | export function extractPairingUrlFromQrPayload(payload: string): string { | 58 | export function extractPairingUrlFromQrPayload(payload: string): string { |
| 49 | const trimmed = payload.trim(); | 59 | const trimmed = payload.trim(); |
| 50 | if (!trimmed) { | 60 | if (!trimmed) { |
| 51 | throw new Error("Scanned QR code did not contain a pairing URL."); | 61 | throw new PairingQrPayloadEmptyError({}); |
| 52 | } | 62 | } |
| 53 | 63 | ||
| 54 | try { | 64 | try { |