feat: add ccTLD-specific date formats, noisy-token parsing, and .gg/.je/.br/.ua normalization, closes #20 and #25

- Add `toISOFromTokens` to extract ISO dates from noisy values (e.g. ".ua" `0-UANIC 20111004161638`, `OK-UNTIL 20261004161638`)
- Parse compact `YYYYMMDDHHMMSS` (.ua) and `YYYYMMDD` (.br, including ticket suffix like `20260319 #31066859`) date formats
- Parse ordinal/prose dates used by .gg/.je (`28th December 2018 at 05:54:43.861`)
- Teach `parseKeyValueLines` to collect indented continuation lines for header-style blocks (.gg/.je) without mistaking URLs or times as key separators
- Extract .gg/.je expiry from `Relevant dates:` sentences and split inline registrar URL (`epag (http://www.epag.de)`)
- Map .ua `status: OK-UNTIL <timestamp>` to `expirationDate` when no explicit expiry field is present
- Treat RDAP `pending release` / `release process: waiting` statuses as `isRegistered: false` (previously always `true`)
- Mark WHOIS `.br` `release process: waiting` as available
This commit is contained in:
2026-09-19 00:51:55 -04:00
parent e736045de1
commit be8e88592f
7 changed files with 232 additions and 23 deletions
+23
View File
@@ -112,3 +112,26 @@ test("normalizeRdap detects transfer lock with camelCase status", () => {
const rec = normalizeRdap("example.com", "com", rdap, []);
expect(rec.transferLock).toBe(true);
});
test("normalizeRdap treats release-pending statuses as not registered", () => {
const rec = normalizeRdap(
"iba.com.br",
"com.br",
{
ldhName: "iba.com.br",
status: ["pending release"],
},
[],
);
expect(rec.isRegistered).toBe(false);
const active = normalizeRdap(
"example.com",
"com",
{
ldhName: "example.com",
status: ["active"],
},
[],
);
expect(active.isRegistered).toBe(true);
});