Official SDK — @wenex/sdk
The @wenex/sdk package is the official TypeScript/JavaScript client for the Wenex Platform. It wraps the REST API with typed methods, handles Brotli compression, and exposes RxJS-compatible patterns.
npm: @wenex/sdkVersion: 1.3.4 Repository: wenex-org/platform-sdk
Installation
npm install @wenex/sdk axios
# or
pnpm add @wenex/sdk axiosOptional: Brotli compression support (reduces network payload):
npm install @wenex/sdk axios brotli-wasmQuick Start
import axios from 'axios';
import { Platform } from '@wenex/sdk';
// 1. Create an axios instance configured for the gateway
const http = axios.create({
baseURL: 'http://localhost:3010',
headers: {
Authorization: `Bearer ${process.env.WENEX_TOKEN}`,
},
});
// 2. Build the Platform client
const platform = Platform.build(http);
// 3. Use any service
const users = await platform.identity.users.find({ query: {} });
console.log(users); // User[]Platform Class
Platform is the root client. It lazily instantiates service clients on first access.
class Platform {
// Service clients (lazily initialized)
get auth(): Auth.Client
get identity(): Identity.Client
get financial(): Financial.Client
get career(): Career.Client
get domain(): Domain.Client
get essential(): Essential.Client
get context(): Context.Client
get general(): General.Client
get special(): Special.Client
get touch(): Touch.Client
get content(): Content.Client
get logistic(): Logistic.Client
get conjoint(): Conjoint.Client
get thing(): Thing.Client
get graphql(): GraphqlService
static build(axios: AxiosInstance, prefix?: string): Platform
}The optional prefix parameter is prepended to all request paths (useful when the API is served under a sub-path).
Authentication
With a JWT
const http = axios.create({
baseURL: 'http://localhost:3010',
headers: { Authorization: `Bearer ${jwtToken}` },
});
const platform = Platform.build(http);With an APT (long-lived token)
const http = axios.create({
baseURL: 'http://localhost:3010',
headers: { Authorization: `Bearer ${aptToken}` },
});
const platform = Platform.build(http);Obtaining a token via the SDK
const platform = Platform.build(axios.create({ baseURL: 'http://localhost:3010' }));
const { access_token } = await platform.auth.auths.token({
username: 'admin@example.com',
password: 'Str0ng!Pass',
grant_type: 'password',
});
// Re-build with the token
const authedPlatform = Platform.build(
axios.create({
baseURL: 'http://localhost:3010',
headers: { Authorization: `Bearer ${access_token}` },
}),
);RestfulService Methods
Every collection (users, accounts, products, etc.) extends RestfulService, which provides these typed methods:
class RestfulService<T extends Core, D extends Dto<Core>> {
// Count documents matching a query
count(query: Query<T>, config?: RequestConfig<T>): Promise<number>
// Create one document
create(data: D, config?: RequestConfig<T>): Promise<Serializer<T>>
// Create many documents
createBulk(data: Items<D>, config?: RequestConfig<T>): Promise<Serializer<T>[]>
// Stream documents via SSE
cursor(filter: FilterOne<T>, options: FetchEventSourceInit, config?: RequestConfig<T>): Promise<void>
// Find documents with full filter support
find(filter: Filter<T>, config?: RequestConfig<T>): Promise<Serializer<T>[]>
// Find one document by ID
findById(id: string, config?: RequestConfig<T>): Promise<Serializer<T>>
// Update one document by ID
updateById(id: string, data: Optional<D>, config?: RequestConfig<T>): Promise<Serializer<T>>
// Update many documents matching a query
updateBulk(data: Optional<D>, query: Query<T>, config?: RequestConfig<T>): Promise<number>
// Soft-delete by ID
deleteById(id: string, config?: RequestConfig<T>): Promise<Serializer<T>>
// Restore a soft-deleted document
restoreById(id: string, config?: RequestConfig<T>): Promise<Serializer<T>>
// Hard-delete by ID (permanent)
destroyById(id: string, config?: RequestConfig<T>): Promise<Serializer<T>>
}RequestConfig Options
The config parameter is an extension of Axios AxiosRequestConfig:
interface RequestConfig<T> extends AxiosRequestConfig {
params?: {
zone?: 'own' | 'share' | 'group' | 'client' | string; // comma-separated
skip?: number;
limit?: number;
sort?: Pagination<T>['sort'];
[key: string]: any;
};
headers?: {
[k in keyof Metadata]?: string | number | boolean | null;
};
fullResponse?: boolean; // If true, returns the full axios response instead of unwrapped data
brotli?: { quality: number } | boolean; // Enable Brotli compression
}CRUD Examples
Identity — Users
const users = platform.identity.users;
// Count all users
const total = await users.count({});
console.log(`Total users: ${total}`);
// Count with filter
const activeCount = await users.count({ status: 'active' });
// Create a user
const newUser = await users.create({
username: 'jdoe',
email: 'jdoe@example.com',
password: 'Str0ng!Pass',
name: 'John Doe',
});
console.log(newUser.id);
// Create many users
const created = await users.createBulk({
items: [
{ username: 'alice', email: 'alice@example.com' },
{ username: 'bob', email: 'bob@example.com' },
],
});
// Find with filter and pagination
const page1 = await users.find({
query: { status: 'active' },
pagination: { limit: 20, skip: 0, sort: { created_at: -1 } },
projection: { username: 1, email: 1 },
});
// Find one by ID
const user = await users.findById('64a1b2c3d4e5f6a7b8c9d0e1');
// Update
const updated = await users.updateById('64a1b2c3d4e5f6a7b8c9d0e1', {
name: 'Jonathan Doe',
});
// Bulk update
const count = await users.updateBulk(
{ status: 'inactive' },
{ archived: true },
);
// Soft delete
const deleted = await users.deleteById('64a1b2c3d4e5f6a7b8c9d0e1');
// Restore
const restored = await users.restoreById('64a1b2c3d4e5f6a7b8c9d0e1');
// Hard delete (permanent — requires manage scope)
await users.destroyById('64a1b2c3d4e5f6a7b8c9d0e1');Financial — Transactions
const txns = platform.financial.transactions;
// Find completed transactions over $100 with account populated
const results = await txns.find({
query: { status: 'completed', amount: { $gte: 100 } },
populate: [{ path: 'account', select: ['name', 'balance'] }],
pagination: { limit: 50, skip: 0, sort: { created_at: -1 } },
});Auth — Token and Verify
const auth = platform.auth.auths;
// Get token
const { access_token } = await auth.token({
username: 'admin@example.com',
password: 'secret',
grant_type: 'password',
});
// Verify token
const claims = await auth.verify();
console.log(claims.sub, claims.scope);
// Check permission
const { can } = await auth.can({ action: 'read', resource: 'identity:users' });
// Logout
await auth.logout();Auth — APTs
const apts = platform.auth.apts;
// Create an APT
const apt = await apts.create({
name: 'my-bot',
scope: 'read:identity:users',
});
console.log(apt.token); // Store this — only shown once
// List APTs
const myApts = await apts.find({ query: {} });
// Revoke an APT
await apts.deleteById(apt.id);Streaming (Cursor)
import { fetchEventSource } from '@microsoft/fetch-event-source';
await platform.identity.users.cursor(
{ query: { status: 'active' } },
{
onmessage(event) {
if (event.event === 'end') {
console.log('Stream complete');
return;
}
const user = JSON.parse(event.data);
console.log('User:', user.id, user.username);
},
onerror(err) {
console.error(err);
throw err; // Re-throw to stop retries
},
},
);GraphQL via SDK
The SDK exposes a graphql client for executing raw GraphQL operations:
const gql = platform.graphql;
const result = await gql.query(`
query {
findIdentityUser(filter: { query: {} }) {
count
data { id username email }
}
}
`);
// With variables
const result2 = await gql.query(
`query FindById($id: String!) {
findIdentityUserById(id: $id) { data { id username email } }
}`,
{ id: '64a1b2c3d4e5f6a7b8c9d0e1' },
);Zone Filtering
Pass zone in config.params:
// My own documents only
const mine = await platform.identity.users.find(
{ query: {} },
{ params: { zone: 'own' } },
);
// Shared with me
const shared = await platform.identity.users.find(
{ query: {} },
{ params: { zone: 'own,share' } },
);Full Response Mode
By default the SDK unwraps the response envelope and returns the data directly. Set fullResponse: true to receive the raw Axios response:
const response = await platform.identity.users.find(
{ query: {} },
{ fullResponse: true },
);
// response.data = { data: [...], count: N }
// response.headers['etag'] = '"abc123"'Brotli Compression
Enable Brotli to compress request bodies (requires brotli-wasm peer dependency):
await platform.identity.users.create(
{ username: 'alice', email: 'alice@example.com' },
{ brotli: { quality: 6 } }, // quality 1–11
);
// Boolean shorthand (uses default quality)
await platform.identity.users.create(data, { brotli: true });Multi-Tenant Usage
Pass the x-domain header to scope requests to a specific tenant:
const tenantHttp = axios.create({
baseURL: 'http://localhost:3010',
headers: {
Authorization: `Bearer ${token}`,
'x-domain': 'tenant-a.example.com',
},
});
const tenantPlatform = Platform.build(tenantHttp);Or override per-request:
await platform.identity.users.find(
{ query: {} },
{ headers: { 'x-domain': 'tenant-b.example.com' } },
);TypeScript Tips
The Platform class accepts a generic Properties type parameter for extending entity types with custom properties:
interface MyUserProps {
preferredLanguage: string;
tier: 'free' | 'pro' | 'enterprise';
}
const platform = Platform.build<MyUserProps>(http);
// platform.identity.users.find() returns User<MyUserProps>[]
const users = await platform.identity.users.find({ query: {} });
users[0].props?.preferredLanguage; // typedService Client Reference
platform.X | Collections available |
|---|---|
platform.auth | .auths, .apts, .grants |
platform.identity | .users, .profiles, .sessions |
platform.financial | .accounts, .wallets, .invoices, .transactions, .currencies |
platform.career | .businesses, .branches, .employees, .products, .services, .stocks, .stores, .customers |
platform.domain | .apps, .clients |
platform.essential | .sagas, .sagaStages |
platform.context | .configs, .settings |
platform.general | .activities, .artifacts, .comments, .events, .workflows |
platform.special | .files, .stats |
platform.touch | .emails, .notices, .pushes, .sms, .histories |
platform.content | .notes, .posts, .tickets |
platform.logistic | .locations, .drivers, .vehicles, .travels, .cargoes |
platform.conjoint | .accounts, .channels, .contacts, .members, .messages |
platform.thing | .devices, .sensors, .metrics |