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

@aawwaaa/astralcore-syncer

v1.0.2

Published

A lightweight library to connect objects together

Readme

Astralcore-Syncer

不到 50 行业务代码,实现一个实时协同编辑器。

astralcore-syncer 是一个极轻量、可嵌入的分布式对象同步内核。
它把 WebSocket、序列化、RPC、广播、资源生命周期管理全部封装成透明抽象,让你像操作本地对象一样构建实时协同应用。

npm version License: MIT TypeScript


快速开始:实时协同编辑器(完整代码)

效果展示

效果展示

代码示例

// shared.js
import { Resource } from "@aawwaaa/astralcore-syncer";

export class SharedDoc extends Resource {
  async resCreate(text) { this.content = text }
  resSave(client) { return { content: this.content } }
  async resLoad({ content }) { this.content = content }
  async modify(text) { this.content = text; this.resSync() }
}

export const SharedDocDef = Resource.define(SharedDoc, "shared-doc").invoke("modify");
// server.js
import { ResourceEnvironment, resourceEnvironmentSetImpl } from "@aawwaaa/astralcore-syncer";
import { ServerMemoryResourceManager } from "@aawwaaa/astralcore-syncer/impl/server/resource-memory";
import { ServerWebsocketRemoteManager } from "@aawwaaa/astralcore-syncer/impl/server/remote-websocket";
import express from "express";
import expressWs from "express-ws";
import { SharedDocDef } from "./shared";

const remote = new ServerWebsocketRemoteManager();
const impl = new ResourceEnvironment(remote, new ServerMemoryResourceManager());
resourceEnvironmentSetImpl(() => impl);

// 创建默认文档,生命周期到服务器停止
const doc = await SharedDocDef.loadOrCreate("main", "Hello, world!");
doc.event.updater("sync", () => console.log("Doc updated:", doc.content));

// 挂载 WebSocket
const { app } = expressWs(express());
app.ws("/ws", (ws) => remote.handleWebSocket(ws));
app.listen(8000, () => console.log("Server on :8000"));
// client.js
import { ResourceEnvironment, resourceEnvironmentSetImpl } from "@aawwaaa/astralcore-syncer";
import { ClientWebsocketRemoteManager } from "@aawwaaa/astralcore-syncer/impl/client/remote-websocket";
import { ClientRemoteResourceManager } from "@aawwaaa/astralcore-syncer/impl/client/resource-remote";
import { SharedDocDef } from "./shared";

const remote = new ClientWebsocketRemoteManager("/ws").init();
const impl = new ResourceEnvironment(remote, new ClientRemoteResourceManager(remote));
resourceEnvironmentSetImpl(() => impl);

using doc = await SharedDocDef.resolve("main");
const textarea = document.getElementById("edit");
textarea.addEventListener("input", () => doc.modify(textarea.value));
doc.event.updater("sync", () => (textarea.value = doc.content));
// HTML: <textarea id="edit" style="width:100%;height:200px;"></textarea>

就这样。 多开几个浏览器窗口试试——你的编辑器已经支持多端实时同步了。


📦 安装

npm install @aawwaaa/astralcore-syncer

核心概念

Resource(资源)

任何需要跨端同步的对象都可以定义为 Resource。你只需实现三个生命周期方法:

| 方法 | 何时调用 | 用途 | |------|----------|------| | resCreate(...args) | 服务器首次创建 | 设置初始状态 | | resSave(client) | 保存/广播时调用 | 返回序列化数据(client=true 给客户端,可裁剪) | | resLoad(data) | 加载或收到同步时调用 | 用数据恢复状态 |

Resource 中包含一个 EventBus 实例 event, 可用于本地或RPC事件。

| 内置事件 | 时机 | | sync | 资源被修改并广播后触发 | | remove | 资源被删除时触发 |

  • event 支持 on, updater(初始执行一次并订阅变化, 只支持无参), off, emit 方法。

invoke & emit

  • invoke("method"):把方法标记为远程可调用。客户端调用时自动 RPC 到服务器,服务器执行后结果广播给所有客户端。
  • emit("event"):把自定义事件标记为可广播,任意端调用 this.event.emit("event", ...) 即可全端同步。

环境 (ResourceEnvironment)

一个单例,组合了 RemoteManager(通信)和 ResourceManager(持久化)。通过 resourceEnvironmentSetImpl 初始化,服务端和客户端分别注入自己的实现。

引用计数

  • 如果你只需要全局单例,你可以忽视引用计数系统。 资源会被多个客户端和 RPC 参数持有。框架使用显式引用计数保证安全回收:
using doc = await SharedDocDef.resolve("main"); // 用 using 自动释放
// 或手动 doc.refRemove()

忘记释放会导致内存泄漏。

  • using 需要 typescript 5.2+ 且 target 为 esnext,也可用 try/finally + doc.refRemove() 替代。

扩展点(按需组合)

框架只在核心同步上锁定,以下部分全部可替换:

| 扩展点 | 接口 | 示例 | |--------|------|------| | 传输层 | RemoteManager | WebRTC、gRPC、Web Worker | | 持久化 | ResourceManager | 替换内存为 MongoDB、PostgreSQL、S3 | | 自定义序列化 | SpecialObjectDefinition | 传输 Date、Buffer、三维向量等特殊对象 | | 鉴权 | callerExt + getCaller() | 在连接时传入用户信息,方法内获取调用者身份 | | 冲突策略 | 在 modify 等方法内实现 | 最后写入胜出、CAS 版本检查、CRDT 算法均可组合 | | 离线支持 | 包装客户端 RPC 层 | 实现本地操作队列与重放 |

这让 astralcore-syncer 成为一个内核,而非全功能平台。你可以自由嫁接任何生态工具(Yjs、JSON Patch、OT 库等)。


与同类方案对比

| 特性 | astralcore-syncer | Meteor | Firebase | ShareDB | Yjs | |------|-------------------|--------|----------|---------|-----| | 抽象层级 | 对象方法 + 事件 | Publication/Sub | 查询订阅 | OT 文档 | CRDT 结构 | | 学习曲线 | 低(懂类即可) | 高(全栈平台) | 中(平台规则) | 高(OT 概念) | 中(CRDT 思维) | | 自托管 | ✅ 纯 Node.js | ✅ (重) | ❌ 有限 | ✅ | ✅ | | 冲突解决 | 留给开发者 | 乐观锁 | 安全规则 | 强制 OT | 强制 CRDT | | 适用场景 | 小型通用协同 | 大型实时应用 | 移动/网页应用 | 文档协作 | 离线优先文档 |


FAQ


示例项目


贡献

欢迎提交 PR!请先打开 Issue 讨论你的想法,或直接提交 Draft PR。


许可证

MIT © aawwaaa