Listory/src/open-telemetry/url-value-parser.service.ts

65 lines
1.6 KiB
TypeScript

import { Injectable } from "@nestjs/common";
// Service adapted from https://github.com/disjunction/url-value-parser
const REPLACE_MASKS: RegExp[] = [
/^\-?\d+$/,
/^(\d{2}|\d{4})\-\d\d\-\d\d$/, // date
/^[\da-f]{8}\-[\da-f]{4}\-[\da-f]{4}\-[\da-f]{4}\-[\da-f]{12}$/, // UUID
/^[\dA-F]{8}\-[\dA-F]{4}\-[\dA-F]{4}\-[\dA-F]{4}\-[\dA-F]{12}$/, // UUID uppercased
// hex code sould have a consistent case
/^[\da-f]{7,}$/,
/^[\dA-F]{7,}$/,
// base64 encoded with URL safe Base64
/^[a-zA-Z0-9\-_]{22,}$/,
// classic Base64
/^(?:[A-Za-z0-9+/]{4}){16,}(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?/,
];
@Injectable()
export class UrlValueParserService {
/**
* replacePathValues replaces IDs and other identifiers from URL paths.
*/
public replacePathValues(path: string, replacement: string = "#val"): string {
const parseResult = this.parsePathValues(path);
return (
"/" +
parseResult.chunks
.map((chunk, i) =>
parseResult.valueIndexes.includes(i) ? replacement : chunk
)
.join("/")
);
}
private getPathChunks(path: string): string[] {
return path.split("/").filter((chunk) => chunk !== "");
}
private parsePathValues(path: string): {
chunks: string[];
valueIndexes: number[];
} {
const chunks = this.getPathChunks(path);
const valueIndexes = chunks
.map((chunk, index) => (this.isValue(chunk) ? index : null))
.filter((index) => index !== null);
return { chunks, valueIndexes };
}
private isValue(str: string): boolean {
for (let mask of REPLACE_MASKS) {
if (str.match(mask)) {
return true;
}
}
return false;
}
}