npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

apollo-angular-signal

v0.0.7

Published

A lightweight Angular library that converts Apollo GraphQL queries into Angular signals, enabling seamless integration between Apollo Client and Angular's signal-based reactive programming.

Readme

Apollo Angular Signal

A lightweight Angular library that converts Apollo GraphQL queries into Angular signals, enabling seamless integration between Apollo Client and Angular's signal-based reactive programming.

Installation

npm install apollo-angular-signal

What It Does

This library takes Apollo Angular ObservableQuery results and transforms them into Angular signals, providing a more idiomatic way to work with GraphQL data in modern Angular applications.

Usage

Basic Query

import { Component, inject } from '@angular/core';
import { Apollo, gql } from 'apollo-angular';
import { gqlQuery } from 'apollo-angular-signal';

const GET_USERS = gql`
  query GetUsers {
    users {
      id
      name
      email
    }
  }
`;

@Component({
  selector: 'app-users',
  template: `
    @if (users().loading) {
      <div>Loading...</div>
    }
    @if (users().hasError) {
      <div>Error: {{ users().error }}</div>
    }
    @if (users().data) {
      <ul>
        @for (user of users().data.users; track user.id) {
          <li>{{ user.name }} - {{ user.email }}</li>
        }
      </ul>
    }
  `
})
export class UsersComponent {
  private apollo = inject(Apollo);

  users = gqlQuery<{ users: Array<{ id: string; name: string; email: string }> }>(
    this.apollo.watchQuery({
      query: GET_USERS
    }).valueChanges
  );
}

Query with Variables

import { Component, inject, signal } from '@angular/core';
import { Apollo, gql } from 'apollo-angular';
import { gqlQuery } from 'apollo-angular-signal';

const GET_USER = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`;

@Component({
  selector: 'app-user-detail',
  template: `
    <input [(ngModel)]="userId" placeholder="Enter user ID">

    @if (user().loading) {
      <div>Loading...</div>
    }
    @if (user().data) {
      <div>
        <h2>{{ user().data.user.name }}</h2>
        <p>{{ user().data.user.email }}</p>
      </div>
    }
  `
})
export class UserDetailComponent {
  private apollo = inject(Apollo);

  userId = signal('1');

  // Reactive query that re-executes when userId changes
  user = gqlQuery<{ user: { id: string; name: string; email: string } }>(() => {
    const id = this.userId();
    if (!id) return null;

    return this.apollo.watchQuery({
      query: GET_USER,
      variables: { id }
    }).valueChanges;
  });
}

Subscriptions

import { Component, inject } from '@angular/core';
import { Apollo, gql } from 'apollo-angular';
import { gqlQuery } from 'apollo-angular-signal';

const MESSAGE_SUBSCRIPTION = gql`
  subscription OnMessageAdded {
    messageAdded {
      id
      text
      author
    }
  }
`;

@Component({
  selector: 'app-messages',
  template: `
    @if (messages().data) {
      <div>
        <p><strong>{{ messages().data.messageAdded.author }}:</strong></p>
        <p>{{ messages().data.messageAdded.text }}</p>
      </div>
    }
  `
})
export class MessagesComponent {
  private apollo = inject(Apollo);

  messages = gqlQuery<{ messageAdded: { id: string; text: string; author: string } }>(
    this.apollo.subscribe({
      query: MESSAGE_SUBSCRIPTION
    })
  );
}

Using the GqlSignalStatus Component

The GqlSignalStatus component simplifies handling loading and error states with a declarative approach:

import { Component, inject } from '@angular/core';
import { Apollo, gql } from 'apollo-angular';
import { gqlQuery, GqlSignalStatus } from 'apollo-angular-signal';

const GET_USERS = gql`
  query GetUsers {
    users {
      id
      name
      email
    }
  }
`;

@Component({
  selector: 'app-users',
  imports: [GqlSignalStatus],
  template: `
    <gql-signal-status [gql]="users()">
      <div gqlLoading>Loading users...</div>
      <div gqlError>Failed to load users</div>

      <ul>
        @for (user of users().data?.users; track user.id) {
          <li>{{ user.name }} - {{ user.email }}</li>
        }
      </ul>
    </gql-signal-status>
  `
})
export class UsersComponent {
  private apollo = inject(Apollo);

  users = gqlQuery<{ users: Array<{ id: string; name: string; email: string }> }>(
    this.apollo.watchQuery({
      query: GET_USERS
    }).valueChanges
  );
}

Features:

  • Automatically shows loading state while query is in progress
  • Displays error state if query fails
  • Renders main content when data is available
  • Supports custom loading and error templates via gqlLoading and gqlError attributes
  • Falls back to global defaults if no custom templates provided

Global Configuration

You can configure default loading and error templates globally:

import { ApplicationConfig } from '@angular/core';
import { provideGqlSignalConfig } from 'apollo-angular-signal';

// With string templates
export const appConfig: ApplicationConfig = {
  providers: [
    provideGqlSignalConfig({
      loadingDefaultTemplate: 'Loading...',
      errorDefaultTemplate: 'An error occurred'
    })
  ]
};

// Or with component templates
import { LoadingSpinnerComponent } from './loading-spinner.component';
import { ErrorMessageComponent } from './error-message.component';

export const appConfig: ApplicationConfig = {
  providers: [
    provideGqlSignalConfig({
      loadingDefaultTemplate: LoadingSpinnerComponent,
      errorDefaultTemplate: ErrorMessageComponent
    })
  ]
};

API

gqlQuery<T>(query)

Converts an Apollo query/subscription observable into an Angular signal.

Parameters:

  • query: Either an Observable<QueryResult<T>> or a function returning one (for reactive queries)

Returns: A Signal<GqlSignalResult<T>> where GqlSignalResult contains:

  • data?: T - The query result data
  • loading: boolean - Loading state
  • hasError: boolean - Whether an error occurred
  • error?: unknown - Error object if present

Two modes:

  1. Static mode: Pass observable directly
gqlQuery(apollo.watchQuery({ query: GET_DATA }).valueChanges)
  1. Reactive mode: Pass a function for reactive re-execution
gqlQuery(() => {
  const id = someSignal();
  return apollo.watchQuery({ query: GET_DATA, variables: { id } }).valueChanges;
})

License

MIT