Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# `path-matcher` — Hono-compatible path-pattern compilation and matching
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Compiles a Hono-style path pattern string into a regular expression
|
||||
|
||||
+ parameter-name list, then matches it against concrete inbound paths
|
||||
and returns the captured params. The plugin pre-compiles every
|
||||
`RouteRule.path` once at init so per-request route lookup is constant
|
||||
time per rule and zero-allocation in the happy path.
|
||||
|
||||
The matcher accepts the same forms Hono's router accepts so route
|
||||
rules written for the framework's router transparently apply to
|
||||
rate-limit rules without translation. The compiled-pattern cache is
|
||||
exposed so consumers wiring `RateLimitService.check(...)` manually
|
||||
(without the middleware) can pre-compile their own rules.
|
||||
|
||||
## Features
|
||||
|
||||
+ Exact-literal, trailing wildcard (`/api/users/*`), inline segment
|
||||
wildcard (`/api/*/avatar`), and named-param (`/api/users/:id`)
|
||||
pattern forms.
|
||||
+ Captured params returned as a frozen `Record<string, string>` so
|
||||
callers can rely on referential stability.
|
||||
+ All metacharacters in the literal portions are escaped before
|
||||
pattern composition — `?`, `.`, `+` in a path do not turn into
|
||||
regex operators by accident.
|
||||
+ Defensive: every `RegExp` construction is wrapped so a future
|
||||
pattern-syntax mistake surfaces as `RateLimitPluginError(INVALID_PATH_PATTERN)`
|
||||
rather than a bare `SyntaxError`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { isPathMatch } from "@suaveplan/api-plugin-rate-limit";
|
||||
|
||||
isPathMatch("/api/users/:id", "/api/users/123"); // true
|
||||
isPathMatch("/api/users/:id", "/api/posts/123"); // false
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
compilePathPattern,
|
||||
matchPath,
|
||||
} from "@suaveplan/api-plugin-rate-limit";
|
||||
|
||||
const pattern = compilePathPattern("/api/orgs/:org/users/:user");
|
||||
const result = matchPath(pattern, "/api/orgs/acme/users/u42");
|
||||
if (result.matched) {
|
||||
console.log(result.params); // { org: "acme", user: "u42" }
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
+ `interface CompiledPathPattern` — `{ source, regex, paramNames }`.
|
||||
+ `interface PathMatchResult` — `{ matched, params }`.
|
||||
+ `function compilePathPattern(source: string): CompiledPathPattern` —
|
||||
compile a pattern. Throws `RateLimitPluginError(INVALID_PATH_PATTERN)`
|
||||
on regex construction failure.
|
||||
+ `function matchPath(pattern: CompiledPathPattern, path: string): PathMatchResult`
|
||||
— match a compiled pattern against a path.
|
||||
+ `function isPathMatch(source: string, path: string): boolean` —
|
||||
compile + match convenience helper.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
+ Pattern compilation is `O(n)` over the source length; matching is
|
||||
`O(n)` over the path length once the regex is JIT'd by the engine.
|
||||
+ Trailing `/*` matches zero or more path segments (the trailing slash
|
||||
is optional), so `/api/users/*` matches both `/api/users/123` and
|
||||
`/api/users/` — but not `/api/users` (no trailing slash). This
|
||||
mirrors Hono's behavior.
|
||||
+ Inline `*` matches exactly one segment (`[^/]+`) — `/api/*/avatar`
|
||||
matches `/api/u1/avatar` but not `/api/u1/sub/avatar`.
|
||||
+ Named params (`:name`) bind to the captured value; the value is
|
||||
not currently used by the rate-limit service (rules apply to the
|
||||
pattern as a whole) but is preserved so downstream consumers may
|
||||
use it.
|
||||
+ The matcher is universal — zero runtime dependencies.
|
||||
Reference in New Issue
Block a user