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

@ricenote/plugin-search

v1.2.0

Published

RiceNote 搜索插件:可搜索数据源注册表与 /search 页面

Readme

rice.search —— 搜索

全站搜索:提供可搜索数据源注册契约 content.search@1 与 /search 页面, 跨内容类型聚合并做全局分页。

零外部依赖:不引入 Meilisearch / Elasticsearch,字符级检索由各数据源自行实现 (posts 使用 MySQL FULLTEXT with ngram parser,短词回退 LIKE)。

清单摘要

| 项 | 值 | | --- | --- | | id | rice.search | | version | 1.0.0 | | apiVersion | ^1.0.0 | | entry | ./dist/index.js | | provides | content.search@1 | | requires | 无 | | capabilities | services:provide、routes:public、events:subscribe | | migrations | 无 | | 数据表 | 无(本插件不持有任何表,也不查询其他插件的表) |

扩展点(Hook)

公开页面路由

| name | path | kind | cacheable | | --- | --- | --- | --- | | search | /search | search | false(结果随关键词变化,不做 HTML 缓存) |

模板变量:keyword、results(聚合结果)、sources(参与检索的数据源)、pagination。

服务契约(提供)

content.search@1:

registerSource(source): () => void             // 数据源拥有者主动注册,返回注销句柄
unregisterSource(id): void                     // 幂等;插件 stop 阶段必须调用
listSources(): { id, label }[]
search({ keyword, page, pageSize })            // 跨数据源检索,按数据源聚合后全局分页
hasSources(): boolean

SearchSource 约定:

{
  id: string;      // 例如 'posts'
  label: string;   // 结果分组展示名,例如 '文章'
  query({ keyword, page, pageSize }): Promise<{ items: SearchHit[]; total: number }>
}
  • 分页由实现方负责;实现方不得返回未对公众可见的内容;
  • 单个数据源抛错只降级它自己的结果(错误隔离),不影响其他来源。

服务契约(消费)

无。这是刻意的:搜索插件不依赖任何内容插件,而是由内容插件"推"数据源进来。

事件

订阅 core.runtime.started.v1:在全部插件就绪后统计已注册数据源并告警 (若一个都没有,/search 会返回空结果)。

后台菜单 / 插槽 / 管理 API

无。

设置项(settingsSchema,后台自动生成表单)

后台「扩展中心 → 搜索 → 设置」。保存后需重启服务生效(ctx.config 是插件启动期快照)。

分组「搜索行为」

| 字段 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | resultPageSize | number(1–50) | 10 | 每页结果数 | | maxKeywordLength | number(1–500) | 100 | 关键词长度上限(超长直接拒绝) | | maxItemsPerSource | number(1–500) | 50 | 单个数据源最多返回的条数(防止某一个来源淹没结果) |

谁在向它注册

| 数据源 id | 拥有者 | 检索实现 | | --- | --- | --- | | posts | rice.posts | MySQL FULLTEXT(ngram)+ 短词 LIKE 回退,见 ADR-009 |

其他内容插件(如 rice.pages)如需被检索,只需在 core.runtime.started.v1 阶段调用 registerSource,并在 stop() 中调用 unregisterSource —— 两侧都不产生硬依赖。

依赖与启停

  • 可独立启停;禁用后 /search 路由消失,此时:
    • 主题里的 {{ url('search') }} 会降级为 #(Core 记录一次告警), 官方主题用 has_feature('search') 控制入口显隐;
    • 数据源拥有者通过 tryUse 得到 undefined,静默跳过注册。