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

@turinhub/tale-js-sdk

v2.4.4

Published

Official TypeScript SDK for Tale backend services

Readme

@turinhub/tale-js-sdk

官方 TypeScript SDK,用于与 Tale 后端服务集成与交互。

安装

支持 npm、pnpm、yarn 安装:

npm install @turinhub/tale-js-sdk
# 或
pnpm add @turinhub/tale-js-sdk
# 或
yarn add @turinhub/tale-js-sdk

快速开始

本 SDK 采用 ESM(type: module)。在 TypeScript 或现代 Node.js/前端环境中可直接导入:

import {
  createTaleAdminClient,
  createTaleAppClient,
} from "@turinhub/tale-js-sdk";

const admin = createTaleAdminClient({
  baseUrl: "https://api.tale.example",
  taleToken: "tale-user-token",
});

const currentUser = await admin.currentUser.get();
const apps = await admin.apps.listByOrg(currentUser.app.orgId);
const issued = await admin.appTokens.issue({ appKey: "oa_xxx" });

const app = createTaleAppClient({
  baseUrl: "https://api.tale.example",
  appToken: issued.token,
});

const files = await app.cms.listFiles({ folderId: "folder-id" });

认证与 Token

SDK 中常见的鉴权选项都通过 x-t-token 发送到 Tale 后端:

  • appToken:应用作用域 Token,适用于 CMS、RBAC、ACL、Task、Attachment 等应用内资源 API。
  • taleToken:Tale 用户 Token,适用于平台级 App 管理 API,例如获取当前用户、应用列表、应用详情、App Secret,以及按 App Key 换发 App Token。
  • baseUrl:Tale 后端服务基础 URL;未显式传入时会读取环境变量。

服务端可使用 getAppToken() 通过 TALE_APP_KEYTALE_APP_SECRET 获取应用 Token。getAppToken() 是 server-only helper,不应在浏览器代码中调用或暴露 TALE_APP_SECRET。浏览器端的 Cookie、缓存、自动续期和多应用切换策略不由 SDK 核心管理,调用方可基于 createTaleAdminClient().appTokens.issue() 或业务后端代理自行封装。

生产环境服务端网站建议使用动态 Token provider,而不是在进程启动时签发一次后长期持有固定 appToken

import { createTaleAppClient, getAppToken } from "@turinhub/tale-js-sdk";

const app = createTaleAppClient({
  baseUrl: process.env.TALE_BASE_URL,
  appTokenProvider: () =>
    getAppToken({
      baseUrl: process.env.TALE_BASE_URL,
      appKey: process.env.TALE_APP_KEY,
      appSecret: process.env.TALE_APP_SECRET,
    }),
});

getAppToken() 会按凭据缓存 token,在过期前提前后台刷新;刷新失败但旧 token 仍有效时会继续使用旧 token,并在后续短间隔重试。SDK 内部请求遇到明确的 token 过期或无效响应时,会强制刷新并重试一次。多实例部署时,仍建议在应用层结合 Redis/KV 与分布式锁共享 token 并错峰刷新,避免所有实例同时请求签发接口。

Admin 与 App Client

也可以从子路径导入两个客户端入口:

import { createTaleAdminClient } from "@turinhub/tale-js-sdk/admin";
import { createTaleAppClient } from "@turinhub/tale-js-sdk/app";

Admin client 只接收 taleToken,用于平台级应用管理:

const admin = createTaleAdminClient({ baseUrl, taleToken });

await admin.currentUser.get();
await admin.apps.listByOrg("org_1");
await admin.apps.create({ appName: "Demo", orgId: "org_1" });
await admin.apps.getDetail("oa_xxx");
await admin.apps.update({ appId: "app_1", appName: "Demo" });
await admin.appTokens.getSecret("oa_xxx");
await admin.appTokens.issue({ appKey: "oa_xxx" });

App client 接收固定 appToken 或动态 appTokenProvider,用于单应用内资源:

const app = createTaleAppClient({ baseUrl, appToken });

await app.cms.listFiles({ folderId: "folder_1" });
await app.users.list({ page: 0, size: 20 });
await app.tasks.create({ openId: "ou_xxx", taskTypeId: "type_1" });
await app.tasks.get("task_1", {
  includeAttachments: true,
  includeSubTasks: true,
});
await app.rbac.listRoles();
await app.acl.listRecords();
await app.attachments.listByRef({ refType: "task", refId: "task_1" });
await app.appTokens.list({ page: 0, size: 20 });

Legacy-compatible 函数导入

已有项目可以继续从根入口直接导入函数。该方式在 2.x 内保持兼容,但新项目建议优先使用 Admin/App client。

import {
  getAppToken,
  getCurrentUser,
  listAppsByOrg,
  listFiles,
} from "@turinhub/tale-js-sdk";

const appToken = await getAppToken({
  baseUrl,
  appKey: process.env.TALE_APP_KEY,
  appSecret: process.env.TALE_APP_SECRET,
});

const files = await listFiles({ baseUrl, appToken, folderId: "folder-id" });
const currentUser = await getCurrentUser({ baseUrl, taleToken });
const apps = await listAppsByOrg(currentUser.app.orgId, { baseUrl, taleToken });

AppTS 模块提供平台应用相关方法:

import {
  getCurrentUser,
  listAppsByOrg,
  createApp,
  getAppDetail,
  updateApp,
} from "@turinhub/tale-js-sdk";

AppTokenTS 模块提供 App Token 相关接口封装:

import {
  listAppTokens,
  getAppSecret,
  issueAppToken,
} from "@turinhub/tale-js-sdk";

const page = await listAppTokens({
  baseUrl: "https://api.tale.example",
  appToken: "app-token",
  page: 0,
  size: 20,
  isValid: true,
});

const secret = await getAppSecret("oa_xxx", {
  baseUrl: "https://api.tale.example",
  taleToken: "tale-user-token",
});

const issued = await issueAppToken({
  baseUrl: "https://api.tale.example",
  taleToken: "tale-user-token",
  appKey: "oa_xxx",
});

公开类型、入参和响应字段保持 camelCase。SDK 会处理 Java 后端可能返回的 { code, msg, data } envelope 与直接 payload,但不再兼容历史 snake_case 响应字段。

开发与测试

仓库采用 TypeScript 与 Jest:

pnpm install   # 或 npm install / yarn
pnpm run typecheck
pnpm run build
pnpm run test:unit
pnpm test

发布

如果本机配置了 npm 镜像,发布时显式指定 npm 官方 registry:

pnpm run build
pnpm run typecheck
pnpm run format:check
pnpm run test:unit
npm publish --access public --registry=https://registry.npmjs.org/

更新日志与版本

遵循语义化版本(SemVer)。发布与变更说明将按迭代在仓库中维护。

TODO

  • [x] 修改 User Group 等分页格式,统一为 PageResponse。

许可证

本项目基于 MIT 许可证开源,详见 LICENSE 文件。版权归 Turinhub 团队所有。