@unicitylabs/sphere-sdk 0.6.0 → 0.6.2
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 +8 -0
- package/dist/core/index.cjs +53 -11
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +37 -1
- package/dist/core/index.d.ts +37 -1
- package/dist/core/index.js +53 -11
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +28 -0
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +28 -0
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +28 -0
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +11 -0
- package/dist/impl/nodejs/index.d.ts +11 -0
- package/dist/impl/nodejs/index.js +28 -0
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +53 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +53 -11
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/dist/l1/index.d.cts +0 -717
- package/dist/l1/index.d.ts +0 -717
package/README.md
CHANGED
|
@@ -409,6 +409,12 @@ const privateGroup = await gc.createGroup({
|
|
|
409
409
|
visibility: GroupVisibility.PRIVATE,
|
|
410
410
|
});
|
|
411
411
|
|
|
412
|
+
// Create a write-restricted group (only admins/writers can post)
|
|
413
|
+
const announcements = await gc.createGroup({
|
|
414
|
+
name: 'Announcements',
|
|
415
|
+
writeRestricted: true,
|
|
416
|
+
});
|
|
417
|
+
|
|
412
418
|
// Discover and join
|
|
413
419
|
const available = await gc.fetchAvailableGroups(); // public groups on relay
|
|
414
420
|
await gc.joinGroup(group.id);
|
|
@@ -455,6 +461,7 @@ const members = gc.getMembers(group.id);
|
|
|
455
461
|
gc.isCurrentUserAdmin(group.id); // boolean
|
|
456
462
|
gc.isCurrentUserModerator(group.id); // boolean
|
|
457
463
|
await gc.canModerateGroup(group.id); // includes relay admin check
|
|
464
|
+
gc.canWriteToGroup(group.id); // false if write-restricted and not admin/moderator
|
|
458
465
|
|
|
459
466
|
// Moderate (requires admin/moderator role)
|
|
460
467
|
await gc.kickUser(group.id, userPubkey, 'reason');
|
|
@@ -487,6 +494,7 @@ interface GroupData {
|
|
|
487
494
|
name: string;
|
|
488
495
|
description?: string;
|
|
489
496
|
visibility: GroupVisibility; // 'PUBLIC' | 'PRIVATE'
|
|
497
|
+
writeRestricted?: boolean; // Only admins and moderators can post
|
|
490
498
|
memberCount?: number;
|
|
491
499
|
unreadCount?: number;
|
|
492
500
|
lastMessageTime?: number;
|
package/dist/core/index.cjs
CHANGED
|
@@ -8401,6 +8401,12 @@ var CommunicationsModule = class {
|
|
|
8401
8401
|
this.unsubscribeComposing = deps.transport.onComposing?.((indicator) => {
|
|
8402
8402
|
this.handleComposingIndicator(indicator);
|
|
8403
8403
|
}) ?? null;
|
|
8404
|
+
if (deps.transport.onChatReady) {
|
|
8405
|
+
deps.transport.onChatReady(() => {
|
|
8406
|
+
const conversations = this.getConversations();
|
|
8407
|
+
deps.emitEvent("communications:ready", { conversationCount: conversations.size });
|
|
8408
|
+
});
|
|
8409
|
+
}
|
|
8404
8410
|
}
|
|
8405
8411
|
/**
|
|
8406
8412
|
* Load messages from storage.
|
|
@@ -9043,6 +9049,7 @@ var GroupChatModule = class {
|
|
|
9043
9049
|
await this.subscribeToJoinedGroups();
|
|
9044
9050
|
}
|
|
9045
9051
|
this.deps.emitEvent("groupchat:connection", { connected: true });
|
|
9052
|
+
this.deps.emitEvent("groupchat:ready", { groupCount: this.groups.size });
|
|
9046
9053
|
} catch (error) {
|
|
9047
9054
|
logger.error("GroupChat", "Failed to connect to relays", error);
|
|
9048
9055
|
this.deps.emitEvent("groupchat:connection", { connected: false });
|
|
@@ -9161,17 +9168,23 @@ var GroupChatModule = class {
|
|
|
9161
9168
|
const group = this.groups.get(groupId);
|
|
9162
9169
|
if (!group) return;
|
|
9163
9170
|
if (event.kind === NIP29_KINDS.GROUP_METADATA) {
|
|
9164
|
-
if (
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9171
|
+
if (event.content && event.content.trim()) {
|
|
9172
|
+
try {
|
|
9173
|
+
const metadata = JSON.parse(event.content);
|
|
9174
|
+
group.name = metadata.name || group.name;
|
|
9175
|
+
group.description = metadata.about || group.description;
|
|
9176
|
+
group.picture = metadata.picture || group.picture;
|
|
9177
|
+
if (metadata["write-restricted"] === true) group.writeRestricted = true;
|
|
9178
|
+
else group.writeRestricted = void 0;
|
|
9179
|
+
} catch {
|
|
9180
|
+
}
|
|
9174
9181
|
}
|
|
9182
|
+
for (const tag of event.tags) {
|
|
9183
|
+
if (tag[0] === "write-restricted") group.writeRestricted = true;
|
|
9184
|
+
}
|
|
9185
|
+
group.updatedAt = event.created_at * 1e3;
|
|
9186
|
+
this.groups.set(groupId, group);
|
|
9187
|
+
this.persistGroups();
|
|
9175
9188
|
} else if (event.kind === NIP29_KINDS.GROUP_MEMBERS) {
|
|
9176
9189
|
this.updateMembersFromEvent(groupId, event);
|
|
9177
9190
|
} else if (event.kind === NIP29_KINDS.GROUP_ADMINS) {
|
|
@@ -9475,7 +9488,8 @@ var GroupChatModule = class {
|
|
|
9475
9488
|
picture: options.picture,
|
|
9476
9489
|
closed: true,
|
|
9477
9490
|
private: isPrivate,
|
|
9478
|
-
hidden: isPrivate
|
|
9491
|
+
hidden: isPrivate,
|
|
9492
|
+
...options.writeRestricted ? { "write-restricted": true } : {}
|
|
9479
9493
|
})
|
|
9480
9494
|
});
|
|
9481
9495
|
if (!eventId) return null;
|
|
@@ -9670,6 +9684,19 @@ var GroupChatModule = class {
|
|
|
9670
9684
|
getMessages(groupId) {
|
|
9671
9685
|
return (this.messages.get(groupId) || []).sort((a, b) => a.timestamp - b.timestamp);
|
|
9672
9686
|
}
|
|
9687
|
+
getMessagesPage(groupId, options) {
|
|
9688
|
+
const limit = options?.limit ?? 20;
|
|
9689
|
+
const before = options?.before ?? Infinity;
|
|
9690
|
+
const groupMessages = this.messages.get(groupId) ?? [];
|
|
9691
|
+
const filtered = groupMessages.filter((m) => m.timestamp < before).sort((a, b) => b.timestamp - a.timestamp);
|
|
9692
|
+
const page = filtered.slice(0, limit);
|
|
9693
|
+
return {
|
|
9694
|
+
messages: page.reverse(),
|
|
9695
|
+
// chronological order
|
|
9696
|
+
hasMore: filtered.length > limit,
|
|
9697
|
+
oldestTimestamp: page.length > 0 ? page[0].timestamp : null
|
|
9698
|
+
};
|
|
9699
|
+
}
|
|
9673
9700
|
getMembers(groupId) {
|
|
9674
9701
|
return (this.members.get(groupId) || []).sort((a, b) => a.joinedAt - b.joinedAt);
|
|
9675
9702
|
}
|
|
@@ -9776,6 +9803,17 @@ var GroupChatModule = class {
|
|
|
9776
9803
|
const admins = await this.fetchRelayAdmins();
|
|
9777
9804
|
return admins.has(myPubkey);
|
|
9778
9805
|
}
|
|
9806
|
+
/**
|
|
9807
|
+
* Check if current user can write messages to a group.
|
|
9808
|
+
* For write-restricted groups, only admins/moderators can post.
|
|
9809
|
+
* For normal groups, any member can post.
|
|
9810
|
+
*/
|
|
9811
|
+
canWriteToGroup(groupId) {
|
|
9812
|
+
const group = this.groups.get(groupId);
|
|
9813
|
+
if (!group) return false;
|
|
9814
|
+
if (!group.writeRestricted) return true;
|
|
9815
|
+
return this.isCurrentUserModerator(groupId);
|
|
9816
|
+
}
|
|
9779
9817
|
getCurrentUserRole(groupId) {
|
|
9780
9818
|
const myPubkey = this.getMyPublicKey();
|
|
9781
9819
|
if (!myPubkey) return null;
|
|
@@ -10150,6 +10188,7 @@ var GroupChatModule = class {
|
|
|
10150
10188
|
let description;
|
|
10151
10189
|
let picture;
|
|
10152
10190
|
let isPrivate = false;
|
|
10191
|
+
let writeRestricted = false;
|
|
10153
10192
|
if (event.content && event.content.trim()) {
|
|
10154
10193
|
try {
|
|
10155
10194
|
const metadata = JSON.parse(event.content);
|
|
@@ -10157,6 +10196,7 @@ var GroupChatModule = class {
|
|
|
10157
10196
|
description = metadata.about || metadata.description;
|
|
10158
10197
|
picture = metadata.picture;
|
|
10159
10198
|
isPrivate = metadata.private === true;
|
|
10199
|
+
if (metadata["write-restricted"] === true) writeRestricted = true;
|
|
10160
10200
|
} catch {
|
|
10161
10201
|
}
|
|
10162
10202
|
}
|
|
@@ -10166,6 +10206,7 @@ var GroupChatModule = class {
|
|
|
10166
10206
|
if (tag[0] === "picture" && tag[1]) picture = tag[1];
|
|
10167
10207
|
if (tag[0] === "private") isPrivate = true;
|
|
10168
10208
|
if (tag[0] === "public" && tag[1] === "false") isPrivate = true;
|
|
10209
|
+
if (tag[0] === "write-restricted") writeRestricted = true;
|
|
10169
10210
|
}
|
|
10170
10211
|
return {
|
|
10171
10212
|
id: groupId,
|
|
@@ -10174,6 +10215,7 @@ var GroupChatModule = class {
|
|
|
10174
10215
|
description,
|
|
10175
10216
|
picture,
|
|
10176
10217
|
visibility: isPrivate ? GroupVisibility.PRIVATE : GroupVisibility.PUBLIC,
|
|
10218
|
+
writeRestricted: writeRestricted || void 0,
|
|
10177
10219
|
createdAt: event.created_at * 1e3
|
|
10178
10220
|
};
|
|
10179
10221
|
} catch {
|