@ours.network/notifications 1.0.1 → 1.0.3-nightly.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 +1 -1
- package/dist/server.js +4 -1
- package/dist/store.d.ts +3 -1
- package/dist/store.js +5 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ Responses are never cached. User and producer credentials have separate scopes.
|
|
|
55
55
|
| POST `/api/v1/devices` | User | `{ "subscription": PushSubscriptionJSON }` → device `id` |
|
|
56
56
|
| POST `/api/v1/devices/delete` | User | `{ "id": "device-id" }`, only that user's device |
|
|
57
57
|
| GET `/api/v1/devices/status?id=...` | User | `{ "active": true }` |
|
|
58
|
-
| GET `/api/v1/inbox?limit=50&before
|
|
58
|
+
| GET `/api/v1/inbox?limit=50&before=...&unread=true` | User | Items, shared unread count, revision, next cursor; with `unread=true` only unread items and `filter: "unread"` |
|
|
59
59
|
| GET `/api/v1/unread-evidence?target=TARGET_JSON[&target=ALIAS_JSON]&revision=OBSERVED_REVISION&limit=100&after=...` | User | Capability `unread-evidence/1`: one conversation's records created at or before the observed revision and still unread, oldest first (limit 1-200). A record read since that revision is absent, so a caller comparing with that revision's count sees it as incomplete. Items omit title and body. A cursor whose record was deleted, or that this scope and revision could not have returned, answers 409. Services without the route answer 404 |
|
|
60
60
|
| GET `/api/v1/summary` | User | Shared unread count, revision, per-chat source/identity/count, and `sections: {chats, tasks}`; mission-associated rows (task and room targets, or any row with a `taskId`) count under `chats`, agent rows without a `taskId` field count in neither section (as before), and `tasks` is always 0 (kept for compatibility) |
|
|
61
61
|
| POST `/api/v1/read-target` | User | `{ "target": { "kind": "agent", "agentId": "agent" }, "revision": OBSERVED_REVISION }`, reads only this chat up to the revision captured before its history load |
|
package/dist/server.js
CHANGED
|
@@ -134,7 +134,10 @@ export function createNotificationService(config, send) {
|
|
|
134
134
|
const limit = Number(url.searchParams.get('limit') ?? 50);
|
|
135
135
|
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
136
136
|
throw new HttpError(400, 'invalid limit');
|
|
137
|
-
|
|
137
|
+
const unread = url.searchParams.get('unread');
|
|
138
|
+
if (unread !== null && unread !== 'true' && unread !== 'false')
|
|
139
|
+
throw new HttpError(400, 'invalid unread filter');
|
|
140
|
+
result = store.inbox(user, url.searchParams.get('before') ?? undefined, limit, unread === 'true');
|
|
138
141
|
}
|
|
139
142
|
else if (req.method === 'GET' && url.pathname === '/api/v1/unread-evidence') {
|
|
140
143
|
// Capability `unread-evidence/1`: a separate route, so a service without it answers
|
package/dist/store.d.ts
CHANGED
|
@@ -74,7 +74,9 @@ export declare class Store {
|
|
|
74
74
|
deleteDevice(userId: string, id: string): boolean;
|
|
75
75
|
device(userId: string, id: string): Device | undefined;
|
|
76
76
|
deviceStatus(userId: string, id: string): boolean;
|
|
77
|
-
|
|
77
|
+
/** Newest first. With `unread`, only unread records; the cursor may name a record that has been read since. */
|
|
78
|
+
inbox(userId: string, before?: string, limit?: number, unread?: boolean): {
|
|
79
|
+
filter?: "unread" | undefined;
|
|
78
80
|
items: Notification[];
|
|
79
81
|
unread: number;
|
|
80
82
|
revision: number;
|
package/dist/store.js
CHANGED
|
@@ -313,14 +313,16 @@ export class Store {
|
|
|
313
313
|
}
|
|
314
314
|
device(userId, id) { const d = this.state.devices.find(d => d.id === id && d.userId === userId); return d ? structuredClone(d) : undefined; }
|
|
315
315
|
deviceStatus(userId, id) { return this.state.devices.some(d => d.id === id && d.userId === userId); }
|
|
316
|
-
|
|
316
|
+
/** Newest first. With `unread`, only unread records; the cursor may name a record that has been read since. */
|
|
317
|
+
inbox(userId, before, limit = 50, unread = false) {
|
|
317
318
|
const all = this.state.notifications.filter(n => n.userId === userId);
|
|
318
319
|
const index = before ? all.findIndex(n => n.id === before) : all.length;
|
|
319
320
|
if (index < 0)
|
|
320
321
|
throw new HttpError(400, 'invalid cursor');
|
|
321
|
-
const
|
|
322
|
+
const older = unread ? all.slice(0, index).filter(n => !n.readAt) : all.slice(0, index);
|
|
323
|
+
const items = older.slice(Math.max(0, older.length - limit)).reverse();
|
|
322
324
|
return { items, unread: all.filter(n => !n.readAt).length, revision: this.state.revision,
|
|
323
|
-
nextCursor:
|
|
325
|
+
nextCursor: older.length > limit ? items.at(-1)?.id : null, ...(unread ? { filter: 'unread' } : {}) };
|
|
324
326
|
}
|
|
325
327
|
/**
|
|
326
328
|
* One conversation's unread evidence as of an observed revision, oldest first.
|