Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@twnd/ux / core / common / initialized.ts
Size: Mime:
/**
 * @license
 * FOURBURNER CONFIDENTIAL
 * Unpublished Copyright (C) 2021 FourBurner Technologies, Inc. All Rights Reserved.
 *
 * NOTICE: All information contained herein is, and remains the property of FOURBURNER TECHNOLOGIES,
 * INC. The intellectual and technical concepts contained herein are proprietary to FOURBURNER
 * TECHNOLOGIES, INC. and may be covered by U.S. and Foreign Patents, patents in process, and are
 * protected by trade secret or copyright law. Dissemination of this information or reproduction of
 * this material is strictly forbidden unless prior written permission is obtained from FOURBURNER
 * TECHNOLOGIES, INC. Access to the source code contained herein is hereby forbidden to anyone
 * except current FOURBURNER TECHNOLOGIES, INC. employees, managers or contractors who have executed
 * Confidentiality and Non-disclosure agreements explicitly covering such access.
 *
 * The copyright notice above does not evidence any actual or intended publication or disclosure of
 * this source code, which includes information that is confidential and/or proprietary, and is a
 * trade secret, of FOURBURNER TECHNOLOGIES, INC. ANY REPRODUCTION, MODIFICATION, DISTRIBUTION,
 * PUBLIC PERFORMANCE, OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT THE EXPRESS
 * WRITTEN CONSENT OF FOURBURNER TECHNOLOGIES, INC. IS STRICTLY PROHIBITED, AND IN VIOLATION OF
 * APPLICABLE LAWS AND INTERNATIONAL TREATIES. THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR
 * RELATED INFORMATION DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS
 * CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART.
 */

import {Observable, Subscriber} from 'rxjs';
import {ngDevMode} from '.';
import {Constructor} from './constructor';

/**
 * Mixin that adds an initialized property to a directive which, when subscribed to, will emit a
 * value once markInitialized has been called, which should be done during the ngOnInit function.
 * If the subscription is made after it has already been marked as initialized, then it will trigger
 * an emit immediately.
 * @docs-private
 */
export interface HasInitialized {
  /** Stream that emits once during the directive/component's ngOnInit. */
  initialized: Observable<void>;

  /**
   * Sets the state as initialized and must be called during ngOnInit to notify subscribers that
   * the directive has been initialized.
   * @docs-private
   */
  _markInitialized: () => void;
}

type HasInitializedCtor = Constructor<HasInitialized>;

/** Mixin to augment a directive with an initialized property that will emits when ngOnInit ends. */
export function mixinInitialized<T extends Constructor<{}>>(base: T): HasInitializedCtor&T
{
  return class extends base
  {
    /** Whether this directive has been marked as initialized. */
    _isInitialized = false;

    /**
     * List of subscribers that subscribed before the directive was initialized. Should be notified
     * during _markInitialized. Set to null after pending subscribers are notified, and should
     * not expect to be populated after.
     */
    _pendingSubscribers: Subscriber<void>[]|null = [];

    /**
     * Observable stream that emits when the directive initializes. If already initialized, the
     * subscriber is stored to be notified once _markInitialized is called.
     */
    initialized = new Observable<void>(subscriber => {
      // If initialized, immediately notify the subscriber. Otherwise store the subscriber to notify
      // when _markInitialized is called.
      if (this._isInitialized) {
        this._notifySubscriber(subscriber);
      } else {
        this._pendingSubscribers!.push(subscriber);
      }
    });

    constructor(...args: any[])
    {
      super(...args);
    }

    /**
     * Marks the state as initialized and notifies pending subscribers. Should be called at the end
     * of ngOnInit.
     * @docs-private
     */
    _markInitialized(): void
    {
      if (this._isInitialized && (typeof ngDevMode === 'undefined' || ngDevMode)) {
        throw Error(
          'This directive has already been marked as initialized and ' +
            'should not be called twice.',
        );
      }

      this._isInitialized = true;

      this._pendingSubscribers!.forEach(this._notifySubscriber);
      this._pendingSubscribers = null;
    }

    /** Emits and completes the subscriber stream (should only emit once). */
    _notifySubscriber(subscriber: Subscriber<void>): void
    {
      subscriber.next();
      subscriber.complete();
    }
  };
}