1 | import { Stream } from 'xstream';
|
2 | export declare type Component<So, Si> = (sources: So, ...rest: Array<any>) => Si;
|
3 | export declare type FirstArg<T extends (r: any, ...args: Array<any>) => any> = T extends (r: infer R, ...args: Array<any>) => any ? R : any;
|
4 | export declare type IsolateableSource<A = any, B = any> = {
|
5 | isolateSource(source: IsolateableSource<A, B>, scope: any): IsolateableSource<A, B>;
|
6 | isolateSink(sink: A, scope: any): B;
|
7 | };
|
8 | export declare type Sources = {
|
9 | [name: string]: IsolateableSource;
|
10 | };
|
11 | export declare type WildcardScope = {
|
12 | ['*']?: string;
|
13 | };
|
14 | export declare type ScopesPerChannel<So> = {
|
15 | [K in keyof So]: any;
|
16 | };
|
17 | export declare type Scopes<So> = (Partial<ScopesPerChannel<So>> & WildcardScope) | string;
|
18 | /**
|
19 | * `isolate` takes a small component as input, and returns a big component.
|
20 | * A "small" component is a component that operates in a deeper scope.
|
21 | * A "big" component is a component that operates on a scope that
|
22 | * includes/wraps/nests the small component's scope. This is specially true for
|
23 | * isolation contexts such as onionify.
|
24 | *
|
25 | * Notice that we type BigSo/BigSi as any. This is unfortunate, since ideally
|
26 | * these would be generics in `isolate`. TypeScript's inference isn't strong
|
27 | * enough yet for us to automatically provide the typings that would make
|
28 | * `isolate` return a big component. However, we still keep these aliases here
|
29 | * in case TypeScript's inference becomes better, then we know how to proceed
|
30 | * to provide proper types.
|
31 | */
|
32 | export declare type OuterSo<ISo> = {
|
33 | [K in keyof ISo]: ISo[K] extends IsolateableSource ? FirstArg<IsolateableSource['isolateSource']> : ISo[K];
|
34 | };
|
35 | export declare type OuterSi<ISo, ISi> = {
|
36 | [K in keyof ISo & keyof ISi]: ISo[K] extends IsolateableSource ? (ReturnType<ISo[K]['isolateSink']> extends Stream<infer T> ? Stream<T> : (ReturnType<ISo[K]['isolateSink']> extends Stream<any> ? Stream<unknown> : unknown)) : ISi[K];
|
37 | } & {
|
38 | [K in Exclude<keyof ISi, keyof ISo>]: ISi[K];
|
39 | };
|
40 | /**
|
41 | * Takes a `component` function and a `scope`, and returns an isolated version
|
42 | * of the `component` function.
|
43 | *
|
44 | * When the isolated component is invoked, each source provided to it is
|
45 | * isolated to the given `scope` using `source.isolateSource(source, scope)`,
|
46 | * if possible. Likewise, the sinks returned from the isolated component are
|
47 | * isolated to the given `scope` using `source.isolateSink(sink, scope)`.
|
48 | *
|
49 | * The `scope` can be a string or an object. If it is anything else than those
|
50 | * two types, it will be converted to a string. If `scope` is an object, it
|
51 | * represents "scopes per channel", allowing you to specify a different scope
|
52 | * for each key of sources/sinks. For instance
|
53 | *
|
54 | * ```js
|
55 | * const childSinks = isolate(Child, {DOM: 'foo', HTTP: 'bar'})(sources);
|
56 | * ```
|
57 | *
|
58 | * You can also use a wildcard `'*'` to use as a default for source/sinks
|
59 | * channels that did not receive a specific scope:
|
60 | *
|
61 | * ```js
|
62 | * // Uses 'bar' as the isolation scope for HTTP and other channels
|
63 | * const childSinks = isolate(Child, {DOM: 'foo', '*': 'bar'})(sources);
|
64 | * ```
|
65 | *
|
66 | * If a channel's value is null, then that channel's sources and sinks won't be
|
67 | * isolated. If the wildcard is null and some channels are unspecified, those
|
68 | * channels won't be isolated. If you don't have a wildcard and some channels
|
69 | * are unspecified, then `isolate` will generate a random scope.
|
70 | *
|
71 | * ```js
|
72 | * // Does not isolate HTTP requests
|
73 | * const childSinks = isolate(Child, {DOM: 'foo', HTTP: null})(sources);
|
74 | * ```
|
75 | *
|
76 | * If the `scope` argument is not provided at all, a new scope will be
|
77 | * automatically created. This means that while **`isolate(component, scope)` is
|
78 | * pure** (referentially transparent), **`isolate(component)` is impure** (not
|
79 | * referentially transparent). Two calls to `isolate(Foo, bar)` will generate
|
80 | * the same component. But, two calls to `isolate(Foo)` will generate two
|
81 | * distinct components.
|
82 | *
|
83 | * ```js
|
84 | * // Uses some arbitrary string as the isolation scope for HTTP and other channels
|
85 | * const childSinks = isolate(Child, {DOM: 'foo'})(sources);
|
86 | * ```
|
87 | *
|
88 | * Note that both `isolateSource()` and `isolateSink()` are static members of
|
89 | * `source`. The reason for this is that drivers produce `source` while the
|
90 | * application produces `sink`, and it's the driver's responsibility to
|
91 | * implement `isolateSource()` and `isolateSink()`.
|
92 | *
|
93 | * _Note for Typescript users:_ `isolate` is not currently type-transparent and
|
94 | * will explicitly convert generic type arguments to `any`. To preserve types in
|
95 | * your components, you can use a type assertion:
|
96 | *
|
97 | * ```ts
|
98 | * // if Child is typed `Component<Sources, Sinks>`
|
99 | * const isolatedChild = isolate( Child ) as Component<Sources, Sinks>;
|
100 | * ```
|
101 | *
|
102 | * @param {Function} component a function that takes `sources` as input
|
103 | * and outputs a collection of `sinks`.
|
104 | * @param {String} scope an optional string that is used to isolate each
|
105 | * `sources` and `sinks` when the returned scoped component is invoked.
|
106 | * @return {Function} the scoped component function that, as the original
|
107 | * `component` function, takes `sources` and returns `sinks`.
|
108 | * @function isolate
|
109 | */
|
110 | declare function isolate<InnerSo, InnerSi>(component: Component<InnerSo, InnerSi>, scope?: any): Component<OuterSo<InnerSo>, OuterSi<InnerSo, InnerSi>>;
|
111 | export default isolate;
|
112 | export declare function toIsolated<InnerSo, InnerSi>(scope?: any): (c: Component<InnerSo, InnerSi>) => Component<OuterSo<InnerSo>, OuterSi<InnerSo, InnerSi>>;
|