Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions website/__tests__/matchers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,22 +215,30 @@ describe("MatchHost", () => {
describe("MatchLocation", () => {
it("matches by country", () => {
const ctx = makeCtx({ headers: { "cf-ipcountry": "BR" } });
expect(MatchLocation({ includeLocations: [{ country: "BR" }] }, ctx)).toBe(true);
expect(MatchLocation({ includeLocations: [{ type: "location", country: "BR" }] }, ctx)).toBe(
true,
);
});

it("does not match wrong country", () => {
const ctx = makeCtx({ headers: { "cf-ipcountry": "US" } });
expect(MatchLocation({ includeLocations: [{ country: "BR" }] }, ctx)).toBe(false);
expect(MatchLocation({ includeLocations: [{ type: "location", country: "BR" }] }, ctx)).toBe(
false,
);
});

it("excludes matching location", () => {
const ctx = makeCtx({ headers: { "cf-ipcountry": "BR" } });
expect(MatchLocation({ excludeLocations: [{ country: "BR" }] }, ctx)).toBe(false);
expect(MatchLocation({ excludeLocations: [{ type: "location", country: "BR" }] }, ctx)).toBe(
false,
);
});

it("matches by city", () => {
const ctx = makeCtx({ headers: { "cf-ipcity": "Sao Paulo", "cf-ipcountry": "BR" } });
expect(MatchLocation({ includeLocations: [{ city: "Sao Paulo" }] }, ctx)).toBe(true);
expect(
MatchLocation({ includeLocations: [{ type: "location", city: "Sao Paulo" }] }, ctx),
).toBe(true);
});

it("returns true when includeLocations is empty", () => {
Expand Down
26 changes: 25 additions & 1 deletion website/matchers/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,56 @@ export interface Coordinate {
radius?: number;
}

/**
* A rule that matches by a circular area (haversine radius).
*
* @title Map
*/
export interface Map {
/**
* @title Mode
* @default map
* @description Match users inside a circular area on the map.
*/
type: "map";
/**
* @title Area selection
* @format map
* @example -7.27820,-35.97630,2000
* @description "latitude,longitude,radius_in_meters" for haversine-radius matching.
*/
coordinates?: string;
coordinates: string;
}

/**
* A rule that matches by Cloudflare geo headers (country / region / city).
*
* @title Location
* @format location
*/
export interface Location {
/**
* @title Mode
* @default location
* @description Match users by country, region and city.
*/
type: "location";
/**
* @title City
* @example São Paulo
* @description Exact city name (case-insensitive) as returned by Cloudflare's cf-ipcity header.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new city field description claims matching is case-insensitive, but the matcher uses strict case-sensitive equality. Either document exact casing or normalize both sides before comparing.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At website/matchers/location.ts, line 47:

<comment>The new city field description claims matching is case-insensitive, but the matcher uses strict case-sensitive equality. Either document exact casing or normalize both sides before comparing.</comment>

<file context>
@@ -7,32 +7,56 @@ export interface Coordinate {
 	/**
 	 * @title City
 	 * @example São Paulo
+	 * @description Exact city name (case-insensitive) as returned by Cloudflare's cf-ipcity header.
 	 */
 	city?: string;
</file context>
Suggested change
* @description Exact city name (case-insensitive) as returned by Cloudflare's cf-ipcity header.
* @description Exact city name as returned by Cloudflare's cf-ipcity header.

*/
city?: string;
/**
* @title Region Code
* @example SP
* @description Matches Cloudflare's cf-region-code header — usually the ISO 3166-2 subdivision code (SP, RJ, MG, …); some regions return numeric codes. Full names like "São Paulo" are NOT matched.
*/
regionCode?: string;
/**
* @title Country
* @example BR
* @description ISO 3166-1 alpha-2 code (BR, US, AR, …) as returned by Cloudflare's cf-ipcountry header.
*/
country?: string;
}
Expand Down
Loading