@sayrio/public 0.1.4 → 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 +250 -77
- package/dist/index.cjs +371 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +184 -59
- package/dist/index.d.ts +184 -59
- package/dist/index.js +365 -68
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +483 -81
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +32 -6
- package/dist/react/index.d.ts +32 -6
- package/dist/react/index.js +490 -88
- package/dist/react/index.js.map +1 -1
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
# @sayrio/public
|
|
3
2
|
|
|
4
3
|
Public JavaScript & TypeScript SDK for **Sayr.io**.
|
|
@@ -7,167 +6,315 @@ real‑time updates via WebSockets.
|
|
|
7
6
|
|
|
8
7
|
- ✅ REST + WebSocket
|
|
9
8
|
- ✅ Browser‑safe
|
|
10
|
-
- ✅ TypeScript
|
|
11
|
-
- ✅ React hooks included (`/react`)
|
|
9
|
+
- ✅ TypeScript‑first
|
|
12
10
|
- ✅ Zero runtime dependencies
|
|
11
|
+
- ✅ Versioned API (`v1`)
|
|
12
|
+
- ✅ Consistent `ApiResult<T>` responses
|
|
13
|
+
|
|
14
|
+
> React hooks are available via the **`@sayrio/public/react`** sub‑path export.
|
|
13
15
|
|
|
14
16
|
---
|
|
15
17
|
|
|
16
18
|
## Installation
|
|
17
19
|
|
|
18
|
-
Install the public Sayr SDK using your preferred package manager:
|
|
19
|
-
|
|
20
20
|
```bash
|
|
21
21
|
npm install @sayrio/public
|
|
22
22
|
```
|
|
23
|
+
|
|
23
24
|
or
|
|
25
|
+
|
|
24
26
|
```bash
|
|
25
27
|
pnpm add @sayrio/public
|
|
26
28
|
```
|
|
27
29
|
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Core Concepts
|
|
33
|
+
|
|
34
|
+
### ✅ `ApiResult<T>`
|
|
35
|
+
|
|
36
|
+
All SDK methods return a **non‑throwing** result object:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
interface ApiResult<T> {
|
|
40
|
+
success: boolean;
|
|
41
|
+
data: T | null;
|
|
42
|
+
error: string | null;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Always check `success` before accessing `data`.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
28
50
|
## Usage
|
|
29
51
|
|
|
30
52
|
### Basic Usage (REST)
|
|
31
53
|
|
|
32
|
-
Fetch public organization
|
|
54
|
+
Fetch a public organization.
|
|
55
|
+
|
|
56
|
+
`Sayr.org` is an alias for the latest API version (`v1`).
|
|
33
57
|
|
|
34
58
|
```ts
|
|
35
59
|
import Sayr from "@sayrio/public";
|
|
36
60
|
|
|
37
|
-
const
|
|
61
|
+
const res = await Sayr.org.get("acme");
|
|
38
62
|
|
|
39
|
-
|
|
63
|
+
if (!res.success) {
|
|
64
|
+
console.error(res.error);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
console.log(res.data.name);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
You can also use the versioned API explicitly:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const res = await Sayr.v1.org.get("acme");
|
|
40
75
|
```
|
|
41
76
|
|
|
42
77
|
---
|
|
43
78
|
|
|
44
|
-
|
|
79
|
+
## Organizations
|
|
45
80
|
|
|
46
|
-
|
|
81
|
+
### Fetch an Organization
|
|
47
82
|
|
|
48
83
|
```ts
|
|
49
|
-
const
|
|
50
|
-
await Sayr.org.tasks("acme", {
|
|
51
|
-
order: "desc",
|
|
52
|
-
limit: 10
|
|
53
|
-
});
|
|
84
|
+
const res = await Sayr.org.get("acme");
|
|
54
85
|
|
|
55
|
-
|
|
86
|
+
if (res.success) {
|
|
87
|
+
console.log(res.data);
|
|
88
|
+
}
|
|
56
89
|
```
|
|
57
90
|
|
|
58
91
|
---
|
|
59
92
|
|
|
60
|
-
|
|
93
|
+
## Tasks
|
|
61
94
|
|
|
62
|
-
|
|
95
|
+
### List Tasks (Paginated)
|
|
63
96
|
|
|
64
97
|
```ts
|
|
65
|
-
const
|
|
66
|
-
|
|
98
|
+
const res = await Sayr.org.tasks.list("acme", {
|
|
99
|
+
order: "desc",
|
|
100
|
+
limit: 10,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (!res.success) return;
|
|
104
|
+
|
|
105
|
+
res.data.items.forEach((task) => {
|
|
106
|
+
console.log(task.title);
|
|
107
|
+
});
|
|
67
108
|
|
|
68
|
-
console.log(
|
|
109
|
+
console.log(res.data.pagination);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Returned shape:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
ApiResult<{
|
|
116
|
+
items: Task[];
|
|
117
|
+
pagination: Pagination;
|
|
118
|
+
}>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### Fetch a Single Task
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
const res = await Sayr.org.tasks.get("acme", 42);
|
|
127
|
+
|
|
128
|
+
if (res.success) {
|
|
129
|
+
console.log(res.data.title);
|
|
130
|
+
}
|
|
69
131
|
```
|
|
70
132
|
|
|
71
133
|
---
|
|
72
134
|
|
|
73
|
-
|
|
135
|
+
## Comments
|
|
74
136
|
|
|
75
|
-
|
|
137
|
+
### List Task Comments (Paginated)
|
|
76
138
|
|
|
77
139
|
```ts
|
|
78
|
-
Sayr.
|
|
79
|
-
[Sayr.wsTypes.UPDATE_ORG]: (data) => {
|
|
80
|
-
console.log("Organization updated", data);
|
|
81
|
-
},
|
|
140
|
+
const res = await Sayr.org.comments.list("acme", 42);
|
|
82
141
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
142
|
+
if (!res.success) return;
|
|
143
|
+
|
|
144
|
+
res.data.items.forEach((comment) => {
|
|
145
|
+
console.log(comment.contentMarkdown);
|
|
86
146
|
});
|
|
87
147
|
```
|
|
88
148
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
149
|
+
Returned shape:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
ApiResult<{
|
|
153
|
+
items: Comment[];
|
|
154
|
+
pagination: Pagination;
|
|
155
|
+
}>
|
|
156
|
+
```
|
|
94
157
|
|
|
95
158
|
---
|
|
96
159
|
|
|
97
|
-
##
|
|
160
|
+
## Labels & Categories
|
|
161
|
+
|
|
162
|
+
### Labels
|
|
98
163
|
|
|
99
|
-
|
|
164
|
+
```ts
|
|
165
|
+
const res = await Sayr.org.labels.list("acme");
|
|
166
|
+
|
|
167
|
+
if (res.success) {
|
|
168
|
+
console.log(res.data);
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Categories
|
|
100
173
|
|
|
101
174
|
```ts
|
|
102
|
-
|
|
175
|
+
const res = await Sayr.org.categories.list("acme", "desc");
|
|
176
|
+
|
|
177
|
+
if (res.success) {
|
|
178
|
+
console.log(res.data);
|
|
179
|
+
}
|
|
103
180
|
```
|
|
104
181
|
|
|
105
182
|
---
|
|
106
183
|
|
|
107
|
-
|
|
184
|
+
## Authenticated User (`/me`)
|
|
185
|
+
|
|
186
|
+
The `/me` namespace provides **read‑only access** to the currently
|
|
187
|
+
authenticated user.
|
|
108
188
|
|
|
109
|
-
|
|
189
|
+
> Authentication is required
|
|
190
|
+
> Set a token using `Sayr.client.setToken(...)`.
|
|
110
191
|
|
|
111
|
-
|
|
112
|
-
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### Set Token
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
Sayr.client.setToken("********");
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
### Fetch Current User
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
const res = await Sayr.me.get();
|
|
206
|
+
|
|
207
|
+
if (res.success) {
|
|
208
|
+
console.log(res.data.email);
|
|
209
|
+
}
|
|
113
210
|
```
|
|
114
211
|
|
|
115
212
|
---
|
|
116
213
|
|
|
117
|
-
###
|
|
214
|
+
### List Your Organizations
|
|
118
215
|
|
|
119
|
-
|
|
216
|
+
```ts
|
|
217
|
+
const res = await Sayr.me.organizations();
|
|
120
218
|
|
|
121
|
-
|
|
122
|
-
|
|
219
|
+
if (res.success) {
|
|
220
|
+
console.log(res.data);
|
|
221
|
+
}
|
|
123
222
|
```
|
|
124
223
|
|
|
125
224
|
---
|
|
126
225
|
|
|
127
|
-
|
|
226
|
+
## Real‑Time Updates (WebSocket)
|
|
128
227
|
|
|
129
|
-
|
|
228
|
+
Subscribe to public real‑time events using WebSockets:
|
|
130
229
|
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
);
|
|
230
|
+
```ts
|
|
231
|
+
Sayr.ws(org.wsUrl, {
|
|
232
|
+
[Sayr.WS_EVENTS.UPDATE_TASK]: (data) => {
|
|
233
|
+
console.log("Task updated", data);
|
|
234
|
+
},
|
|
235
|
+
});
|
|
137
236
|
```
|
|
138
237
|
|
|
139
|
-
|
|
238
|
+
### WebSocket Features
|
|
239
|
+
|
|
240
|
+
- Automatic reconnection
|
|
241
|
+
- Heartbeat support (PING / PONG)
|
|
242
|
+
- Typed event constants
|
|
243
|
+
- Public‑safe payloads only
|
|
140
244
|
|
|
141
245
|
---
|
|
142
246
|
|
|
143
247
|
## Browser Usage (No Bundler)
|
|
144
248
|
|
|
145
|
-
The SDK can be used directly in the browser via ESM:
|
|
146
|
-
|
|
147
249
|
```html
|
|
148
250
|
<script type="module">
|
|
149
251
|
import Sayr from "https://esm.sh/@sayrio/public";
|
|
150
252
|
|
|
151
|
-
const
|
|
152
|
-
|
|
253
|
+
const res = await Sayr.org.get("acme");
|
|
254
|
+
|
|
255
|
+
if (res.success) {
|
|
256
|
+
console.log(res.data);
|
|
257
|
+
}
|
|
153
258
|
</script>
|
|
154
259
|
```
|
|
155
260
|
|
|
156
261
|
---
|
|
157
262
|
|
|
158
|
-
## API
|
|
263
|
+
## API Overview
|
|
264
|
+
|
|
265
|
+
### `Sayr.org` (latest)
|
|
266
|
+
|
|
267
|
+
Alias for `Sayr.v1.org`.
|
|
268
|
+
|
|
269
|
+
#### Organization
|
|
270
|
+
|
|
271
|
+
| Method | Description |
|
|
272
|
+
| ----------- | --------------------------- |
|
|
273
|
+
| `get(slug)` | Fetch a public organization |
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
#### Tasks
|
|
278
|
+
|
|
279
|
+
| Method | Description |
|
|
280
|
+
| -------------------------- | ---------------------- |
|
|
281
|
+
| `tasks.list(slug, opts?)` | List tasks (paginated) |
|
|
282
|
+
| `tasks.get(slug, shortId)` | Fetch a single task |
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
#### Comments
|
|
287
|
+
|
|
288
|
+
| Method | Description |
|
|
289
|
+
| ------------------------------------- | ------------------------ |
|
|
290
|
+
| `comments.list(slug, shortId, opts?)` | List task comments |
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
#### Labels
|
|
295
|
+
|
|
296
|
+
| Method | Description |
|
|
297
|
+
| ------------------- | ------------------------ |
|
|
298
|
+
| `labels.list(slug)` | List organization labels |
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
#### Categories
|
|
159
303
|
|
|
160
|
-
|
|
304
|
+
| Method | Description |
|
|
305
|
+
| ------------------------------- | --------------- |
|
|
306
|
+
| `categories.list(slug, order?)` | List categories |
|
|
161
307
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
| `labels(slug)` | List organization labels |
|
|
166
|
-
| `categories(slug, order?)` | List categories |
|
|
167
|
-
| `tasks(slug, opts?)` | List tasks (paginated) |
|
|
168
|
-
| `task(slug, shortId)` | Fetch a single task |
|
|
169
|
-
| `comments(slug, shortId, opts?)` | List task comments |
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
### `Sayr.me`
|
|
170
311
|
|
|
312
|
+
Authenticated user endpoints.
|
|
313
|
+
|
|
314
|
+
| Method | Description |
|
|
315
|
+
| ----------------- | -------------------------------------- |
|
|
316
|
+
| `get()` | Fetch the authenticated user |
|
|
317
|
+
| `organizations()` | List organizations the user belongs to |
|
|
171
318
|
|
|
172
319
|
---
|
|
173
320
|
|
|
@@ -177,22 +324,23 @@ Create a WebSocket connection for public events:
|
|
|
177
324
|
|
|
178
325
|
```ts
|
|
179
326
|
const conn = Sayr.ws(wsUrl, {
|
|
180
|
-
UPDATE_TASK: () => {}
|
|
327
|
+
UPDATE_TASK: () => {},
|
|
181
328
|
});
|
|
182
329
|
|
|
183
|
-
// Close the connection when no longer needed
|
|
184
330
|
conn.close();
|
|
185
331
|
```
|
|
186
332
|
|
|
187
333
|
---
|
|
188
334
|
|
|
189
|
-
### `
|
|
335
|
+
### `WS_EVENTS`
|
|
336
|
+
|
|
337
|
+
Typed WebSocket event constants:
|
|
190
338
|
|
|
191
339
|
```ts
|
|
192
|
-
Sayr.
|
|
193
|
-
Sayr.
|
|
194
|
-
Sayr.
|
|
195
|
-
|
|
340
|
+
Sayr.WS_EVENTS.CREATE_TASK;
|
|
341
|
+
Sayr.WS_EVENTS.UPDATE_TASK;
|
|
342
|
+
Sayr.WS_EVENTS.UPDATE_TASK_COMMENTS;
|
|
343
|
+
Sayr.WS_EVENTS.ERROR;
|
|
196
344
|
```
|
|
197
345
|
|
|
198
346
|
---
|
|
@@ -202,5 +350,30 @@ Sayr.wsTypes.ERROR
|
|
|
202
350
|
This package ships with full TypeScript definitions:
|
|
203
351
|
|
|
204
352
|
```ts
|
|
205
|
-
import type {
|
|
353
|
+
import type {
|
|
354
|
+
Organization,
|
|
355
|
+
Task,
|
|
356
|
+
Comment,
|
|
357
|
+
Label,
|
|
358
|
+
Category,
|
|
359
|
+
} from "@sayrio/public";
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## React Hooks
|
|
365
|
+
|
|
366
|
+
React bindings are available via:
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
import {
|
|
370
|
+
useOrg,
|
|
371
|
+
useTasks,
|
|
372
|
+
useTask,
|
|
373
|
+
useComments,
|
|
374
|
+
} from "@sayrio/public/react";
|
|
206
375
|
```
|
|
376
|
+
|
|
377
|
+
See **`@sayrio/public/react` README** for full hook documentation.
|
|
378
|
+
|
|
379
|
+
---
|