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 🙏

© 2025 – Pkg Stats / Ryan Hefner

protobuf-arkts-generator

v0.1.1

Published

HarmonyOS ArkTS Protobuf 代码生成器,纯 ArkTS 运行时与服务客户端

Readme

HarmonyOS ArkTS Protobuf 生成器

npm version npm downloads license node

为 HarmonyOS ArkTS 项目生成纯 ArkTS 的 Protobuf 代码(消息、枚举、服务存根),内置轻量运行时,不依赖第三方库,开箱即用。

  • 强类型:64 位整型可选 bigint|number
  • JSON 支持:可选生成 toJson/fromJson,内置 WKT(Timestamp/Duration/Any/Struct/Value/ListValue/FieldMask)映射
  • 服务客户端:生成 *Client,通过自定义 RpcTransport 进行 unary 调用
  • 路径与索引:自动分包、构建 index.ets 聚合导出

环境要求

  • Node.js 16+
  • HarmonyOS DevEco Studio(或 CLI)用于集成 ArkTS 代码

快速开始

  1. 克隆并安装依赖:
    npm install
  2. 将你的 .proto 文件放到一个输入目录,例如 ./protos(仓库已附带示例)。
  3. 运行生成:
    npx arkpb-gen --in ./protos --out ./packages --int64 bigint --docs on
  4. 生成结果在 ./packages 下:
    • packages/<pkg>/messages/*.etsenums/*.etsservices/*.ets
    • packages/<pkg>/index.ets(聚合导出)
    • 运行时被复制到 packages/protobuf-core/;示例导入:
import { Writer, Reader } from '../protobuf-core'

HarmonyOS 集成指南

将生成产物引入你的 HarmonyOS ArkTS 项目,有两种常见方式:

方式 A:直接拷贝源码

  1. 在应用模块(例如 entry)内创建目录:
    • entry/src/main/ets/protobuf-core/(复制 packages/protobuf-core/*
    • entry/src/main/ets/pb/(复制你生成的包目录,如 packages/user/packages/google/ 等)
  2. 在 ArkTS 代码中按相对路径导入并使用:
import { Writer, Reader } from '../protobuf-core'
import { UserLoginResponse } from '../pb'
const w = new Writer()
const buf = UserLoginResponse.encode(UserLoginResponse.create({
  sessionId: 'x', userPrivilege: 'y', isTokenType: false, formatTimestamp: 0n
}), w).finish()
const decoded = UserLoginResponse.decode(new Reader(buf))

方式 B:单独模块/库

  • packages/ 作为独立模块(或库工程)引入,并在应用模块中通过路径或别名导入。
  • 保证 protobuf-core 位于生成包的同级(默认目录名可配)。

服务调用(实现 RpcTransport)

生成的 *Client 通过 RpcTransport 发送请求:

import { RpcTransport } from '../protobuf-core'
class HttpTransport implements RpcTransport {
  async unary(path: string, req: Uint8Array, md?: Record<string,string>): Promise<Uint8Array> {
    // 在此使用 HarmonyOS 的网络能力(例如 HTTP/WebSocket)发送二进制并返回二进制响应
    // 伪代码:
    // const resBytes: Uint8Array = await httpPostBinary(baseUrl + path, req, md)
    // return resBytes
    return new Uint8Array(0)
  }
}

使用客户端:

import { DemoClient } from '../pb'
const t = new HttpTransport()
const cli = new DemoClient(t)
// const res = await cli.UseA(Common.create({ id: 123 }))

编码/解码示例

import { Writer, Reader } from '../protobuf-core'
import { UserLoginResponse } from '../pb'
const m = UserLoginResponse.create({ sessionId: 's', userPrivilege: 'p', isTokenType: false, formatTimestamp: 0n })
const b = UserLoginResponse.toBinary(m)
const m2 = UserLoginResponse.fromBinary(b)

JSON 往返示例

import { UserLoginResponse } from '../pb'
const m = UserLoginResponse.create({ sessionId: 's', userPrivilege: 'p', isTokenType: true, formatTimestamp: 123n })
const j = UserLoginResponse.toJson(m)
const m2 = UserLoginResponse.fromJson(j)

map 字段示例

import { ExampleMapMsg, Demo } from '../pb'
const mp = new Map<string, Demo>()
mp.set('k1', Demo.create({ v: 1 }))
mp.set('k2', Demo.create({ v: 2 }))
const m = ExampleMapMsg.create({ items: mp })

oneof 字段示例

import { ExampleOneof } from '../pb'
const m1 = ExampleOneof.create({ content: { kind: 'text', text: 'hello' } })
const m2 = ExampleOneof.create({ content: { kind: 'image', image: new Uint8Array([1,2,3]) } })

CLI 选项详解

  • --in <dir>:输入 .proto 根目录(支持子目录递归)
  • --out <dir>:输出 ArkTS 目录
  • --int64 bigint|number:64 位整型模式
    • bigint:精度安全,推荐
    • number:可能失精度;使用 Reader.int64Number()/uint64Number()
  • --docs on|off:是否输出注释(消息/字段/oneof/枚举/成员/服务/方法)
  • --omit-defaults on|off:编码时省略默认值(标量/枚举),消息字段不省略
  • --json on|off:生成 toJson/fromJson
    • 标量直映;bytes→Base64;int64(bigint)→字符串
    • map:对象映射(键统一字符串化);oneof:按被选键展开
    • WKT:Timestamp/Duration/Any/Struct/Value/ListValue/FieldMask 支持
  • --json-enum names|numbers|accept-both:枚举 JSON 策略
    • names:序列化为名称;反序列化按名称
    • accept-both:反序列化同时接受名称与数值(序列化仍按当前模式)
  • --json-strict on|offfromJson 类型严格校验
  • --concurrent sendable|off:为消息/服务添加 @Sendable 标注
  • --namespace-as-file on|off:按包层级拆分目录并构建分层索引
  • --bundle-runtime on|off:复制运行时至输出并重写导入路径,默认 on
  • --runtime-dir <name>:运行时子目录名,默认 protobuf-core

编译结果示例

输入:

syntax = "proto3";
package user;
message UserLoginResponse {
  string sessionId = 1;
  string userPrivilege = 2;
  bool isTokenType = 3;
  int64 formatTimestamp = 5;
  bytes data = 6;
}

输出(简化):packages/user/messages/UserLoginResponse.ets

import { Writer, Reader } from '../../protobuf-core'
export class UserLoginResponse {
  sessionId: string | undefined
  userPrivilege: string | undefined
  isTokenType: boolean | undefined
  formatTimestamp: bigint | undefined
  data: Uint8Array | undefined
  // ... encode/decode/verify/toBinary/fromBinary
}

高级用法

省略默认值

node ./src/generator/arkpb-gen.js --in ./protos --out ./packages --int64 bigint --omit-defaults on

启用 JSON 与 WKT

node ./src/generator/arkpb-gen.js --in ./protos --out ./packages --int64 bigint --json on --json-enum names

常见问题(FAQ)

  • 枚举十六进制负值:生成器已预处理 = -0x... 为十进制负数
  • 索引文件为空:已采用“合并写入”避免被后续覆盖清空
  • int64 number 精度:超过 Number.MAX_SAFE_INTEGER 会失精度,推荐 bigint
  • Base64:bytes 在 JSON 中使用 Base64 字符串,运行时提供 encodeBase64/decodeBase64

ArkTS 兼容性注意事项

  • 导入路径不带扩展名:不要在 import/export 中写 .ets 后缀
  • 保留字字段自动避让:生成的属性名会使用安全标识符(例如 export_),JSON 键保持原字段名
  • 不使用 any/unknown 与索引签名:verifyfromJson 采用显式类型与 object
  • 运行时不依赖 TextEncoder/TextDecoder:使用纯算法 UTF-8 编解码
  • 禁止下标访问字符串/字节数组:运行时 Base64 与 UTF-8 使用 DataView.getUint8string.charAt

目录结构

  • src/generator/arkpb-gen.js:生成器 CLI
  • runtime/arkpb/*:运行时源码(Writer/Reader/util/RpcTransport)
  • protos/:示例协议(用于本仓库验证)
  • packages/:默认输出目录(执行后生成)

完整命令清单(参考)

# 基本生成(bigint,带注释)
npx arkpb-gen --in ./protos --out ./packages --int64 bigint --docs on

# 生成 JSON API 与 WKT 映射
npx arkpb-gen --in ./protos --out ./packages --int64 bigint --json on --json-enum names

# 打开并发标注与分层目录
npx arkpb-gen --in ./protos --out ./packages --int64 bigint --docs on --json on --concurrent sendable --namespace-as-file on

# 自定义运行时目录名
npx arkpb-gen --in ./protos --out ./packages --int64 bigint --runtime-dir protobuf-core

如需将生成过程集成到你的构建流水线,可在工程脚本中调用上述命令并自动拷贝到 ArkTS 项目模块下。若需要进一步的使用示例或问题定位,请在 Issues 中反馈。