Skip to content

Instantly share code, notes, and snippets.

@jchild3rs
Created May 21, 2022 01:16
Show Gist options
  • Save jchild3rs/374f0c8645ccecd79b762fb01fd71821 to your computer and use it in GitHub Desktop.
Save jchild3rs/374f0c8645ccecd79b762fb01fd71821 to your computer and use it in GitHub Desktop.
import "buffer";
import P from "parsimmon";
import { NextRequest, NextResponse } from "next/server";
/** State and city tokens are just letters */
const dashToken = P.string("-");
const slashToken = P.string("/");
const zipPrefixToken = P.regex(/zip-/i);
const zipToken = P.regex(/[\d]+/i);
const poiToken = P.string("/p");
const stateToken = P.regex(/[a-z]+/i);
const locationToken = P.regex(/[a-z]+/i);
const refinementsToken = P.regex(/[\w]+/i);
/** The "-apartments" token represents all property types */
const allPropertiesToken = P.string("apartments").map(() => [
"apartments",
"condos",
"houses",
"townhouses",
]);
/** Other property types map to their defined properties */
const condosToken = P.string("condos").map(() => ["condos"]);
const housesToken = P.string("houses").map(() => ["houses"]);
const townhousesToken = P.string("townhouses").map(() => ["townhouses"]);
/** A valid property type is any of the above tokens */
const propertyTypeToken = P.alt(
allPropertiesToken,
condosToken,
housesToken,
townhousesToken
);
const propertyTypesAndMaybeRefinementsToken = P.alt(
P.seq(propertyTypeToken.skip(slashToken), refinementsToken).map(
([propertyType, refinements]) => ({
propertyType,
refinements: refinements?.split("_"),
})
),
propertyTypeToken.map((propertyType) => ({
propertyType,
}))
);
const zipRouteToken = P.seq(
slashToken.skip(zipPrefixToken),
zipToken.skip(dashToken),
propertyTypesAndMaybeRefinementsToken
).map(([_, zipCode, propertyTypeAndMaybeRefinements]) => ({
zipCode,
...propertyTypeAndMaybeRefinements,
}));
const poiRouteToken = P.seq(
poiToken.skip(slashToken),
stateToken.skip(slashToken),
locationToken.skip(dashToken),
propertyTypesAndMaybeRefinementsToken
).map(([_, state, location, propertyTypeAndMaybeRefinements]) => ({
state,
location,
...propertyTypeAndMaybeRefinements,
}));
const cityStateRouteToken = P.seq(
slashToken,
stateToken.skip(slashToken),
locationToken.skip(dashToken),
propertyTypesAndMaybeRefinementsToken
).map(([_, state, location, propertyTypeAndMaybeRefinements]) => ({
state,
location,
...propertyTypeAndMaybeRefinements,
}));
const searchParser = P.alt(poiRouteToken, zipRouteToken, cityStateRouteToken);
export function middleware(req: NextRequest) {
const url: URL = req.nextUrl;
const result = searchParser.parse(url.pathname);
if (result.status) {
console.log(result.value);
url.pathname = "/search";
for (const key of Object.keys(result.value)) {
const value = result.value[key];
if (Array.isArray(value)) {
value.forEach((val) => {
url.searchParams.append(key, val);
});
} else {
url.searchParams.append(key, value);
}
}
return NextResponse.rewrite(url);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment