export type ParamValue = string | number | boolean export type NeArray = [T, ...T[]] /** * Non-empty readonly array */ export type NeRoArray = readonly [T, ...T[]] export type ScopeStringFor

= | P | `${P}:${string}` | `${P}?${string}` /** * Allows to quickly check if a scope is for a specific resource. */ export function isScopeStringFor

( value: string, prefix: P, ): value is ScopeStringFor

{ if (value.length > prefix.length) { // First, check the next char is either : or ? const nextChar = value.charCodeAt(prefix.length) if (nextChar !== 0x3a /* : */ && nextChar !== 0x3f /* ? */) { return false } // Then check the full prefix return value.startsWith(prefix) } else { // value and prefix must be equal return value === prefix } } /** * Abstract interface that allows parsing various syntaxes into permission * representations. */ export interface ScopeSyntax

{ readonly prefix: P readonly positional?: ParamValue keys(): Iterable getSingle(key: string): ParamValue | null | undefined getMulti(key: string): readonly ParamValue[] | null | undefined } export function isScopeSyntaxFor

( syntax: ScopeSyntax, prefix: P, ): syntax is ScopeSyntax

{ return syntax.prefix === prefix }