switchMap(() => {
   const proxyLogger = new Subject();
   const frameMain = createMainFramer(document, getState, proxyLogger);
   const buildAndFrameMain = actions.pipe(
     ofType(
       types.updateFile,
       types.executeChallenge,
       types.challengeMounted
     ),
     debounceTime(executeDebounceTimeout),
     switchMap(() =>
       buildFromFiles(getState(), true).pipe(
         map(frameMain),
         ignoreElements(),
         catchError(err => of(disableJSOnError(err)))
       )
     )
   );
   return merge(buildAndFrameMain, proxyLogger.map(updateConsole));
 })
Example #2
0
function registerConsoleExecutor(
  watchExpressionStore: WatchExpressionStore,
  registerExecutor: RegisterExecutorFunction,
): IDisposable {
  const disposables = new UniversalDisposable();
  const rawOutput: Subject<?EvaluationResult> = new Subject();
  const send = expression => {
    disposables.add(
      // We filter here because the first value in the BehaviorSubject is null no matter what, and
      // we want the console to unsubscribe the stream after the first non-null value.
      watchExpressionStore
        .evaluateConsoleExpression(expression)
        .filter(result => result != null)
        .first()
        .subscribe(result => rawOutput.next(result)),
    );
    watchExpressionStore._triggerReevaluation();
  };
  const output: Observable<{
    result?: EvaluationResult,
  }> = rawOutput.map(result => {
    invariant(result != null);
    return {data: result};
  });
  disposables.add(
    registerExecutor({
      id: 'debugger',
      name: 'Debugger',
      send,
      output,
      getProperties: watchExpressionStore.getProperties.bind(
        watchExpressionStore,
      ),
    }),
  );
  return disposables;
}
Example #3
0
  console.debug("Pinging reaper server..");
  return Rx.Observable.fromPromise($.ajax({
    url: `${URL_PREFIX}/ping`
  }).promise());
});

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Login
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

export const loginSubject = new Rx.Subject();

export const loginResult = loginSubject.map(login => {
  console.info("Logging in with username: " + login.username);
  return Rx.Observable.fromPromise($.ajax({
    url: `${URL_PREFIX}/login`,
    method: 'POST',
    data: { username: login.username, password: login.password}
  }).promise());
}).share();

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Logout
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

export const logoutSubject = new Rx.Subject();

export const logoutResult = logoutSubject.map(logout => {
  console.info("Logging out");
  return Rx.Observable.fromPromise($.ajax({
    url: `${URL_PREFIX}/logout`,
    method: 'POST'
});


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// cluster
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


export const addClusterSubject = new Rx.Subject();
export const deleteClusterSubject = new Rx.Subject();


export const addClusterResult = addClusterSubject.map(seed => {
  console.info("Adding new cluster with seed node: " + seed);
  return Rx.Observable.fromPromise($.ajax({
    url: `${URL_PREFIX}/cluster?seedHost=${encodeURIComponent(seed)}`,
    method: 'POST'
  }).promise());
}).share();

export const deleteClusterResult = deleteClusterSubject.map(name => {
  console.info("Deleting cluster with name: " + name);
  return Rx.Observable.fromPromise($.ajax({
    url: `${URL_PREFIX}/cluster/${encodeURIComponent(name)}`,
    method: 'DELETE'
  }).promise());
}).share();


export const clusterNames = Rx.Observable.merge(
    Rx.Observable.timer(0, POLLING_INTERVAL).map(t => Rx.Observable.just({})),
  _observeSuggestions(): Observable<?HyperclickSuggestion> {
    return this._fetchStream
      .map(mouseEvent => {
        if (mouseEvent == null) {
          return null;
        }
        return this._getMousePositionAsBufferPosition(mouseEvent);
      })
      .distinctUntilChanged((x, y) => {
        if (x == null || y == null) {
          return (x == null) === (y == null);
        }
        return x.compare(y) === 0;
      })
      .filter(position => {
        if (position == null) {
          return true;
        }

        // Don't fetch suggestions if the mouse is still in the same 'word', where
        // 'word' is defined by the wordRegExp at the current position.
        //
        // If the last suggestion had multiple ranges, we have no choice but to
        // fetch suggestions because the new word might be between those ranges.
        // This should be ok because it will reuse that last suggestion until the
        // mouse moves off of it.
        if (
          (this._lastSuggestionAtMouse == null ||
            !Array.isArray(this._lastSuggestionAtMouse.range)) &&
          this._isInLastWordRange(position)
        ) {
          return false;
        }

        // Don't refetch if we're already inside the previously emitted suggestion.
        if (this._isInLastSuggestion(position)) {
          return false;
        }

        return true;
      })
      .do(position => {
        if (position == null) {
          this._lastWordRange = null;
        } else {
          const match = wordAtPosition(this._textEditor, position);
          this._lastWordRange = match != null ? match.range : null;
        }
      })
      .switchMap(position => {
        if (position == null) {
          return Observable.of(null);
        }

        return Observable.using(
          () => this._showLoading(),
          () =>
            Observable.defer(() =>
              this._hyperclick.getSuggestion(this._textEditor, position),
            )
              .startWith(null) // Clear the previous suggestion immediately.
              .catch(e => {
                getLogger('hyperclick').error(
                  'Error getting Hyperclick suggestion:',
                  e,
                );
                return Observable.of(null);
              }),
        );
      })
      .distinctUntilChanged();
  }