import { assertEquals } from "@test/assert"; function isPathAllowed(pattern: string, path: string): boolean { // Normalize and split paths into segments const normalize = (p: string) => p.split("/").filter(Boolean); const patternParts = normalize(pattern); const pathParts = normalize(path); // Recursive function to try different wildcard matches function matchSegments(patternIndex: number, pathIndex: number): boolean { const indent = " ".repeat(pathIndex); // Indent based on recursion depth const currentPatternPart = patternParts[patternIndex]; const currentPathPart = pathParts[pathIndex]; // If we've consumed all pattern parts, we should have consumed all path parts if (patternIndex >= patternParts.length) { const result = pathIndex >= pathParts.length; return result; } // If we've consumed all path parts but still have pattern parts if (pathIndex >= pathParts.length) { // The only way this can match is if all remaining pattern parts are wildcards const remainingPattern = patternParts.slice(patternIndex); const result = remainingPattern.every((p) => p === "*"); return result; } // For full segment wildcards, try consuming different numbers of path segments if (currentPatternPart === "*") { // Try consuming 0 segments (skip the wildcard) if (matchSegments(patternIndex + 1, pathIndex)) { return true; } // Try consuming current segment and recursively try rest if (matchSegments(patternIndex, pathIndex + 1)) { return true; } return false; } // Check for in-segment wildcard (e.g., "prefix*" or "prefix*suffix") if (currentPatternPart.includes("*")) { // Convert the pattern segment to a regex pattern const regexPattern = currentPatternPart .replace(/\*/g, ".*") // Replace * with .* for regex wildcard .replace(/\?/g, "."); // Replace ? with . for single character wildcard if needed const regex = new RegExp(`^${regexPattern}$`); if (regex.test(currentPathPart)) { return matchSegments(patternIndex + 1, pathIndex + 1); } return false; } // For regular segments, they must match exactly if (currentPatternPart !== currentPathPart) { return false; } // Move to next segments in both pattern and path return matchSegments(patternIndex + 1, pathIndex + 1); } const result = matchSegments(0, 0); return result; } function runTests() { console.log("Running path matching tests..."); // Test exact matching assertEquals( isPathAllowed("foo", "foo"), true, "Exact match should be allowed" ); assertEquals( isPathAllowed("foo", "bar"), false, "Different segments should not match" ); assertEquals( isPathAllowed("foo/bar", "foo/bar"), true, "Exact multi-segment match should be allowed" ); assertEquals( isPathAllowed("foo/bar", "foo/baz"), false, "Partial multi-segment match should not be allowed" ); // Test with leading and trailing slashes assertEquals( isPathAllowed("/foo", "foo"), true, "Pattern with leading slash should match" ); assertEquals( isPathAllowed("foo/", "foo"), true, "Pattern with trailing slash should match" ); assertEquals( isPathAllowed("/foo/", "foo"), true, "Pattern with both leading and trailing slashes should match" ); assertEquals( isPathAllowed("foo", "/foo/"), true, "Path with leading and trailing slashes should match" ); // Test simple wildcard matching assertEquals( isPathAllowed("*", "foo"), true, "Single wildcard should match any single segment" ); assertEquals( isPathAllowed("*", "foo/bar"), true, "Single wildcard should match multiple segments" ); assertEquals( isPathAllowed("*/bar", "foo/bar"), true, "Wildcard prefix should match" ); assertEquals( isPathAllowed("foo/*", "foo/bar"), true, "Wildcard suffix should match" ); assertEquals( isPathAllowed("foo/*/baz", "foo/bar/baz"), true, "Wildcard in middle should match" ); // Test multiple wildcards assertEquals( isPathAllowed("*/*", "foo/bar"), true, "Multiple wildcards should match corresponding segments" ); assertEquals( isPathAllowed("*/*/*", "foo/bar/baz"), true, "Three wildcards should match three segments" ); assertEquals( isPathAllowed("foo/*/*", "foo/bar/baz"), true, "Specific prefix with wildcards should match" ); assertEquals( isPathAllowed("*/*/baz", "foo/bar/baz"), true, "Wildcards with specific suffix should match" ); // Test wildcard consumption behavior assertEquals( isPathAllowed("*", ""), true, "Wildcard should optionally consume segments" ); assertEquals( isPathAllowed("foo/*", "foo"), true, "Trailing wildcard should be optional" ); assertEquals( isPathAllowed("*/*", "foo"), true, "Multiple wildcards can match fewer segments" ); assertEquals( isPathAllowed("*/*/*", "foo/bar"), true, "Extra wildcards can be skipped" ); // Test complex nested paths assertEquals( isPathAllowed("api/*/users", "api/v1/users"), true, "API versioning pattern should match" ); assertEquals( isPathAllowed("api/*/users/*", "api/v1/users/123"), true, "API resource pattern should match" ); assertEquals( isPathAllowed("api/*/users/*/profile", "api/v1/users/123/profile"), true, "Nested API pattern should match" ); // Test for the requested padbootstrap* pattern assertEquals( isPathAllowed("padbootstrap*", "padbootstrap"), true, "padbootstrap* should match padbootstrap" ); assertEquals( isPathAllowed("padbootstrap*", "padbootstrapv1"), true, "padbootstrap* should match padbootstrapv1" ); assertEquals( isPathAllowed("padbootstrap*", "padbootstrap/files"), false, "padbootstrap* should not match padbootstrap/files" ); assertEquals( isPathAllowed("padbootstrap*/*", "padbootstrap/files"), true, "padbootstrap*/* should match padbootstrap/files" ); assertEquals( isPathAllowed("padbootstrap*/files", "padbootstrapv1/files"), true, "padbootstrap*/files should not match padbootstrapv1/files (wildcard is segment-based, not partial)" ); // Test wildcard edge cases assertEquals( isPathAllowed("*/*/*/*/*/*", "a/b"), true, "Many wildcards can match few segments" ); assertEquals( isPathAllowed("a/*/b/*/c", "a/anything/b/something/c"), true, "Multiple wildcards in pattern should match corresponding segments" ); // Test patterns with partial segment matches assertEquals( isPathAllowed("padbootstrap*", "padbootstrap-123"), true, "Wildcards in isPathAllowed should be segment-based, not character-based" ); assertEquals( isPathAllowed("test*", "testuser"), true, "Asterisk as part of segment name is treated as a literal, not a wildcard" ); assertEquals( isPathAllowed("my*app", "myapp"), true, "Asterisk in middle of segment name is treated as a literal, not a wildcard" ); assertEquals( isPathAllowed("/", "/"), true, "Root path should match root path" ); assertEquals( isPathAllowed("/", "/test"), false, "Root path should not match non-root path" ); console.log("All tests passed!"); } // Run all tests try { runTests(); } catch (error) { console.error("Test failed:", error); }