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

@yuku123/render

v1.0.1

Published

平台共享前端渲染引擎: schema → antd/echarts 渲染 + 12 栏栅格布局编辑 + 字段类型注册表 (z-report / z-lc 共用)

Readme

@yuku123/render

平台共享的前端渲染引擎:把后端产出的 schema 变成能看的界面。z-report(报表看板)与 z-lc(低代码) 共用同一套分发、布局与图表适配,两边不再各写一份 ECharts/antd 拼装代码。

设计前提只有一条:后端是唯一事实源。视图形状由 Java 侧的 z-report-common schema 决定, 本包只做 option → 组件 的分发与视觉补全,不做业务校验,也不含任何报表/低代码的业务语义。

包结构

| 目录 | 职责 | | --- | --- | | src/contract/ | Java 契约的 TS 镜像。view.ts 对 z-report(ViewSchema / WidgetSpec / DatasetSchema / WidgetOption …),field.ts 对 z-lc(FieldDefDTO / EntityDefDTO / FieldTypeDescriptor / 算子词表)。只声明形状,不校验;改 Java 必须同步改这里,否则分发会静默落到兜底分支 | | src/renderer/ | UniversalRenderer:按 _widgetType 分发 + 12 栏栅格摆放;WidgetShell 是部件共用外框 | | src/renderer/widgets/ | 内置部件:ChartWidget(LINE/BAR/PIE)、KpiWidget、TableWidget、RawWidget(任意结构) | | src/charts/ | ECharts 适配:buildChartOption 补全裸 xAxis/缺省 yAxis,并剥掉 _ 前缀的渲染器元信息;useChart 管实例生命周期 | | src/layout/ | 12 栏栅格算术(GRID_COLUMNS / ROW_H / cellStyle / totalRows),与 z-report 后端的布局单位一致 | | src/fields/ | 字段类型注册表(Baserow 式):一个类型条目 owning 单元格渲染/内联编辑/表单/筛选/导出/ coerc 六件事,视图侧不允许 switch(fieldType) | | playground/ | 独立调试台,不依赖任何后端 |

两个入口

包里有两半,服务两个消费方,不共用一个 barrel(两边的 FieldType 本来就是两个不相干的域):

| 入口 | 给谁 | 需要的 peer | | --- | --- | --- | | @yuku123/render | z-report:schema → 看板/图表渲染 | react react-dom antd echarts(布局编辑另需 @dnd-kit/*)| | @yuku123/render/fields | z-lc:字段注册表 + 运行时值转换 | react react-dom antd dayjs @ant-design/icons |

npm i @yuku123/render            # 报表侧
npm i @yuku123/render dayjs @ant-design/icons   # 低代码侧(用到 ./fields)

用法

import UniversalRenderer from '@yuku123/render'

// renderData 就是 GET /api/render/view/{id} 的响应
<UniversalRenderer renderData={renderData} />

新图表类型不需要改渲染引擎,注册即可(也可以覆盖内置的):

<UniversalRenderer
  renderData={renderData}
  widgetRenderers={{ SCATTER: MyScatter, RAW: MyDrillDownTree }}
/>

分发规则:_widgetType 缺失按 TABLE 处理;未注册的类型落到 ChartWidget(后端先加了类型、 引擎还没跟上时按 echarts 图表渲染,而不是白屏)。

字段注册表(@yuku123/render/fields)

视图侧只跟解析结果打交道,类型分支全在注册表里:

import {
  createWorkspaceContext,
  resolveEntityFields,
  readFieldValue,
} from '@yuku123/render/fields'

const ws = createWorkspaceContext({
  appCode, tenantCode,
  entities, dicts, views, fieldTypes,   // 来自后端的 meta bundle
  services: {
    // 引擎不持传输层:REF 选择器的候选由消费方注入(z-lc 接的是 api/runtime.listRecords)
    loadReference: ({ entityCode, appCode, tenantCode, labelField, keyword, page, size }) =>
      listRecords(entityCode, { appCode, tenantCode }, {
        page, size,
        conditions: keyword && labelField ? [{ fieldCode: labelField, operator: 'like', value: keyword }] : [],
      }).then((p) => p.records ?? []),
  },
})

for (const rf of resolveEntityFields(entity, ws)) {
  const { value, displayValue } = readFieldValue(row, rf)
  rf.def.renderCell({ ctx: rf.ctx, row, value, displayValue })   // 单元格
  rf.def.toFieldValue(formValue, rf.ctx)                          // 写回前按 Java 侧 coerce 口径整形
  rf.operators                                                    // 该列能用的筛选算子
}

toFieldValue 这一层是必须的:后端 FieldTypeRegistry.coerceValue 很硬(Long.parseLong("") 直接抛、Boolean.parseBoolean 把 anything-but-"true" 判成 false、日期只认 yyyy-MM-dd[ HH:mm:ss] 不认 ISO/epoch),所以线格式在这里收口,不在视图里散着写。

自定义/覆盖类型走 registerFieldDefinition。

RAW:任意结构也是一种产出

RAW 部件没有约定形状。它承载的是后端对象整形语言(z-util/z-util-expr/z-util-expr-obj)的产出, 整条链路是:

库里拿原始数据  →  内存 SQL 粗糙产出二维表  →  对象 DSL 把二维抬成高维结构  →  RAW 渲染

整形程序本身就是一段 JSON(步骤数组),写在 widget 的 shape 字段上,例如把订单按区域分组、 组内挂明细、再按城市键索引:

[
  {"op": "group", "by": "region", "items": "lines",
   "agg": {"total": "SUM(amount)"},
   "into": {"region": "${region}", "total": "${total}",
            "lines": {"op": "map", "of": "lines",
                      "into": {"city": "${city}", "amount": "${amount}"}}}},
  {"op": "keyBy", "key": "region"}
]

后端 RawOptionBuilder 原样透传产出({type:"raw", value: <任意结构>}),内置 RawWidget 只负责"看得见"——展开成结构树(上限 MAX_TREE_NODES,超出截断并说明)。真正按业务形态渲染 (下钻表、思维导图、表单)由使用方注册部件覆盖 RAW,契约上只有 option.value 这一件事。

开发

npm install
npm run dev        # playground, http://localhost:5399
npm run typecheck  # tsc --noEmit (strict + noUnusedLocals + noUncheckedIndexedAccess)
npm run test       # vitest (jsdom; echarts 被桩掉, 断言喂给它的 option)
npm run build      # ES 产物 + .d.ts, peer 全部外部化

react / react-dom / antd / echarts / dayjs / @ant-design/icons / @dnd-kit/* 都是 peer: react >= 18、antd >= 5.29 || ^6,其余标了 optional(只有用到对应那半边时才需要装)。

写 antd 属性时必须两端通吃:5.29.3 是 antd 5 的最后一版,Statistic.styles / Tag.variant 这类新 API 只在 6 上有,valueStyle / bordered 只在 5 上不弃用 —— 用哪一头都会在另一头静默失效 (生产构建不打弃用告警,坏掉的样式不会报错)。包内一律走两端都认的写法 (字号用 Statistic.valueRender,无边框用 style.borderColor), src/test/deprecation.test.tsx 会把内置部件与内置字段定义全渲染一遍并断言控制台没有 deprecated。 z-render 的 devDeps 装的是 antd 6,所以 5.29 那一头由 z-lc 自己的用例与页面守住。

发布

@yuku123/render 发到 npmjs(组织唯一的 npm 发布口径,和 @yuku123/z-*-frontend-component 同一命名空间):

npm login --registry=https://registry.npmjs.org/   # 需要 @yuku123 的发布权限
npm version patch                                   # 生产版本,不用 --tag next
npm publish                                          # publishConfig 已固定走 npmjs

~/.npmrc 默认 registry 是 npmmirror(只读镜像),发包必须靠 publishConfig.registry 这一行; prepublishOnly 会先跑测试再重建 dist,避免把旧产物发出去。发布凭证(@yuku123 scope 的 Granular Token) 按组织惯例记在 z-biz-tool-lead/004_重要秘钥/npm-token.md,口径索引见 z-opc-foundation-lead/004_重要秘钥/npm-token.md。

发完还要手动推镜像,否则本机 npm install 装不到(默认源是镜像不是 npmjs):

curl -X PUT https://registry.npmmirror.com/@yuku123%2Frender/sync
npm view @yuku123/render version --registry=https://registry.npmjs.org/    # 冒烟:npmjs 可见
npm view @yuku123/render version --registry=https://registry.npmmirror.com # 冒烟:镜像已同步

已发版本:1.0.0(2026-09-24)。z-report / z-lc 均以 registry 依赖 ^1.0.0,不再用 file: 或 workspace 直连。

边界与待办

  • 不含校验:入参合法性由后端产出时保证(契约镜像文件里也不写校验)。
  • 不引 echarts 的类型包:ChartOption 是宽松形状,避免可选 peer 变成类型上的硬依赖。
  • 待办:LayoutEditor(dnd-kit 拖动配置,需同时兼容 z-report 的 12 栏 {x,y,w,h} 与 z-lc 的两栏 {viewId,width})。