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

@aiao/rxdb-angular

v0.0.25

Published

Angular 框架集成库,为 Angular 应用提供 RxDB 支持。基于 Angular Signals 实现响应式数据流。

Readme

@aiao/rxdb-angular

Angular 框架集成库,为 Angular 应用提供 RxDB 支持。基于 Angular Signals 实现响应式数据流。

功能特性

  • Angular Signals 集成: 查询结果以 Signal 暴露,天然融入 Angular 响应式渲染
  • 响应式查询 Hooks: useGet / useFind / useFindByCursor 等,覆盖基础/树/图仓库查询
  • 无限滚动: useInfiniteScroll 返回 signal 资源(与 React/Vue 同名同形),底层类 InfiniteScrollingList 亦可直接使用
  • 变更检测指令: RxDBEntityChangeDirective 在 OnPush 下实时反映实体编辑
  • 依赖注入: 通过 provideRxDB 完全接入 Angular 依赖注入系统
  • 类型安全: 完整的 TypeScript 类型支持

何时使用

  • 构建 Angular 应用并需要本地优先数据库
  • 需要响应式数据流与 Angular Signals 无缝集成
  • 需要离线优先的 Angular 应用

安装

npm install @aiao/rxdb @aiao/rxdb-angular
# 或
pnpm add @aiao/rxdb @aiao/rxdb-angular

使用

注册 RxDB

import { provideRxDB } from '@aiao/rxdb-angular';

export const appConfig: ApplicationConfig = {
  providers: [
    // 传入返回 RxDB 实例的工厂函数
    provideRxDB(() => rxdb)
  ]
};

查询数据

import { Component } from '@angular/core';
import { useGet, useFind } from '@aiao/rxdb-angular';

@Component({
  selector: 'app-todo',
  template: `
    @if (todo.isLoading()) {
      <span>Loading…</span>
    } @else {
      <span>{{ todo.value()?.title }}</span>
    }
  `
})
export class TodoComponent {
  readonly todo = useGet(Todo, 'todo-1');
  readonly todos = useFind(Todo, { where: { combinator: 'and', rules: [] } });
}

无限滚动

推荐入口 —— 与 React / Vue 侧的 useInfiniteScroll 同名同形,随注入上下文自动释放:

@Component({/* ... */})
export class TodoListComponent {
  // 必须在注入上下文中调用(构造器/字段初始化器)
  readonly todos = useInfiniteScroll(Todo, { limit: 50 });

  next() {
    this.todos.loadMore(); // isLoading 为真或 hasMore 为假时是 no-op
  }
}

模板里直接读 signal:

@for (todo of todos.value(); track todo.id) {
<li>{{ todo.title }}</li>
} @if (todos.isLoading()) { <spinner /> } @if (todos.isEmpty()) { <empty-state /> }

也可以直接用底层类:

@Component({/* ... */})
export class TodoListComponent {
  // 必须在注入上下文中构造:类内部经 inject(DestroyRef) 注册销毁钩子,
  // 并在构造器里建立 effect —— 在普通函数或 service 方法里裸 new 会抛 NG0203。
  readonly list = new InfiniteScrollingList(inject(RxDB), Todo, { limit: 50 });
}

list.loadMore(); // 加载下一页
list.refresh(); // 丢弃已加载页面,从头刷新(宿主销毁后是 no-op)

类没有公开的 destroy() —— 清理由 DestroyRef 接管,宿主销毁时自动退订全部页查询。 需要在注入上下文之外持有实例时,用 runInInjectionContext(injector, () => new InfiniteScrollingList(...)), 生命周期即绑定到该 injector。

破坏性变更(下一个 major)isLoading / error / hasMoreWritableSignal 收窄为只读 Signal。这三个字段是内部状态机的一部分 —— 外部把 isLoading 改成 false 能绕过 loadMore 的并发 guard 发出重复页请求, 把 hasMore 改成 true 能越过终页。状态现在只能经 loadMore / refresh 改变, 与 React 侧「返回纯值」的只读语义一致。若此前依赖 todos.isLoading.set(...) 之类的写法,请改为调用 loadMore() / refresh(),或在组件里自持一个 signal。

OnPush 下的实时变更检测

实体是原地可变的类实例,引用不变,OnPush 视图看不到它们的字段变化。rxdbChangeDetector 把实体的 patches$ 接上 markForCheck

<div [rxdbChangeDetector]="entity"></div>
<div [debounceTime]="200" [rxdbChangeDetector]="entity"></div>

debounceTimeauditTime 单位是毫秒,同时设置时串联生效(顺序 debounceTime → auditTime), 仅正有限值生效:0、负值、NaNInfinity 一律表示禁用,两者都禁用时 patch 同步透传。

异步操作

const save = useAction((todo: Todo) => repository.save(todo));

save.isPending(); // Signal<boolean>
save.execute(todo);

isPending并发计数而不是布尔开关:N 次调用同时在途时它一直为真,直到最后一个 settle; 计数在 finally 里回退,因此失败也会正确复位。有意不做去重与取消 —— 重复点击会真的执行多次,错误原样冒泡给调用方。

持久化状态

usePersistedState 与既有的柯里化 useState同一份状态,只是签名扁平:

const theme = usePersistedState('my-app', 'theme', 'dark');
theme.value.set('light'); // 落盘到 'my-app:theme'

// 等价写法
const same = useState('my-app')('theme').signal('dark'); // === theme.value

两者共用同一张 root 注册表、同一套键格式与失败语义。扁平签名的存在是为了三端对齐: React 的 hooks 规则不允许「从返回对象的方法里再调 hook」,柯里化形态在 React 侧无法复现。

  • 必须在 Angular 注入上下文中调用。
  • 后续调用传入的 initialValue 会被忽略,但仍参与类型标签校验 —— 同 key 换值类型直接抛错。
  • namespacename 在键里各自转义,不会互相串号;含 :% 的旧键在首次读取时一次性迁移。
  • 写盘失败不抛错,signal 值照常更新,失败经 persistError 暴露。
  • SSR 下不读也不写 localStorage;暂不监听 storage 事件,因此不跨标签页同步。

三端 API 对照

同功能同 API 是本仓库的硬约束,框架惯例允许容器形态与命名差异,不允许能力缺失:

| 能力 | Angular | Vue | React | | ------------ | ------------------------------------------------------ | ------------------------------------ | --------------------------------------- | | 查询 | useGet / useFind / … | 同名 | 同名 | | 无限滚动 | useInfiniteScroll | useInfiniteScroll | useInfiniteScroll | | 异步操作 | useActionSignal<boolean> | useActionComputedRef<boolean> | useAction → 渲染快照 | | 持久化状态 | usePersistedState / useStateWritableSignal<T> | usePersistedStateRef<T> | usePersistedState → 快照 + setValue | | 实体实时变更 | RxDBEntityChangeDirectivemarkForCheck) | useEntityChange | useEntityChange |

时间窗判定(withTimeWindows)放在 @aiao/utils 里由三端共用。Vue / React 的持久化内核是 @aiao/utilsPersistedStateRegistry,与 Angular 的 root 服务 StateRegistry 键格式一致但各自持有内存状态 —— 同一页面里混用两端框架时,盘上数据互通,内存值不互通。

完整示例

参考 dev-rxdb-angular 中的完整集成示例。