rotur-sdk 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +302 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# rotur-sdk
|
|
2
|
+
|
|
3
|
+
The official TypeScript SDK for the [Rotur](https://rotur.dev) platform. Covers auth, profiles, posts, credits, keys, groups, items, gifts, tokens, validators, status, files, cosmetics, push notifications, and more — all with full type safety.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install rotur-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { Rotur } from "rotur-sdk";
|
|
15
|
+
|
|
16
|
+
const rotur = new Rotur();
|
|
17
|
+
|
|
18
|
+
// Browser auth - opens the Rotur login popup
|
|
19
|
+
await rotur.login();
|
|
20
|
+
|
|
21
|
+
// Or provide a token you already have
|
|
22
|
+
const rotur = new Rotur({ token: "your-token-here" });
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API Reference
|
|
26
|
+
|
|
27
|
+
### Authentication
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
// Popup-based OAuth flow (browser only)
|
|
31
|
+
await rotur.login({ system: "my-app", timeout: 60_000 });
|
|
32
|
+
|
|
33
|
+
// Check current auth state
|
|
34
|
+
rotur.loggedIn; // boolean
|
|
35
|
+
rotur.token; // string | null
|
|
36
|
+
|
|
37
|
+
// Set/refresh token manually
|
|
38
|
+
rotur.setToken("new-token");
|
|
39
|
+
|
|
40
|
+
// Logout (clears token + disconnects socket)
|
|
41
|
+
rotur.logout();
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Link-based Auth (for CLI / server)
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
const code = await rotur.link.getCode();
|
|
48
|
+
console.log(`Visit https://rotur.dev/link and enter: ${code}`);
|
|
49
|
+
|
|
50
|
+
// Polls until the user links on the website
|
|
51
|
+
const token = await rotur.link.pollUntilLinked(code);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Profiles
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
const profile = await rotur.profiles.get("username");
|
|
58
|
+
const { exists } = await rotur.profiles.exists("username");
|
|
59
|
+
const avatarUrl = rotur.profiles.getAvatarUrl("username");
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Account (me)
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
await rotur.me.get();
|
|
66
|
+
await rotur.me.update("bio", "hello world");
|
|
67
|
+
await rotur.me.transfer("recipient", 100, "a note");
|
|
68
|
+
await rotur.me.claimDaily();
|
|
69
|
+
await rotur.me.badges();
|
|
70
|
+
await rotur.me.block("username");
|
|
71
|
+
await rotur.me.unblock("username");
|
|
72
|
+
await rotur.me.checkAuth();
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Posts
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
const post = await rotur.posts.create("Hello from the SDK!");
|
|
79
|
+
await rotur.posts.reply(post.id, "Nice post!");
|
|
80
|
+
await rotur.posts.like(post.id);
|
|
81
|
+
await rotur.posts.repost(post.id);
|
|
82
|
+
await rotur.posts.pin(post.id);
|
|
83
|
+
|
|
84
|
+
const feed = await rotur.posts.feed(100, 0);
|
|
85
|
+
const top = await rotur.posts.top(50, 24);
|
|
86
|
+
const results = await rotur.posts.search("query");
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Friends
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
const { friends } = await rotur.friends.list();
|
|
93
|
+
await rotur.friends.request("username");
|
|
94
|
+
await rotur.friends.accept("username");
|
|
95
|
+
await rotur.friends.remove("username");
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Following
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
await rotur.following.follow("username");
|
|
102
|
+
await rotur.following.unfollow("username");
|
|
103
|
+
const { followers } = await rotur.following.followers("username");
|
|
104
|
+
const { following } = await rotur.following.following("username");
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Keys
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
await rotur.keys.create("my-key", { price: 50, subscription: true });
|
|
111
|
+
const myKeys = await rotur.keys.mine();
|
|
112
|
+
const key = await rotur.keys.get("key-id");
|
|
113
|
+
const { owned } = await rotur.keys.check("username", "key-name");
|
|
114
|
+
await rotur.keys.buy("key-id");
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Items
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
const item = await rotur.items.create({ name: "sword", price: 100, selling: true });
|
|
121
|
+
const item = await rotur.items.get("sword");
|
|
122
|
+
const items = await rotur.items.list("username");
|
|
123
|
+
await rotur.items.buy("sword");
|
|
124
|
+
await rotur.items.sell("sword");
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Gifts
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
await rotur.gifts.create(500, { note: "Happy birthday!", expiresInHrs: 48 });
|
|
131
|
+
const { gift } = await rotur.gifts.get("code");
|
|
132
|
+
await rotur.gifts.claim("code");
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Tokens (sub-tokens / scoped access)
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
const { permissions, groups } = await rotur.tokens.permissions();
|
|
139
|
+
const { tokens } = await rotur.tokens.list();
|
|
140
|
+
|
|
141
|
+
const sub = await rotur.tokens.create("bot-token", [
|
|
142
|
+
"posts:view", "posts:create", "account:profile"
|
|
143
|
+
], { expiresInHrs: 24, origin: "my-app" });
|
|
144
|
+
|
|
145
|
+
await rotur.tokens.revoke(sub.id);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Groups
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
const group = await rotur.groups.create("devs", "Developers", {
|
|
152
|
+
description: "A group for devs",
|
|
153
|
+
public: true,
|
|
154
|
+
joinPolicy: "OPEN",
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
await rotur.groups.join("devs");
|
|
158
|
+
await rotur.groups.represent("devs");
|
|
159
|
+
const announcements = await rotur.groups.announcements("devs");
|
|
160
|
+
const roles = await rotur.groups.roles("devs");
|
|
161
|
+
await rotur.groups.assignRole("devs", userId, roleId);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Cosmetics
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
const shop = await rotur.cosmetics.shop({ sort: "newest", limit: 20 });
|
|
168
|
+
const mine = await rotur.cosmetics.mine();
|
|
169
|
+
await rotur.cosmetics.purchase("cosmetic-id");
|
|
170
|
+
await rotur.cosmetics.equip("cosmetic-id");
|
|
171
|
+
await rotur.cosmetics.unequip("hat");
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Files
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
const files = await rotur.files.index();
|
|
178
|
+
const { used, max } = await rotur.files.usage();
|
|
179
|
+
const file = await rotur.files.getByUUID("uuid");
|
|
180
|
+
const file = await rotur.files.getByPath("path/to/file");
|
|
181
|
+
await rotur.files.upload({ /* file data */ });
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Push Notifications
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
const { public_key } = await rotur.push.vapidKeys();
|
|
188
|
+
await rotur.push.register(endpoint, p256dh, auth, "my-app", "fingerprint");
|
|
189
|
+
const { endpoints } = await rotur.push.endpoints();
|
|
190
|
+
await rotur.push.send("username", "my-app", { title: "Hi!", body: "You have a message" });
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Status & Validators
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
const status = await rotur.status.get("username");
|
|
197
|
+
const { validator } = await rotur.validators.generate("key");
|
|
198
|
+
const result = await rotur.validators.validate(validator, "key");
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Standing, Stats, DevFund, Check
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
const standing = await rotur.standing.get("username");
|
|
205
|
+
const economy = await rotur.stats.economy();
|
|
206
|
+
await rotur.devfund.escrowTransfer(100, "petition-id");
|
|
207
|
+
const { banned } = await rotur.check.banned(["user1", "user2"]);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## WebSocket (Real-time)
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
// Connect after login
|
|
214
|
+
const { user_id, username } = await rotur.connectSocket();
|
|
215
|
+
|
|
216
|
+
// Join presence rooms
|
|
217
|
+
rotur.socket.join(["lobby", "chat"]);
|
|
218
|
+
|
|
219
|
+
// Listen for events
|
|
220
|
+
rotur.socket.on("member_join", (msg) => {
|
|
221
|
+
console.log(`${msg.username} joined ${msg.room}`);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
rotur.socket.on("status_update", (msg) => {
|
|
225
|
+
console.log(`${msg.username} is now ${msg.presence}`);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Set your own status
|
|
229
|
+
rotur.socket.setStatus("Building something cool", "online");
|
|
230
|
+
|
|
231
|
+
// Rich presence — "Playing" activity
|
|
232
|
+
rotur.socket.setPlaying("My Game", {
|
|
233
|
+
title: "Level 3",
|
|
234
|
+
status: "In-game",
|
|
235
|
+
url: "https://mygame.com",
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// "Listening to" activity
|
|
239
|
+
rotur.socket.setMusic("Spotify", {
|
|
240
|
+
title: "Song Name",
|
|
241
|
+
artist: "Artist",
|
|
242
|
+
album: "Album",
|
|
243
|
+
start: Date.now(),
|
|
244
|
+
end: Date.now() + 180_000,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Wildcard — receive every message
|
|
248
|
+
rotur.socket.on("*", (msg) => console.log(msg.cmd, msg));
|
|
249
|
+
|
|
250
|
+
// Disconnect
|
|
251
|
+
rotur.socket.disconnect();
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
The socket auto-reconnects with exponential backoff and sends heartbeats every 25s.
|
|
255
|
+
|
|
256
|
+
## Error Handling
|
|
257
|
+
|
|
258
|
+
```ts
|
|
259
|
+
import { ApiError, AuthError } from "rotur-sdk";
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
await rotur.me.transfer("user", 1000);
|
|
263
|
+
} catch (e) {
|
|
264
|
+
if (e instanceof ApiError) {
|
|
265
|
+
console.log(e.status); // HTTP status code
|
|
266
|
+
console.log(e.data); // response body
|
|
267
|
+
console.log(e.message); // human-readable error
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
try {
|
|
272
|
+
await rotur.login();
|
|
273
|
+
} catch (e) {
|
|
274
|
+
if (e instanceof AuthError) {
|
|
275
|
+
console.log(e.code); // "timeout" | "aborted" | "popup_blocked" | "no_token"
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Building
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
npm run build # build CJS + ESM + types via tsup
|
|
284
|
+
npm run dev # watch mode
|
|
285
|
+
npm run typecheck # tsc --noEmit
|
|
286
|
+
npm test # vitest
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Exports
|
|
290
|
+
|
|
291
|
+
| Export | Description |
|
|
292
|
+
|---|---|
|
|
293
|
+
| `Rotur` | Main client class |
|
|
294
|
+
| `RoturSocket` | WebSocket connection (real-time presence) |
|
|
295
|
+
| `ApiError` | HTTP error with `status` and `data` |
|
|
296
|
+
| `performAuth`, `AuthError` | Browser auth flow |
|
|
297
|
+
| `AuthOptions`, `AuthResult` | Auth option types |
|
|
298
|
+
| All types from `types.ts` | `UserProfile`, `NetPost`, `GroupPublic`, `WSMessage`, etc. |
|
|
299
|
+
|
|
300
|
+
## License
|
|
301
|
+
|
|
302
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rotur-sdk",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "The official SDK for the Rotur platform
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "The official SDK for the Rotur platform - auth, profiles, posts, credits, keys, groups, items, gifts, tokens, validators, status, files, cosmetics, push notifications, and more",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|