meeglesdk
v0.1.4
Published
飞书项目 Open API TypeScript SDK
Readme
meeglesdk
TypeScript SDK for Feishu Project (Meego) Open API.
Install
npm install meeglesdkQuick Start
import { MeegoClient, withUserKey } from 'meeglesdk';
const client = new MeegoClient({
pluginId: 'YOUR_PLUGIN_ID',
pluginSecret: 'YOUR_PLUGIN_SECRET',
baseURL: 'https://project.feishu.cn',
});
const items = await client.workItem.query(
'project_key',
'story',
{ work_item_ids: [123456] },
withUserKey('user_key')
);Client Options
const client = new MeegoClient({
pluginId: 'YOUR_PLUGIN_ID',
pluginSecret: 'YOUR_PLUGIN_SECRET',
baseURL: 'https://project.feishu.cn', // optional
timeout: 30000, // optional, ms
retry: {
maxRetries: 2,
retryDelay: 1000, // base delay, exponential backoff
maxRetryDelay: 30000, // optional cap for backoff delay
retryableErrorCodes: [10429, 50006] // optional override
},
rateLimit: 'meego-openapi', // preset: doc-based limits (15 QPS + endpoint overrides)
// or customize:
// rateLimit: {
// enabled: true, // optional, default true when provided
// qps: 15, // per token QPS
// burst: 15, // optional burst size
// scope: 'token+method+path', // 'token' | 'token+path' | 'token+method+path'
// entryTtlMs: 600000, // optional, idle bucket cleanup (default 10 min)
// rules: [ // optional overrides
// { method: 'POST', path: '/open_api/work_item/actual_time/update', qps: 10 },
// ],
// },
tokenType: 0, // 0: plugin_access_token, 1: virtual_plugin_token
onTokenRefresh: (token, type, userKey) => {
// persist token if needed
},
logger: console, // optional
});Auth Flows
Plugin Token (Server)
const token = await client.auth.getPluginToken();User Token (Auth Code Exchange)
const { token, expire_time, refresh_token } = await client.auth.getUserToken(code);Manually Set User Token
client.setUserToken({
userKey,
token,
expireTime: expireTimeSeconds,
refreshToken,
refreshTokenExpireTime,
saasTenantKey: tenantKey,
});Request-Level Auth (Recommended for Multi-User)
Do not store user tokens on a shared client. Instead, pass auth per request:
await client.workItem.query(
'project_key',
'story',
{ work_item_ids: [123456] },
{ auth: { type: 'user', token: userToken } }
);
// Helper shortcuts (return request options)
await client.workItem.query(
'project_key',
'story',
{ work_item_ids: [123456] },
withUserKey('user_key')
);Rules:
type: 'user': use the provided user token;userKeyis not needed.type: 'plugin': use plugin token;userKeyis required for user-scoped APIs.type: 'auto'(default): ifuserKeyis provided and a cached token exists for that user, it is used; otherwise plugin token is used.authMode(optional): only applies when a plugin token is used; controlsx-auth-modefor strict read permission checks.
x-auth-mode (Force Read Auth for Plugin Token)
When calling read APIs with plugin_access_token (or virtual_plugin_token), you can set x-auth-mode to
force the server to respect the X-User-Key permissions.
This header has no effect when a user token is used.
authMode: 1-> strict mode (recommended when you must enforce the user's read permissions)authMode: 0or omitted -> compatibility mode
await client.workItem.query(
'project_key',
'story',
{ work_item_ids: [123456] },
{ auth: { type: 'plugin', userKey: 'user_key', authMode: 1 } }
);Token Management Notes
TokenManagercachesplugin_access_tokenand refreshes it automatically.user_access_tokenis cached peruserKeywhen you callauth.getUserTokenorclient.setUserToken.user_access_tokenwill be auto-refreshed per user when possible (requiresrefresh_token).- Use request-level
authfor multi-user apps; avoid sharing a client-scoped user token across users.
Timeout & Retry
- Default timeout: 30s.
- Retries use exponential backoff with a base delay and are enabled by default.
- Network errors, timeouts, and retryable API error codes are retried (default:
10429,50006). - Per-request overrides are supported via
options.retry,options.skipRetry, andoptions.timeout.
WBS View (Query + Body)
const wbs = await client.workItem.workflow.getWbsView(
'project_key',
'story',
123456,
{
query: { need_union_deliverable: true, need_schedule_table_agg: true },
body: {
expand: {
need_union_deliverable: true,
need_wbs_relation_chain_entity: true,
need_wbs_relation_chain_path: true,
},
},
},
{ auth: { type: 'plugin', userKey: 'user_key' } }
);Universal Search (Field Select)
const request = {
data_sources: [
{
project_key: 'project_key',
work_item_type_keys: 'story',
},
],
search_group: {
conjunction: 'AND',
search_params: [{ param_key: 'created_at', value: Date.now() - 86400000, operator: '>' }],
},
field_selected: ['work_item_id', 'name'],
pagination: { page_size: 20 },
};
const result = await client.workItem.search.universalSearch(request, {
auth: { type: 'plugin', userKey: 'user_key' },
});
// Next page
const next = await client.workItem.search.universalSearch(
{
...request,
pagination: { page_size: 20, search_after: result.pagination.search_after },
},
{ auth: { type: 'plugin', userKey: 'user_key' } }
);Services Overview
Top-level services:
authworkItemspaceuserconfigviewmeasuretenant
workItem sub-services:
search,batch,comment,subtask,attachment,chat,workflow
Tests
Integration tests use real credentials in tests/config.ts.
bun testNetwork access is required.
Unit Tests (Edge Cases)
Unit tests mock network calls and focus on request parsing, retries, and token caching.
bun test tests/unitPerformance Benchmarks (Local)
Quick micro-benchmarks for request parsing and big-int handling (no network).
bun run tests/perf/benchmark.ts