Angular

@atolljs/angular — Signal adapter for zoneless Angular. Call in an injection context (field initializer or constructor) so subscriptions release on destroy. NgModule apps get the same pools through AtollModule — the NestJS binding's forRoot/registerPool vocabulary.

Install

frontend
npm install @atolljs/core @atolljs/angular

Usage

main.ts + app.component.tsfrontend
// main.ts — the connectWorker client registers as a DI provider,
// terminated on app teardown (it re-spawns lazily on the next call)
bootstrapApplication(AppComponent, {
  providers: [
    provideZonelessChangeDetection(),
    provideAtoll({ pools: [{ name: 'counter', client: counter }] }),
  ],
});

// app.component.ts
import { Component, effect } from '@angular/core';
import { injectAtollPool, sharedValue, taskState } from '@atolljs/angular';
import { counterMemory } from './counter.memory';
import { counter } from './counter';

@Component({
  selector: 'app-root',
  template: `<button (click)="increment.run(1)">
    count: {{ count() ?? '…' }}</button>`,
})
export class AppComponent {
  private readonly counter = injectAtollPool<typeof counter>('counter');
  count = sharedValue(counterMemory, 'count');
  increment = taskState(this.counter.increment);

  constructor() {
    effect(() => console.log('count →', this.count()));
  }
}

Binding API

ExportSignatureWhat it does
provideAtollprovideAtoll({ pools: AtollPoolDeclaration[] }, ...features)Register worker pools or connectWorker clients ({ name, client }) as environment providers — terminated on injector destroy; also usable at route level.
injectAtollPoolinjectAtollPool<T>(name): TInject a pool registered by provideAtoll inside an injection context; mockable via TestBed.
AtollModuleAtollModule.forRoot({pools?}) / forRootAsync / registerPool(decl) / registerPoolAsyncNgModule alternative to provideAtoll — same pool tokens + lifecycle, declared on the importing module; async forms resolve their factory before bootstrap.
InjectAtollPool@InjectAtollPool(name)Constructor-parameter decorator form of injectAtollPool for @Injectable() classes.
observableSignalobservableSignal(source: ObservableValue<T>): Signal<T>Subscribe to any observable snapshot.
sharedValuesharedValue(memory, key, select?, options?): Signal<T | undefined>Bind one shared-memory field to a Signal; optional selector + equality.
taskStatetaskState(task | asyncFn): { state: Signal<TaskSnapshot>, run, runOnce }Bind an AsyncTask — or any async fn — to a Signal and get its triggers.

Live demo

@atolljs/angularangular/ ↗

If the frame is blank, the examples aren't up — run npm run dev:all (dev servers) or npm run serve:all (built apps) from the repository root.

Notes

  • Works with OnPush + zoneless change detection out of the box.
  • Worker-hosted Angular trees (islands) live in the companion package @atolljs/angular-island — see the Islands page under this section.