feat(core-realtime): channel-template matcher (placeholder extraction)
This commit is contained in:
28
packages/core-realtime/src/channel-template.ts
Normal file
28
packages/core-realtime/src/channel-template.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
const PLACEHOLDER = /\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;
|
||||
|
||||
export function matchChannelTemplate(
|
||||
template: string,
|
||||
candidate: string,
|
||||
): { params: Record<string, string> } | null {
|
||||
// No placeholders: exact match.
|
||||
if (!template.includes("{")) {
|
||||
return template === candidate ? { params: {} } : null;
|
||||
}
|
||||
|
||||
// Build a regex from the template, replacing {name} with named groups.
|
||||
const names: string[] = [];
|
||||
const escaped = template.replace(/[.+?^${}()|[\]\\]/g, "\\$&"); // escape regex specials
|
||||
// The above escapes `{` and `}` too — restore them around placeholders.
|
||||
const pattern = escaped.replace(/\\\{([a-zA-Z_][a-zA-Z0-9_]*)\\\}/g, (_m, name) => {
|
||||
names.push(name);
|
||||
return `([^.]+)`;
|
||||
});
|
||||
const re = new RegExp(`^${pattern}$`);
|
||||
const match = candidate.match(re);
|
||||
if (!match) return null;
|
||||
const params: Record<string, string> = {};
|
||||
names.forEach((name, i) => {
|
||||
params[name] = match[i + 1]!;
|
||||
});
|
||||
return { params };
|
||||
}
|
||||
Reference in New Issue
Block a user