| 1 | 39 | export function slugify(input: string): string { |
| 2 | 26 | return input |
| 3 | 36 | .normalize('NFKD') |
| 4 | 64 | .replace(/[\u0300-\u036f]/g, '') |
| 5 | 28 | .toLowerCase() |
| 6 | 14 | .trim() |
| 7 | 56 | .replace(/[^a-z0-9]+/g, '-') |
| 8 | 50 | .replace(/^-+|-+$/g, ''); |
| 9 | | } |
| 10 | | |
| 11 | 116 | export class NamespacedKeyValidationError extends Error { |
| 12 | 13 | constructor( |
| 13 | 76 | readonly field: 'namespace' | 'key', |
| 14 | 83 | readonly reason: string, |
| 15 | 10 | ) { |
| 16 | 64 | super(`${field} ${reason}`); |
| 17 | 93 | this.name = 'NamespacedKeyValidationError'; |
| 18 | | } |
| 19 | 2 | } |
| 20 | | |
| 21 | 73 | export function namespacedKey(namespace: string, key: string): string { |
| 22 | 64 | const ns = slugify(namespace); |
| 23 | 50 | const k = slugify(key); |
| 24 | 184 | if (ns === '') throw new NamespacedKeyValidationError('namespace', 'must not be empty'); |
| 25 | 170 | if (k === '') throw new NamespacedKeyValidationError('key', 'must not be empty'); |
| 26 | 41 | return `${ns}:${k}`; |
| 27 | | } |