Skip to content

Commit

Permalink
Merge pull request #8 from adamjosefus/development
Browse files Browse the repository at this point in the history
Mathing mask bug fixed
  • Loading branch information
adamjosefus authored Feb 12, 2022
2 parents ad12633 + b8e7f48 commit 8342ed2
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 32 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Our solution enables shift the server root that as user needs.

## Documentation 📖

Description of all classes and methods with **examples** will found in the [documentation](https://doc.deno.land/https://raw.githubusercontent.com/adamjosefus/allo_routing/main/mod.ts).
Description of all classes and methods with **examples**
will found in the [documentation](https://doc.deno.land/https://deno.land/x/allo_routing/mod.ts).

---

Expand Down
77 changes: 46 additions & 31 deletions routers/MaskRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,18 @@ import { RouterMalformedException } from "./RouterMalformedException.ts";
*/
export class MaskRouter extends Router implements IRouter {

readonly #masks: readonly string[];
readonly #mask: string;
readonly #maskVariants: readonly string[];
readonly #serveResponse: ServeResponseType;
readonly #options: Required<RouterOptions>;

readonly #varibleOpenChar = '[';
readonly #varibleCloseChar = ']';
readonly #maskParser = /\<(?<name>[a-z][A-z0-9]*)(=(?<defaultValue>.+?))?\s*(\s+(?<expression>.+?))?\>/g;

readonly #maskCache = new Cache<string>();
readonly #variantCache = new Cache<string[]>();
readonly #matchCache = new Cache<boolean>();
readonly #varialibityCache = new Cache<string[]>();
readonly #paramParserCache = new Cache<RegExp>();
readonly #paramDeclarationCache = new Cache<ParamDeclarationsType>();
readonly #paramValuesCache = new Cache<ParamValuesType | null>();
Expand All @@ -48,7 +52,8 @@ export class MaskRouter extends Router implements IRouter {
constructor(mask: string, serveResponse: ServeResponseType, options?: RouterOptions) {
super();

this.#masks = this.#parseVarialibity(MaskRouter.cleanPathname(mask));
this.#mask = this.#parseMask(mask);
this.#maskVariants = this.#parseVariants(mask);
this.#serveResponse = serveResponse;
this.#options = createRequiredOptions(options);
}
Expand All @@ -63,12 +68,12 @@ export class MaskRouter extends Router implements IRouter {

async serveResponse(req: Request): Promise<Response> {
const pathname = this.#computePathname(req);
const mask = this.#getMatchedMask(pathname);

if (mask === null) throw new Error("No mask matched");
const matchedMask = this.#getMatchedMask(pathname);
if (matchedMask === null || !this.#match(pathname)) throw new Error("No mask matched");

const params: Record<string, string> = {};
const paramValues = this.#parseParamValues(mask, pathname);
const paramValues = this.#parseParamValues(this.#mask, matchedMask, pathname);

if (paramValues === null) {
throw new Error("No param values parsed");
Expand All @@ -85,7 +90,7 @@ export class MaskRouter extends Router implements IRouter {


#match(pathname: string): boolean {
const result = this.#masks.some(mask => {
const result = this.#maskVariants.some(mask => {
return this.#matchMask(mask, pathname);
});

Expand All @@ -94,7 +99,7 @@ export class MaskRouter extends Router implements IRouter {


#getMatchedMask(pathname: string): string | null {
const result = this.#masks.find(mask => {
const result = this.#maskVariants.find(mask => {
return this.#matchMask(mask, pathname);
}) ?? null;

Expand All @@ -112,7 +117,7 @@ export class MaskRouter extends Router implements IRouter {
const paramDeclarations = this.#parseParamDeclarations(mask);
if (paramDeclarations === null) return true;

const paramValues = this.#parseParamValues(mask, pathname);
const paramValues = this.#parseParamValues(mask, mask, pathname);
if (paramValues === null) return false;

return Array.from(paramValues.values()).every(({ valid }) => valid);
Expand Down Expand Up @@ -165,31 +170,27 @@ export class MaskRouter extends Router implements IRouter {
}


#parseParamValues(mask: string, pathname: string): ParamValuesType | null {
const parse = (mask: string, pathname: string) => {
const paramParser = this.#createParamParser(mask);
const paramValues: ParamValuesType = new Map();
#parseParamValues(primaryMask: string, matchedMask: string, pathname: string): ParamValuesType | null {
const isValid = (value: string | null, expression: RegExp | null): boolean => {
if (expression === null) return true;
if (value === null) return false;

paramParser.lastIndex = 0;
if (!paramParser.test(pathname)) return null;
expression.lastIndex = 0;
return expression.test(value)
}

const paramDeclarations = this.#parseParamDeclarations(mask);
const parse = (primaryMask: string, matchedMask: string, pathname: string) => {
const paramParser = this.#createParamParser(matchedMask);
const paramValues: ParamValuesType = new Map();

const paramDeclarations = this.#parseParamDeclarations(primaryMask);
if (paramDeclarations === null) return paramValues;

paramParser.lastIndex = 0;
const exec = paramParser.exec(pathname);

const parsedValues = exec?.groups ?? {};

function isValid(value: string | null, expression: RegExp | null): boolean {
if (expression === null) return true;
if (value === null) return false;

expression.lastIndex = 0;
return expression.test(value)
}


let order = 1;
for (const [name, declaration] of paramDeclarations) {
const parsedValue = parsedValues[name] as string | undefined;
Expand All @@ -208,7 +209,7 @@ export class MaskRouter extends Router implements IRouter {
return paramValues;
}

return this.#paramValuesCache.load(`${mask}|${pathname}`, () => parse(mask, pathname));
return this.#paramValuesCache.load(`${primaryMask}|${matchedMask}|${pathname}`, () => parse(primaryMask, matchedMask, pathname));
}


Expand All @@ -226,10 +227,10 @@ export class MaskRouter extends Router implements IRouter {
}


#parseVarialibity(mask: string): string[] {
#parseVariants(mask: string): string[] {
const parse = (mask: string): string[] => {
const openChar = '[';
const closeChar = ']';
const openChar = this.#varibleOpenChar;
const closeChar = this.#varibleCloseChar;

type RangeType = {
open: number,
Expand Down Expand Up @@ -307,15 +308,29 @@ export class MaskRouter extends Router implements IRouter {
}

const result = variations.reduce((acc: string[], variation) => {
acc.push(...this.#parseVarialibity(variation));
acc.push(...this.#parseVariants(variation));

return acc;
}, []).filter((v, i, arr) => arr.indexOf(v) === i);

return result;
}

return this.#varialibityCache.load(mask, () => parse(mask));
return this.#variantCache.load(mask, () => parse(MaskRouter.cleanPathname(mask)));
}


#parseMask(mask: string): string {
const parse = (mask: string): string => {
const openChar = this.#varibleOpenChar;
const closeChar = this.#varibleCloseChar;

return MaskRouter.cleanPathname(mask)
.replaceAll(openChar, '')
.replaceAll(closeChar, '');
}

return this.#maskCache.load(mask, () => parse(mask));
}


Expand Down
8 changes: 8 additions & 0 deletions tests/MaskRouter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@ Deno.test("MaskRouter::parseParams", async () => {
presenter: "homepage",
},
},
{
mask: "[<presenter=homepage>[/<action=default>]]",
pathname: "",
expectation: {
presenter: "homepage",
action: "default",
},
},
];


Expand Down

0 comments on commit 8342ed2

Please sign in to comment.