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

irobotbox-saihe

v1.1.0

Published

赛盒 irobot 登录、产品图上传、批量改价(allegro、Ebay)、CLI 与 SDK(baseUrl/商户号由调用方或环境显式提供)

Readme

irobotbox-saihe

saihe产品图上传(Node 18+)。

安装

在 monorepo 根目录执行 npm install(已配置 workspace irobotbox-saihe),或在本包目录单独执行 npm install

本机单实例 Node 服务(推荐做法)

部署形态是**一台机器、一个 Node 进程(或单实例 PM2/systemd)**时,建议开启 sessionFile

  • 进程重启、发版后仍能尽量复用上次 Cookie,少重复登录、少打验证码。
  • 路径请用 **path.resolve 固定成绝对路径**(或 __dirname 相对项目目录),避免工作目录变了导致单例校验里 sessionFile 不一致。
  • 会话文件含 Cookie,勿提交到 git(在仓库根 .gitignore 里忽略 saihe_session.json*.publish.json 或你的专用路径);文件权限按本机安全要求收紧。
  • Publish SSO(Allegro 等):配置了 sessionFile 时,默认会额外使用同目录、去掉扩展名后加 .publish.json 的文件持久化换票得到的 .AspNetCore.Cookies。也可显式传 publishSessionFile(绝对路径推荐),或传 publishSessionFile: null 关闭落盘。ERP 重新登录或 resetAllegroPublishSession 会删除该文件,避免误用过期 Publish 票。

若将来改为多机/多副本,再考虑改为不依赖本机文件、或集中存储会话;单机构造下 sessionFile 是最省心的默认项。

SDK 使用示例

多模块、同进程请用 **getSaiheIrobotClient** 单例,共享同一份 Cookie;不要各处 new SaiheIrobotClient。需要换账号时先调用 resetSaiheIrobotClient(),再带新 config 调用 getSaiheIrobotClient(config)

初始化(应用启动或公共模块中只执行一次)

const path = require("path");
const {
  getSaiheIrobotClient,
} = require("irobotbox-saihe");

const client = getSaiheIrobotClient({
  baseUrl: process.env.SAIHE_BASE_URL, // 必填:赛盒站点根地址,勿硬编码
  username: process.env.SAIHE_USERNAME,
  password: process.env.SAIHE_PASSWORD,
  customerId: process.env.SAIHE_CUSTOMER_ID, // 未设置时,登录/上传会要求提供或由 session 恢复
  // 本机单服务建议固定绝对路径,例如:path.resolve(process.cwd(), "data/saihe_session.json")
  sessionFile: path.resolve(process.cwd(), "saihe_session.json"),
});

不建议getSaiheIrobotClient 内部自动 await 登录:该函数是同步的,无法完成异步登录;且进程内首次拉客户端就弹验证码/OCR 会拖慢所有引用方。

更合适的方式:

| 场景 | 做法 | |------|------| | 长驻服务启动 | await initSaiheIrobotClient(config),或 getSaiheIrobotClient(config)await client.ensureErpSession() | | 仅上传 | 可继续只 uploadImage:失效时内部会重登(与您以往用法一致) | | Allegro Listing | ensureAllegroPublishSession / allegroListingSearch / allegroListingBatchUpdatePrice 等在需换 Publish 票时会先 ensureErpSession(默认工作台探测);buildAllegroBatchUpdatePricePayload(单条)、buildAllegroBatchUpdatePricePayloadMany(多条 listing)与 ALLEGRO_BATCH_SITE_IDSallegroListing.js | | eBay V2 Listing(ERP) | 仅用 ERP CookiebaseUrl + sessionFile),不要 Publish SSO。buildDefaultListingListParams 组装列表筛选;client.ebayListingSearchPage / ebayListingRecordCount 拉列表;ebayBatchSetBuyItNowPrice / ebayCollectListingBasicIdsFromSearch 做批量 Buy It Now 改价(详见下文)。 |

ensureErpSession({ force: true }) / skipProbe: true 会跳过探测、直接走完整登录(验证码等)。详见 SaiheIrobotClient JSDoc。

eBay V2(ERP 批量改价)

与 Allegro 不同:接口在 /IrobotBox/EbayV2/,走 GET + query,响应多为 HTML content-type 包裹的 JSON。

const client = getSaiheIrobotClient({ /* …同初始化示例… */ });

await client.ensureErpSession();

const clientSku = "YOUR_CLIENT_SKU";
const count = await client.ebayListingRecordCount({
  SearchValue: clientSku,
});
const page = await client.ebayListingSearchPage({
  SearchValue: clientSku,
  CurrentPage: "1",
  pagesize: "20",
});

const ids = await client.ebayCollectListingBasicIdsFromSearch({
  SearchValue: clientSku,
});

await client.ebayBatchSetBuyItNowPrice({
  listingBasicIds: ids,
  operatingvalue: "24.00",
  chunkSize: 50,
  skipSaveVerification: false,
  throwOnBusinessFailure: false,
  retryExcludeBusyListingIds: true,
});
  • getSaiheIrobotClientebayBatchSetBuyItNowPrice 按每个 chunk 单独走会话探测与重登重试,后半批失败时不会重复提交已成功的前面的块。非法 chunkSize(非有限数字或小于 1)会静默回退为 50;单次 GET 过长时可自行减小 chunkSize。设 throwOnBusinessFailure: true(或放在最后一个参数的 callOptions 里)时,若 EditBuyItNowPrice 返回 success: false 会抛错(默认 false,与仅解析 JSON 的旧用法兼容)。不要与 retryExcludeBusyListingIds 同时开启(先抛错则无法自动剔除)。
  • retryExcludeBusyListingIds: true(或 callOptions 里):当服务端返回如 ListingID:…的产品正在修改中! 时,在本 chunk 内解析 msg 中的 ID、剔除后自动重试其余 listing;汇总结果里可有 skippedBusyListingBasicIds。底层解析见 parseListingBasicIdsFromEbayEditFailureMsg
  • 直接使用 ebayBatchSetBuyItNowPrice(jar, baseUrl, …)(不经过 client)时不含 ERP 会话重试,但可传 retryExcludeBusyListingIds(与本段逻辑一致);会话仍须自备。

其它文件里取同一客户端(无参即可)

const { getSaiheIrobotClient } = require("irobotbox-saihe");

async function main() {
  const client = getSaiheIrobotClient();
  const result = await client.uploadImage("2779085", "/path/to/need_upload/a.png");
  console.log(result.oss.url);
}

上传说明

  • SKU 须为纯数字字符串(如 "2779085"),否则会抛错。
  • 第二参数可为:本地文件路径、Buffer(建议同时传 uploadOptions.fileName)、或 { buffer, fileName, mimeType? }
  • 返回含 displayFileNameoss(含 url)、save(后台 SaveImage 响应)。
// 从 need_upload 目录按文件名(与 CLI 一致时可只传文件名拼路径)
await client.uploadImage("2779085", path.join(process.cwd(), "need_upload", "pic.png"));

// 内存图片
await client.uploadImage("2779085", imageBuffer, {
  fileName: "shot.png",
  mimeType: "image/png",
});

切换账号(例如多租户测试)

const { getSaiheIrobotClient, resetSaiheIrobotClient } = require("irobotbox-saihe");

resetSaiheIrobotClient();
const other = getSaiheIrobotClient({
  username: "user2",
  password: "secret2",
  sessionFile: "/path/to/session2.json",
});

CLI

npx saihe --help
# 或在本仓库内:node bin/cli.cjs --help
  • 无子命令:交互/环境变量登录,写入 saihe_session.json(或 SAIHE_SESSION_FILE)。
  • npx saihe images <SKU> [index]:查产品图 Tab。
  • npx saihe upload <SKU> <文件名>:从 need_upload 上传;会话失效时可用 SAIHE_PASSWORD 等自动重登。

SAIHE_BASE_URL 为必填;其余常用:SAIHE_SESSION_FILESAIHE_USERNAMESAIHE_PASSWORDSAIHE_CUSTOMER_IDSAIHE_NO_OCRSAIHE_CAPTCHA 等,见 bin/cli.cjs--help 输出。

自测

npm run test:smoke
# 真机联调(需网络):见 test/sdk-smoke.cjs 内注释;eBay 列表可选环境变量 SAIHE_TEST_EBAY_CLIENT_SKU