export function repoStart()

in packages/database/src/core/Repo.ts [208:328]


export function repoStart(
  repo: Repo,
  appId: string,
  authOverride?: object
): void {
  repo.stats_ = statsManagerGetCollection(repo.repoInfo_);

  if (repo.forceRestClient_ || beingCrawled()) {
    repo.server_ = new ReadonlyRestClient(
      repo.repoInfo_,
      (
        pathString: string,
        data: unknown,
        isMerge: boolean,
        tag: number | null
      ) => {
        repoOnDataUpdate(repo, pathString, data, isMerge, tag);
      },
      repo.authTokenProvider_,
      repo.appCheckProvider_
    );

    // Minor hack: Fire onConnect immediately, since there's no actual connection.
    setTimeout(() => repoOnConnectStatus(repo, /* connectStatus= */ true), 0);
  } else {
    // Validate authOverride
    if (typeof authOverride !== 'undefined' && authOverride !== null) {
      if (typeof authOverride !== 'object') {
        throw new Error(
          'Only objects are supported for option databaseAuthVariableOverride'
        );
      }
      try {
        stringify(authOverride);
      } catch (e) {
        throw new Error('Invalid authOverride provided: ' + e);
      }
    }

    repo.persistentConnection_ = new PersistentConnection(
      repo.repoInfo_,
      appId,
      (
        pathString: string,
        data: unknown,
        isMerge: boolean,
        tag: number | null
      ) => {
        repoOnDataUpdate(repo, pathString, data, isMerge, tag);
      },
      (connectStatus: boolean) => {
        repoOnConnectStatus(repo, connectStatus);
      },
      (updates: object) => {
        repoOnServerInfoUpdate(repo, updates);
      },
      repo.authTokenProvider_,
      repo.appCheckProvider_,
      authOverride
    );

    repo.server_ = repo.persistentConnection_;
  }

  repo.authTokenProvider_.addTokenChangeListener(token => {
    repo.server_.refreshAuthToken(token);
  });

  repo.appCheckProvider_.addTokenChangeListener(result => {
    repo.server_.refreshAppCheckToken(result.token);
  });

  // In the case of multiple Repos for the same repoInfo (i.e. there are multiple Firebase.Contexts being used),
  // we only want to create one StatsReporter.  As such, we'll report stats over the first Repo created.
  repo.statsReporter_ = statsManagerGetOrCreateReporter(
    repo.repoInfo_,
    () => new StatsReporter(repo.stats_, repo.server_)
  );

  // Used for .info.
  repo.infoData_ = new SnapshotHolder();
  repo.infoSyncTree_ = new SyncTree({
    startListening: (query, tag, currentHashFn, onComplete) => {
      let infoEvents: Event[] = [];
      const node = repo.infoData_.getNode(query._path);
      // This is possibly a hack, but we have different semantics for .info endpoints. We don't raise null events
      // on initial data...
      if (!node.isEmpty()) {
        infoEvents = syncTreeApplyServerOverwrite(
          repo.infoSyncTree_,
          query._path,
          node
        );
        setTimeout(() => {
          onComplete('ok');
        }, 0);
      }
      return infoEvents;
    },
    stopListening: () => {}
  });
  repoUpdateInfo(repo, 'connected', false);

  repo.serverSyncTree_ = new SyncTree({
    startListening: (query, tag, currentHashFn, onComplete) => {
      repo.server_.listen(query, currentHashFn, tag, (status, data) => {
        const events = onComplete(status, data);
        eventQueueRaiseEventsForChangedPath(
          repo.eventQueue_,
          query._path,
          events
        );
      });
      // No synchronous events for network-backed sync trees
      return [];
    },
    stopListening: (query, tag) => {
      repo.server_.unlisten(query, tag);
    }
  });
}