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

yichong-web

v0.6.0

Published

YiChong Web 后端 SDK:完整公共 API、Replicate、R2 上传、AI、用量与账户接口

Readme

yichong-web

开发文档:飞书开发指南与 API 速查 · 本地文档源稿。接口、版本或接入状态变更时同步维护。

供 Imgkits、TeachAny、Transmonkey 使用的 TypeScript / ESM 后端工具包。开放 [email protected] 中网站可用的 24 个方法,包括 Replicate、Cloudflare R2 上传、AI、用量、账户状态和配置;Canva 宿主专用的身份接口不开放。运行时仅依赖 yichong-api,不依赖 Vue、Nuxt、React 或 Canva SDK。

现有登录代码和 Pinia store 继续提供用户 ID、业务 JWT、渠道与语言。账户请求另外读取当前 passport 和鉴权渠道。SDK 只执行显式调用的底层接口,不组织登录流程、保存票据、计算消费或刷新账户,不读取路由和 localStorage。每个方法读取调用时的最新上下文,不缓存初始化时的用户或 JWT。

安装与验证

当前版本 0.6.0 移除 Canva 宿主专用的 account.handleUserLoginByCanvaId、account.getPassport、canvaIdentity.getUserIds 以及 accountPassport / canvaIdentity 服务配置(三个网站均未使用);0.5.0 新增任务等待 waitForPrediction、上传保留期 retention、getPredictionOutputUrl / isAbortError 与上报 sdkVersion,精确依赖 [email protected];0.4.0 新增 TTS 和行为统计。使用 Node.js 22 或 24 做常规开发:

cd yichong-web
npm ci
npm run check
npm pack

在需要升级的网站目录执行:

npm install [email protected] --save-exact

所有接口通过正式 npm 依赖 [email protected] 复用公共实现,npm 会自动安装 API 包。公共层以现有 Canva 接口为参考;yichong-canva2 保持原有独立实现。公开包保留 import ... from 'yichong-api',不内嵌 dist/shared-api/ 或引用本地源码目录。

构建脚本清理 dist,只编译 Web 源码,生成 ESM 和类型声明。API 发布后,在本目录执行 npm ci 即可开发,不需要任何相邻源码目录。check 包含类型检查、模拟传输测试,以及实际 tarball 的 npm 依赖自动安装、入口和类型消费者检查。安装检查使用本机临时 registry 和空缓存,仅向本机读取候选包,不依赖未发布版本的线上 registry。工具包创建或重构不会自动升级三个网站的依赖。

从现有 Nuxt / Pinia 接入

以 Imgkits 为例,在 Nuxt 插件中创建客户端。不要在模块顶层创建共享用户单例;SSR 时每个 Nuxt 请求使用自己的实例。

import { createWebClient } from 'yichong-web'
import { userStore } from '~/stores/user'

export default defineNuxtPlugin((nuxtApp) => {
  const store = userStore()
  const client = createWebClient({
    getContext: () => ({
      uid: store.user?.id,
      platformUid: store.user?.google_uid || store.user?.id,
      jwt: store.jwt,
      appChannel: 'imgkits',
      locale: String(nuxtApp.$i18n.locale.value),
    }),
  })
  return { provide: { yichongWeb: client } }
})

三个网站现有公共请求的默认 app_channel 分别为 imgkits、teachany、trans_monkey;独立产品可在 getter 中显式返回自己的渠道。app_channel 是请求归属,Channel: ai 是模型服务的认证通道,两者不同。不要从页面显示名推断渠道。platform 缺省为 web,platformUid 缺省回退到 uid;SDK 不要求 Canva ID。

locale 默认 en,现有 jp、zh、zh_TW 分别映射为 ja、zh-CN、zh-TW。时区可通过 timezone 传入;省略时取当前运行环境的 IANA 时区,失败回退 UTC。上下文附加到 SDK 自有服务请求的 uid / platform_uid / platform / app_channel / timezone query;语言只通过 Accept-Language 发送。

replicateBaseUrl 默认 https://api.imgkits.com,uploadBaseUrl 默认 https://ai.imgkits.com,旧配置继续有效。所有端点也可通过 services 分别配置;同一服务两种配置都存在时,旧的 replicateBaseUrl / uploadBaseUrl 优先。fetch 可以注入原生 fetch 兼容的传输,不是返回已解析对象的 $fetch。Replicate、Chat、内容提取要求 uid 和业务 JWT;文本审核要求 JWT。上传签名保持原有 node-nauth 合同,允许缺省 uid,由网站保留自己的登录前置条件。

完整接口与服务配置

以下 24 个方法均可直接从 createWebClient() 返回值调用。参数/响应类型均可从 yichong-web 导入;apiContracts 和 defaultServices 也从包入口导出,分别提供路径协议和默认地址;0.5.0 起另导出 getPredictionOutputUrl 和 isAbortError。

| 分组 | 客户端方法 | services 配置项 / 默认地址 | | --- | --- | --- | | Replicate(5) | createPrediction、createSpecifyPrediction、getPrediction、cancelPrediction、waitForPrediction | replicate / https://api.imgkits.com | | 上传(5) | generatePresignedUrl、initiateUpload、getUploadUrl、completeUpload、uploadFile | upload / https://ai.imgkits.com | | 文本审核(1) | textCheck | moderation / 未配置时跟随 replicate | | 内容提取(1) | contentExtract | content / https://ai.imgkits.com | | 大模型(1) | chat | chat / https://ai.imgkits.com | | 音视频转录(2) | createVtt、getVttStatus | vtt / https://api.imgkits.com | | 语音合成(2) | createTextToSpeech、getTextToSpeechResult | tts / https://ai.imgkits.com | | 行为统计(1) | reportUsage | usageReporting.endpoint / https://log.aibabygenerator.io/api/report | | 用量(3) | reduceFreeCnt、addMonthlyUsage、addFreeUsageCnt | account / https://usa.imgkits.com | | 账户(1) | account.getUserStatusByPassport | account / https://usa.imgkits.com | | 站点配置(1) | siteConfig.getAppVersion | siteConfig / https://usa.imgkits.com | | 错误上报(1) | reportError | reporting / https://report.imgkits.com |

services 支持反向代理路径前缀,例如 { account: 'https://usa.imgkits.com/product' }。WebApiServices、WebReportingConfig 和 AccountCredentials 提供对应的配置类型。

Canva 版的 canvaid-login、canva-passport 和 getUserIdByAppid 依赖 Canva ID 或 Canva 宿主令牌,网站拿不到,因此不在 Web 客户端上;apiContracts 仍原样导出公共库的完整合同表,仅供查阅。网站的 passport 继续由现有登录层通过 /api/user/passport(google_uid)取得,再经 getAccountCredentials 传入。Imgkits 的 OCR、支付、3D 生成等其他业务端点,以及普通网站的 Google 登录流程,不因开放这些方法就自动接入。升级依赖后,网站仍需逐项把原有业务入口适配到 SDK。

任务等待、上传保留期与上报版本(0.5.0 起)

0.5.0 精确依赖 [email protected],与 yichong-canva2 2.5.1 的 API 对齐:

import { getPredictionOutputUrl, isAbortError } from 'yichong-web'

const controller = new AbortController()
try {
  const { data: id } = await client.createSpecifyPrediction({ owner, name, input })
  const task = await client.waitForPrediction({ id }, { signal: controller.signal })
  const url = getPredictionOutputUrl(task.output)
  const saved = await client.uploadFile({ file, retention: 'day30' })
} catch (error) {
  if (!isAbortError(error)) showError(error)
}
  • waitForPrediction 只重复调用 getPrediction,Web 查询正文继续补 user_id。默认每 3 秒查询、最多 60 次、总预算 180 秒;failed / canceled / aborted 抛 prediction_failed,用完抛 prediction_timeout,主动取消抛 aborted。不会自动取消后端任务、重复创建或消费。已有轮询与任务恢复逻辑的页面无需改用。
  • uploadFile 的 retention: 'temp' | 'day30' 选择自动命名前缀,默认 temp_;不能与 objectName 同时传入。Imgkits 的 utils/uploadR2.js 现有命名规则不变。
  • reporting.sdkVersion 可写入错误诊断的 sdk_version;reporting.robot 会参与脱敏。

TTS 与行为统计(0.4.0 起)

直接调用 client.createTextToSpeech({ text, voice?, emotion?, speed?, language?, refer_audio?, refer_audio_text? }) 与 client.getTextToSpeechResult({ jobId })。服务地址由 services.tts 覆盖,默认 https://ai.imgkits.com。创建正文的 guid 自动取当前系统 uid,不传 app_id 或手动身份字段;JWT 可选,有有效值才发送。text 最多 5000 个 Unicode 字符,speed 范围 0.5–2.0。

两方法返回完整 { code: 0, msg, data };status 为 0 等待、2 处理中、10 完成、-1 失败,创建也可能立即返回失败。完成后的 data.result 为音频 URL 或 null。默认单次 60 秒,支持 { timeoutMs, signal },不自动重试、轮询或重复扣费;后端已有 TTS 字符用量处理。创建超时不代表后端未创建或未计费,不要直接重放创建。

void client.reportUsage({ sum_key: 'voice_select', title: '选择音色', data: { voice: 'Arrogant_Miss' } }) 兼容现有 GET 统计接口。创建客户端时可配置 usageReporting: { enabled, endpoint, appKey } 与 getUsageReportingMetadata: () => ({ session_id, app_version })。Web 端只显式记录业务事件,不自动监听路由或创建网站会话。

统计允许登录前调用,不发送 JWT、passport 或 cookie。返回 Promise<boolean>,失败返回 false、不抛错、不阻塞业务。默认每次 4 秒,网络/超时/429/5xx 最多重试一次,同事件复用 UUID。只传固定属性、计数、耗时、错误码;不要传用户文本、完整 input/output、文件 URL、凭据或原始错误。

Chat、审核与内容提取

const check = await client.textCheck({ text: prompt })
if (!check.data.allowed) {
  // 在页面提示审核结果,并停止当前业务流程。
  return
}

const extracted = await client.contentExtract({ type: 'link', url: publicUrl })
const reply = await client.chat({
  payload: { messages: [{ role: 'user', content: extracted.data.content }] },
})
console.log(reply.data.result)

三个接口均使用业务 JWT 和 Channel: ai,返回完整 { code: 0, msg, data }。textCheck 返回 allowed / decision / categories 等原始审核结果;contentExtract 接收公开 HTTP(S) 地址,type 为 file / video / link,本地文件应先上传;chat 返回完整文本,不自动解析文本内的 JSON,也不提供流式增量。默认等待预算分别为 60 秒、360 秒、360 秒,均支持第二参数的 signal / timeoutMs。

音视频转录

const task = await client.createVtt({
  audio: 'https://media.example/audio.mp3',
  // 视频改用 video: 'https://media.example/video.mp4'
})
const status = await client.getVttStatus({ jobId: task.data.jobId })
if (status.data.status === 10 && status.data.result) {
  const segments = JSON.parse(status.data.result)
  console.log(segments)
}

创建使用 POST /get-vtt/create,查询使用 POST /get-vtt/status。默认地址为 https://api.imgkits.com,可通过 services.vtt 覆盖(支持路径前缀);后端需已部署通用路由及相应网关转发。

创建只传 audio 或 video 的公开 HTTP(S) 地址,userId 自动取当前 getContext().uid。身份、业务 JWT、Channel: ai、语言与时区沿用 Web 上下文;查询正文只传 jobId。可选参数 ifRender: 0 | 1、email、env 按后端原名传递,普通使用省略 env。

返回完整 { code, msg, data };data.status 为 0 / 2 时继续等待,为 10 时成功,为 -1 时由页面显示任务失败。data.result 是字幕片段数组的 JSON 字符串,不是 WEBVTT/SRT 文件。单次请求默认超时 60 秒,支持第二参数 { timeoutMs, signal };上传、轮询和扣费时机由业务组织,SDK 不自动执行。取消请求只停止等待,不取消后端任务。

用量与账户底层请求

在已有客户端配置中增加凭据 getter,值从网站现有登录层读取:

const client = createWebClient({
  getContext: readCurrentRequestContext, // 返回 uid、jwt、appChannel、locale 等
  getAccountCredentials: () => ({
    accessChannel: readCurrentAccountChannel(),
    passport: readCurrentPassport(),
  }),
})

// 以下是独立操作示例;一次消费按原业务规则选择一种接口。
await client.reduceFreeCnt({ cnt: 1 })
// 或 client.addMonthlyUsage({ cnt: 1 })
// 或 client.addFreeUsageCnt({ cnt: 1 })

const status = await client.account.getUserStatusByPassport()
// 网站继续按账户服务的业务字段处理 status、更新原有 store。

示例中的 readCurrent... 函数由网站现有 store / 登录层提供。appChannel 是请求归属(如 imgkits),accessChannel 是账号票据所属渠道(如 imgkit 或插件专用渠道),两者不能直接互相替代。消费接口使用 X-Access-Channel / X-Access-Ticket,不会把 JWT 当作 passport。

用量接口返回原始 { ok: 0, msg, ... },默认等待 30 秒;失败不自动重试,避免重复记账。SDK 不选择套餐、不修改本地积分,也不自动刷新账户。未提供当前票据或 uid 时,用量请求会在本地报 account_not_ready。

账户状态查询返回后端原始对象,不因为 HTTP 200 就判定登录成功;需要账户渠道和当前 passport,默认等待 30 秒。SDK 不登录、不申请或保存 passport,不处理 Google Drive state。网站仍负责读取业务结果、更新登录状态和处理过期。

站点配置与错误上报

const config = await client.siteConfig.getAppVersion({ key: 'your-existing-config-key' })
console.log(config.version)

站点配置无需 JWT 或 passport;成功时解析 data.value 的 JSON 对象,后端 success 为假时返回 {}。查询键沿用网站已有配置,SDK 不猜测或添加前缀。

上报需要单独配置通道,不会随其他 API 自动触发:

const client = createWebClient({
  getContext: readCurrentRequestContext,
  getAccountCredentials: readCurrentAccountCredentials,
  reporting: {
    appId: 'imgkits',
    version: 1,
    getToken: readCurrentReportingToken,
    // getSecrets: () => [需要额外脱敏的现有凭据],
  },
})

try {
  await client.reportError({ error, source: 'api', stage: 'create_prediction' })
} catch (reportError) {
  // 独立处理上报失败,保留原业务错误。
}

使用现有上报专用令牌,不能以 JWT/passport 替代,也不内置固定凭据。上报正文会脱敏当前 JWT、passport、上报令牌及 getSecrets 提供的值;不会把业务认证头或公共 query 加到上报请求。该浏览器通道令牌会进入前端运行环境,不应视作服务端秘密。返回 { success: true, data },其中 data.status=ignored 代表 Worker 忽略了该条报告;默认等待 10 秒。未配置时显式调用报 reporting_not_ready,其他接口照常可用。

Replicate

| 方法 | 后端 POST 路径 | 响应 | | --- | --- | --- | | createPrediction({ version, input, debug? }) | /replicate/createPrediction | { code: 0, msg, data: taskId } | | createSpecifyPrediction({ owner, name, input, ... }) | /replicate/createSpecifyPrediction | 同上 | | getPrediction({ id }) | /replicate/getPrediction | { code: 0, msg, data: { id, status, output, ... } } | | cancelPrediction({ id }) | /replicate/cancelPrediction | 原始响应包或供应商任务对象 |

创建和查询自动从当前上下文填入 user_id。业务不得覆盖身份字段。指定模型创建保留 video_type / video_catalog / catalog_model_id / primary_provider / execution_chain / provider_requests;video_catalog=\"schema_v2\" 且提供非空 provider_requests 时可省略顶层 input。模型、输入、供应商顺序和返回数据不改写。

const { $yichongWeb: client } = useNuxtApp()

const created = await client.createSpecifyPrediction({
  owner: 'your-confirmed-owner',
  name: 'your-confirmed-model',
  input: { prompt: 'your prompt' },
})
const result = await client.getPrediction({ id: created.data })
if (result.data.status === 'succeeded') {
  // 按当前模型合同处理 result.data.output;可能是字符串、数组或对象。
}

每个方法只请求一次,不自动轮询、创建重试、上报或扣费。查询到 failed / canceled 返回任务状态,由业务决定如何展示;HTTP / 业务失败则抛 ApiError。业务轮询首次 succeeded 后立即停止,保留原任务恢复与消费规则。cancelPrediction 是显式后端操作,部分供应商只清理网关状态,不能保证上游任务停止。

本版不封装模型目录、/replicate/ai-image/* 或 /replicate/ai-video/* 意图接口。目录任务继续使用原来的对应查询端点,不要切换到普通 getPrediction。

R2 Upload

| 方法 | 签名服务 POST 路径 | | --- | --- | | generatePresignedUrl({ objectName, bucketName? }) | /api/generate-presigned-url | | initiateUpload({ objectName, bucketName?, contentType? }) | /upload/initiate-upload | | getUploadUrl({ objectName, uploadId, partNumber, bucketName? }) | /upload/get-upload-url | | completeUpload({ objectName, uploadId, parts, bucketName? }) | /upload/complete-upload |

上述方法保留服务端原始字段,如 UploadId、ETag、endpointBaseUrl。整套上传无需前端存储密钥,不带业务 JWT 或 passport。文件字节直接 PUT 到返回的签名 URL,URL 原样使用,不附加公共参数或业务认证头。

业务优先使用完整上传方法:

const uploaded = await client.uploadFile({
  file,
  onUploadProgress: ({ loaded, total }) => {
    if (total) progress.value = loaded / total
  },
}, { signal: controller.signal })

// uploaded = { url: '公开资源地址', key: '对象名', endpointBaseUrl: '公开基地址' }
  • 小于 100 MiB 使用单次 PUT;达到 100 MiB 自动分片。multipart: true 可强制小文件分片,false 不关闭大文件自动分片。
  • 桶默认 video。对象名默认 temp_{app_channel}_{本地日期}_{32位随机}.{后缀},沿用现有上传命名。fileName 用于后缀,objectName 可保留业务所需的原有前缀和对象键。
  • 单次上传的公开 URL 来自签名响应的 endpointBaseUrl。分片优先取初始化响应;旧响应缺失时,用同一对象/桶再申请一次普通签名,只读取公开基地址。合并响应返回最新地址时以它为准,不从 S3 Location 或签名 host 猜测地址。
  • 单次上传传进度回调时使用浏览器 XHR,loaded/total 单位为字节;分片为已完成片数/总片数。100% 后仍须等待响应或合并成功,只有 Promise 完成才能使用结果。
  • 分片 PUT 必须能读取 ETag。切换用户或渠道、取消、进度回调异常会停止后续上传步骤;同用户刷新 JWT 不影响上传。
  • 默认总等待预算为单次 120 秒、分片 30 分钟,包含签名、上传、读取响应与合并,不按片重置。第二参数的 timeoutMs 可覆盖。
  • 不自动重试或恢复,不提供服务端分片清理;取消本地传输不等于删除已上传数据。本版不包含 OSS、URL 转存或 Google Drive 导入。

错误与取消

import { ApiError } from 'yichong-web'

try {
  await client.getPrediction({ id: taskId }, { signal, timeoutMs: 30_000 })
} catch (error) {
  if (error instanceof ApiError) {
    if (error.code === 'aborted') return
    // error.message / userMessage 优先保留后端文案。
    // code、status、data、retryAfter 可用于原有界面处理。
  }
}

常见 SDK 错误码:invalid_request / account_not_ready / reporting_not_ready / invalid_response / timeout / aborted / network_error / account_changed / missing_etag / upload_progress_failed。模型和消费接口的 HTTP/业务失败抛出错误;账户旧协议保留原始 JSON,由网站判断业务结果。SDK 不发起自动登录、刷新账户或重放付费请求。取消使用 ApiError.code === 'aborted' 判断。

源码在独立的 frontend/web/yichong-web 目录。上传协议与现有 Web/Canva 上传实现对齐;没有改写 Canva 包,也没有在三站批量替换旧调用。

发布与升级

本次配套版本为 [email protected] 与它精确依赖的 [email protected]。先发布 API,再发布 Web;npm 版本号发布后不可重复使用。

后续公共 API 升级时,先发布 API,再更新本包的精确依赖、版本及 lockfile,运行 npm run check 后发布 Web。npm 可能在发布后短暂返回 404,需等待版本可查询后再升级网站。网站仍然只需安装 yichong-web。