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

@idhub/identity-adapter-angular

v0.1.0

Published

Angular adapter for @idhub/identity-core: IdentityModule.forRoot(), an RxJS-backed IdentityService, an APP_INITIALIZER that establishes the anonymous id before the first route renders, an optional HttpInterceptor, and a companion Express middleware for An

Readme

@idhub/identity-adapter-angular

Angular adapter for @idhub/identity-core. Zero vendor knowledge — it only knows the IdentityProvider / IdentityClient contract from the core package.

import { IdentityModule } from '@idhub/identity-adapter-angular'

@NgModule({
  imports: [
    IdentityModule.forRoot({
      providers: [segmentProvider, launchDarklyProvider, fullStoryProvider],
      cookie: { name: '_anon_id', domain: '.example.com' },
      enableHttpInterceptor: true,
    }),
  ],
})
export class AppModule {}
@Component({ /* ... */ })
export class HeaderComponent {
  readonly state$ = this.identity.state$   // Observable<IdentityState>
  constructor(@Inject(IdentityService) private identity: IdentityService) {}

  onLogin(userId: string) { this.identity.identify(userId, { plan: 'pro' }) }
  onLogout()              { this.identity.reset() }
}

What it gives you

| Export | Purpose | |---|---| | IdentityModule.forRoot(config) | Registers IdentityService, the APP_INITIALIZER, and (opt-in) the interceptor. | | IdentityService | state$: Observable<IdentityState>, snapshot, identify(), reset(), track(), page(). | | IdentityHttpInterceptor | Adds X-Identity-Id to every HttpClient request. Registered only via enableHttpInterceptor: true. | | identityExpressMiddleware() (/server) | Companion SSR middleware for Angular Universal. | | IDENTITY_CONFIG, IDENTITY_ID_HEADER | DI token / header name, for tests and advanced wiring. |

The APP_INITIALIZER guarantee

Angular blocks bootstrap — and therefore the first route render — until every APP_INITIALIZER settles. IdentityService is in the initializer's deps, so Angular must construct it first, and construction runs identity-core's createIdentityClient(), which resolves the canonical anonymous id and fans onAnonymous out to every provider synchronously. This is Angular's equivalent of the Next.js adapter's middleware guarantee, adapted to the bootstrap lifecycle because Angular has no request-time middleware of its own.

The e2e suite asserts this as an ordering property, not a state check: the test-double provider records every hook onto a window-global log, and e2e/identity.spec.ts asserts the log reads exactly bootstrap_start → onAnonymous → app_initializer_done → component_init.

Known limitation. identity-core does not surface the promises returned by async onAnonymous implementations, so the initializer guarantees every provider has been called before first render — not that a provider's own network round-trip finished. Providers needing that should contribute a second APP_INITIALIZER.

SSR / Angular Universal

import { identityExpressMiddleware } from '@idhub/identity-adapter-angular/server'

server.use(identityExpressMiddleware({ cookie: { name: '_anon_id' } }))
// downstream: req.anonymousId is set, Set-Cookie is appended

Separate entry point on purpose — browser bundles never pull it in.

It uses identity-core's cookie primitives (parseCookieHeader, serializeAnonymousIdCookie, resolveCookieConfig) rather than the Web Standard getOrCreateAnonymousIdFromRequest, because Express exposes a Node IncomingMessage, not a Request. Wrapping every request in a synthetic Request would allocate on every hit and still need unwrapping to append Set-Cookie. Cookie naming, defaults and serialization still come from identity-core — only the transport differs, so there is no duplicated cookie logic. Express's real Request/Response satisfy the structural IdentityRequestLike / IdentityResponseLike shapes, so no @types/express dependency is needed. Set-Cookie is appended, never replaced, so it composes with session cookies.

Build strategy (tsup, not ng-packagr)

Angular libraries are normally built with ng-packagr. This package uses tsup, matching the repo-wide convention, which is viable because it ships an injectable service, a providers-only NgModule and an interceptor — no component templates to compile.

Two constraints follow, and both are handled:

  1. No emitDecoratorMetadata. esbuild cannot emit design:paramtypes. Every injection site is therefore explicit — @Inject(...) parameter decorators plus useFactory + deps in forRoot() — so nothing relies on reflected metadata.
  2. useDefineForClassFields: false, required for legacy decorator semantics at the ES2022 target.

AOT caveat. tsup emits plain __decorateClass calls rather than ng-packagr's partial-Ivy output, so the decorated classes are compiled by Angular's JIT compiler. That is what the test app exercises. An app doing a strict AOT build against these classes would want an ng-packagr (partial-compilation) artifact instead. If a consumer hits that, the fallback is a ng-packagr build step for this package only — the source does not need to change.

Angular version support

Developed and tested against Angular 20.3.30 (JIT bootstrap via platformBrowserDynamic). Peer range is >=18 <23. APP_INITIALIZER is deprecated from v19 onward in favour of provideAppInitializer but still present through v22; it is used here because it is the documented multi-provider contract for this package.

Local development

pnpm --filter @idhub/identity-adapter-angular build         # tsup, dual ESM+CJS
pnpm --filter @idhub/identity-adapter-angular test          # vitest unit tests
pnpm --filter @idhub/identity-adapter-angular test:e2e      # playwright against test-app/

test-app/ is a throwaway Angular app (one module, one component, a recording test-double provider) bundled by a 20-line esbuild script and served by a 30-line static server — deliberately not an Angular CLI workspace, which would add a second build system to the repo for two files.