UNPKG

4.29 kBTypeScriptView Raw
1import { Binding, BindingTag } from './binding';
2import { BindingAddress } from './binding-key';
3import { MapObject } from './value-promise';
4/**
5 * A function that filters bindings. It returns `true` to select a given
6 * binding.
7 *
8 * @remarks
9 * Originally, we allowed filters to be tied with a single value type.
10 * This actually does not make much sense - the filter function is typically
11 * invoked on all bindings to find those ones matching the given criteria.
12 * Filters must be prepared to handle bindings of any value type. We learned
13 * about this problem after enabling TypeScript's `strictFunctionTypes` check.
14 * This aspect is resolved by typing the input argument as `Binding<unknown>`.
15 *
16 * Ideally, `BindingFilter` should be declared as a type guard as follows:
17 * ```ts
18 * export type BindingFilterGuard<ValueType = unknown> = (
19 * binding: Readonly<Binding<unknown>>,
20 * ) => binding is Readonly<Binding<ValueType>>;
21 * ```
22 *
23 * But TypeScript treats the following types as incompatible and does not accept
24 * type 1 for type 2.
25 *
26 * 1. `(binding: Readonly<Binding<unknown>>) => boolean`
27 * 2. `(binding: Readonly<Binding<unknown>>) => binding is Readonly<Binding<ValueType>>`
28 *
29 * If we described BindingFilter as a type-guard, then all filter implementations
30 * would have to be explicitly typed as type-guards too, which would make it
31 * tedious to write quick filter functions like `b => b.key.startsWith('services')`.
32 *
33 * To keep things simple and easy to use, we use `boolean` as the return type
34 * of a binding filter function.
35 */
36export interface BindingFilter {
37 (binding: Readonly<Binding<unknown>>): boolean;
38}
39/**
40 * Select binding(s) by key or a filter function
41 */
42export type BindingSelector<ValueType = unknown> = BindingAddress<ValueType> | BindingFilter;
43/**
44 * Type guard for binding address
45 * @param bindingSelector - Binding key or filter function
46 */
47export declare function isBindingAddress(bindingSelector: BindingSelector): bindingSelector is BindingAddress;
48/**
49 * Binding filter function that holds a binding tag pattern. `Context.find()`
50 * uses the `bindingTagPattern` to optimize the matching of bindings by tag to
51 * avoid expensive check for all bindings.
52 */
53export interface BindingTagFilter extends BindingFilter {
54 /**
55 * A special property on the filter function to provide access to the binding
56 * tag pattern which can be utilized to optimize the matching of bindings by
57 * tag in a context.
58 */
59 bindingTagPattern: BindingTag | RegExp;
60}
61/**
62 * Type guard for BindingTagFilter
63 * @param filter - A BindingFilter function
64 */
65export declare function isBindingTagFilter(filter?: BindingFilter): filter is BindingTagFilter;
66/**
67 * A function to check if a given tag value is matched for `filterByTag`
68 */
69export interface TagValueMatcher {
70 /**
71 * Check if the given tag value matches the search criteria
72 * @param tagValue - Tag value from the binding
73 * @param tagName - Tag name
74 * @param tagMap - Tag map from the binding
75 */
76 (tagValue: unknown, tagName: string, tagMap: MapObject<unknown>): boolean;
77}
78/**
79 * A symbol that can be used to match binding tags by name regardless of the
80 * value.
81 *
82 * @example
83 *
84 * The following code matches bindings with tag `{controller: 'A'}` or
85 * `{controller: 'controller'}`. But if the tag name 'controller' does not
86 * exist for a binding, the binding will NOT be included.
87 *
88 * ```ts
89 * ctx.findByTag({controller: ANY_TAG_VALUE})
90 * ```
91 */
92export declare const ANY_TAG_VALUE: TagValueMatcher;
93/**
94 * Create a tag value matcher function that returns `true` if the target tag
95 * value equals to the item value or is an array that includes the item value.
96 * @param itemValues - A list of tag item value
97 */
98export declare function includesTagValue(...itemValues: unknown[]): TagValueMatcher;
99/**
100 * Create a binding filter for the tag pattern
101 * @param tagPattern - Binding tag name, regexp, or object
102 */
103export declare function filterByTag(tagPattern: BindingTag | RegExp): BindingTagFilter;
104/**
105 * Create a binding filter from key pattern
106 * @param keyPattern - Binding key/wildcard, regexp, or a filter function
107 */
108export declare function filterByKey(keyPattern?: string | RegExp | BindingFilter): BindingFilter;