@cycle/isolate

  • Version 5.2.0
  • Published
  • 64.3 kB
  • 2 dependencies
  • MIT license

Install

npm i @cycle/isolate
yarn add @cycle/isolate
pnpm add @cycle/isolate

Overview

A utility function to make scoped dataflow components in Cycle.js

Index

Functions

function isolate

isolate: <InnerSo, InnerSi>(
component: Component<InnerSo, InnerSi>,
scope?: any
) => Component<OuterSo<InnerSo>, OuterSi<InnerSo, InnerSi>>;
  • Takes a component function and a scope, and returns an isolated version of the component function.

    When the isolated component is invoked, each source provided to it is isolated to the given scope using source.isolateSource(source, scope), if possible. Likewise, the sinks returned from the isolated component are isolated to the given scope using source.isolateSink(sink, scope).

    The scope can be a string or an object. If it is anything else than those two types, it will be converted to a string. If scope is an object, it represents "scopes per channel", allowing you to specify a different scope for each key of sources/sinks. For instance

    const childSinks = isolate(Child, {DOM: 'foo', HTTP: 'bar'})(sources);

    You can also use a wildcard '*' to use as a default for source/sinks channels that did not receive a specific scope:

    // Uses 'bar' as the isolation scope for HTTP and other channels
    const childSinks = isolate(Child, {DOM: 'foo', '*': 'bar'})(sources);

    If a channel's value is null, then that channel's sources and sinks won't be isolated. If the wildcard is null and some channels are unspecified, those channels won't be isolated. If you don't have a wildcard and some channels are unspecified, then isolate will generate a random scope.

    // Does not isolate HTTP requests
    const childSinks = isolate(Child, {DOM: 'foo', HTTP: null})(sources);

    If the scope argument is not provided at all, a new scope will be automatically created. This means that while **isolate(component, scope) is pure** (referentially transparent), **isolate(component) is impure** (not referentially transparent). Two calls to isolate(Foo, bar) will generate the same component. But, two calls to isolate(Foo) will generate two distinct components.

    // Uses some arbitrary string as the isolation scope for HTTP and other channels
    const childSinks = isolate(Child, {DOM: 'foo'})(sources);

    Note that both isolateSource() and isolateSink() are static members of source. The reason for this is that drivers produce source while the application produces sink, and it's the driver's responsibility to implement isolateSource() and isolateSink().

    _Note for Typescript users:_ isolate is not currently type-transparent and will explicitly convert generic type arguments to any. To preserve types in your components, you can use a type assertion:

    // if Child is typed `Component<Sources, Sinks>`
    const isolatedChild = isolate( Child ) as Component<Sources, Sinks>;

    Parameter component

    a function that takes sources as input and outputs a collection of sinks.

    Parameter scope

    an optional string that is used to isolate each sources and sinks when the returned scoped component is invoked. {Function} the scoped component function that, as the original component function, takes sources and returns sinks. isolate

function toIsolated

toIsolated: <InnerSo, InnerSi>(
scope?: any
) => (
c: Component<InnerSo, InnerSi>
) => Component<OuterSo<InnerSo>, OuterSi<InnerSo, InnerSi>>;

    Type Aliases

    type Component

    type Component<So, Si> = (sources: So, ...rest: Array<any>) => Si;

      type FirstArg

      type FirstArg<T extends (r: any, ...args: Array<any>) => any> = T extends (
      r: infer R,
      ...args: Array<any>
      ) => any
      ? R
      : any;

        type IsolateableSource

        type IsolateableSource<A = any, B = any> = {
        isolateSource(
        source: IsolateableSource<A, B>,
        scope: any
        ): IsolateableSource<A, B>;
        isolateSink(sink: A, scope: any): B;
        };

          type OuterSi

          type OuterSi<ISo, ISi> = {
          [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];
          } &
          {
          [K in Exclude<keyof ISi, keyof ISo>]: ISi[K];
          };

            type OuterSo

            type OuterSo<ISo> = {
            [K in keyof ISo]: ISo[K] extends IsolateableSource
            ? FirstArg<IsolateableSource['isolateSource']>
            : ISo[K];
            };
            • isolate takes a small component as input, and returns a big component. A "small" component is a component that operates in a deeper scope. A "big" component is a component that operates on a scope that includes/wraps/nests the small component's scope. This is specially true for isolation contexts such as onionify.

              Notice that we type BigSo/BigSi as any. This is unfortunate, since ideally these would be generics in isolate. TypeScript's inference isn't strong enough yet for us to automatically provide the typings that would make isolate return a big component. However, we still keep these aliases here in case TypeScript's inference becomes better, then we know how to proceed to provide proper types.

            type Scopes

            type Scopes<So> = (Partial<ScopesPerChannel<So>> & WildcardScope) | string;

              type ScopesPerChannel

              type ScopesPerChannel<So> = {
              [K in keyof So]: any;
              };

                type Sources

                type Sources = {
                [name: string]: IsolateableSource;
                };

                  type WildcardScope

                  type WildcardScope = {
                  ['*']?: string;
                  };

                    Package Files (1)

                    Dependencies (2)

                    Dev Dependencies (11)

                    Peer Dependencies (0)

                    No peer dependencies.

                    Badge

                    To add a badge like this onejsDocs.io badgeto your package's README, use the codes available below.

                    You may also use Shields.io to create a custom badge linking to https://www.jsdocs.io/package/@cycle/isolate.

                    • Markdown
                      [![jsDocs.io](https://img.shields.io/badge/jsDocs.io-reference-blue)](https://www.jsdocs.io/package/@cycle/isolate)
                    • HTML
                      <a href="https://www.jsdocs.io/package/@cycle/isolate"><img src="https://img.shields.io/badge/jsDocs.io-reference-blue" alt="jsDocs.io"></a>