Skip to content

Commit 09c18a0

Browse files
authored
Merge pull request #145 from solid-contrib/feat/chat-ldo
Feat/chat ldo
2 parents d8aebc5 + bb8ec83 commit 09c18a0

26 files changed

+12354
-0
lines changed

.,

Whitespace-only changes.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Chats LDO CI/CD
2+
3+
on:
4+
push:
5+
paths:
6+
- chats/ldo/**
7+
- .github/workflows/chats-ldo-ci-cd.yml
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
defaults:
13+
run:
14+
working-directory: ./chats/ldo/
15+
strategy:
16+
matrix:
17+
node-version: [ 20 ]
18+
steps:
19+
- uses: actions/checkout@v3
20+
- name: Use Node.js ${{ matrix.node-version }}
21+
uses: actions/setup-node@v3
22+
with:
23+
node-version: ${{ matrix.node-version }}
24+
25+
- run: npm ci
26+
- run: npm run build
27+
- run: npm test
28+
29+
npm-publish:
30+
if: github.ref == 'refs/heads/main'
31+
needs: build
32+
runs-on: ubuntu-latest
33+
outputs:
34+
prereleaseVersion: ${{ steps.prerelease.outputs.version }}
35+
steps:
36+
- uses: actions/download-artifact@v4
37+
with:
38+
name: build
39+
- uses: actions/setup-node@v3
40+
with:
41+
node-version: lts/*
42+
- uses: rlespinasse/github-slug-action@v4.4.1
43+
- name: prerelease version
44+
run: |
45+
echo "::set-output name=version::$(npm version prerelease --preid ${GITHUB_SHA_SHORT} --no-git-tag-version)"
46+
id: prerelease
47+
- run: echo prerelease version is ${{ steps.prerelease.outputs.version }}
48+
- uses: JS-DevTools/npm-publish@v3
49+
name: Publish @solid-data-modules/chats-ldo
50+
with:
51+
token: ${{ secrets.NPM_TOKEN }}
52+
tag: ${{ env.GITHUB_REF_SLUG }}
53+
access: public
54+
55+
npm-release-latest:
56+
if: github.ref == 'refs/heads/main'
57+
needs: build
58+
runs-on: ubuntu-latest
59+
steps:
60+
- uses: actions/download-artifact@v4
61+
with:
62+
name: build
63+
- uses: actions/setup-node@v3
64+
with:
65+
node-version: lts/*
66+
- uses: JS-DevTools/npm-publish@v3
67+
name: Release @solid-data-modules/chats-ldo
68+
with:
69+
token: ${{ secrets.NPM_TOKEN }}
70+
tag: latest
71+
access: public

chats/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
Currently the following implementations for Chat data modules exist:
1010

1111
- [rdflib](./rdflib)
12+
- [ldo](./ldo)

chats/ldo/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
dist
3+
coverage

chats/ldo/README.md

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
# Chats - Data Module (LDO)
2+
3+
A chat module for Solid written with LDO.
4+
5+
## Installation
6+
7+
To install this library, use npm:
8+
9+
```bash
10+
npm install @solid-data-modules/chats-ldo @ldo/connected-solid @ldo/connected @ldo/ldo
11+
```
12+
13+
## Usage
14+
15+
Here's how you can use the @solid-data-modules/chats-ldo library to manage chats in a Solid Pod.
16+
Importing
17+
18+
First, import the necessary components from the library:
19+
```TypeScript
20+
21+
import { Chat, ChatShape } from "@solid-data-modules/chats-ldo";
22+
import { createSolidLdoDataset, SolidConnectedPlugin } from "@ldo/connected-solid";
23+
import { ConnectedLdoDataset } from "@ldo/connected";
24+
```
25+
26+
### Initialization
27+
28+
You'll need to create a SolidLdoDataset instance. This dataset will be used to interact with Solid Pods.
29+
30+
```TypeScript
31+
const dataset: ConnectedLdoDataset<SolidConnectedPlugin[]> = createSolidLdoDataset();
32+
```
33+
34+
### Creating a Chat Instance
35+
36+
To work with a chat, create an instance of the Chat class by providing the container URI where the chat data is or will be stored, and the dataset instance.
37+
38+
```TypeScript
39+
const chatContainerUri = "http://localhost:3003/your-chat-container/"; // Replace with your chat container URI
40+
const chat = new Chat(chatContainerUri, dataset);
41+
```
42+
43+
### Creating a New Chat on a Pod
44+
45+
If the chat doesn't exist yet, you can create it.
46+
47+
```TypeScript
48+
const webId = "http://example.com/profile/card#me"; // Replace with the author's WebID
49+
50+
async function initializeChat() {
51+
try {
52+
const newChatInfo: ChatShape = {
53+
"@id": `${chatContainerUri}index.ttl#this`, // Optional: specify the ID of the chat resource
54+
type: { "@id": "LongChat" }, // Specifies the type of chat
55+
author: { "@id": webId },
56+
created: new Date().toISOString(),
57+
title: "My Awesome Chat",
58+
};
59+
await chat.createChat(newChatInfo);
60+
console.log("Chat created successfully!");
61+
} catch (error) {
62+
console.error("Error creating chat:", error);
63+
}
64+
}
65+
66+
initializeChat();
67+
```
68+
69+
For the ChatShape properties like type and author, you typically provide an object with an @id property pointing to the respective RDF term or WebID.
70+
71+
### Getting Chat Information
72+
73+
You can retrieve the information of an existing chat.
74+
75+
```TypeScript
76+
async function logChatInfo() {
77+
try {
78+
const chatInfo = await chat.getChatInfo();
79+
console.log("Chat Title:", chatInfo.title);
80+
console.log("Chat Author:", chatInfo.author?.["@id"]);
81+
console.log("Chat Created:", chatInfo.created);
82+
} catch (error) {
83+
console.error("Error getting chat info:", error);
84+
}
85+
}
86+
87+
logChatInfo();
88+
```
89+
90+
### Updating Chat Information
91+
92+
You can update the properties of a chat.
93+
94+
```TypeScript
95+
async function updateChatTitle() {
96+
try {
97+
await chat.setChatInfo({
98+
title: "My Updated Awesome Chat",
99+
});
100+
console.log("Chat title updated!");
101+
const updatedInfo = await chat.getChatInfo();
102+
console.log("New Chat Title:", updatedInfo.title);
103+
} catch (error) {
104+
console.error("Error updating chat info:", error);
105+
}
106+
}
107+
108+
updateChatTitle();
109+
```
110+
111+
### Sending a Message
112+
113+
Send a new message to the chat.
114+
115+
```TypeScript
116+
async function postMessage() {
117+
try {
118+
const senderWebId = "[http://example.com/another-profile/card#me](http://example.com/another-profile/card#me)"; // Replace with sender's WebID
119+
await chat.sendMessage("Hello Solid World!", senderWebId);
120+
console.log("Message sent!");
121+
} catch (error) {
122+
console.error("Error sending message:", error);
123+
}
124+
}
125+
126+
postMessage();
127+
```
128+
129+
### Iterating Through Messages
130+
131+
You can iterate through the messages in a chat. The iterator returns messages in groups, typically by the day they were posted, from most recent to oldest.
132+
133+
```TypeScript
134+
async function readMessages() {
135+
try {
136+
const messageIterator = chat.getMessageIterator();
137+
console.log("Chat Messages (most recent first):");
138+
for await (const messageGroup of messageIterator) {
139+
// Messages in messageGroup are sorted from most recent to least recent for that specific day/resource
140+
messageGroup.forEach(message => {
141+
console.log(`- [${message.created2}] ${message.maker?.["@id"]}: ${message.content}`);
142+
});
143+
}
144+
} catch (error) {
145+
console.error("Error reading messages:", error);
146+
}
147+
}
148+
149+
readMessages();
150+
```
151+
152+
### Subscribing to New Messages
153+
154+
You can subscribe to receive real-time updates for new messages.
155+
156+
```TypeScript
157+
async function subscribeToChatMessages() {
158+
try {
159+
console.log("Subscribing to new messages...");
160+
await chat.subscribeToMessages((newMessages) => {
161+
console.log("New message(s) received:", newMessages.length);
162+
newMessages.forEach(message => {
163+
console.log(`> [${message.created2}] ${message.maker?.["@id"]}: ${message.content}`);
164+
});
165+
});
166+
console.log("Now listening for incoming messages.");
167+
// Keep the process alive to receive messages, or integrate into your app's lifecycle.
168+
} catch (error) {
169+
console.error("Error subscribing to messages:", error);
170+
}
171+
}
172+
173+
subscribeToChatMessages();
174+
175+
// To stop listening:
176+
// await chat.unsubscribeFromMessages();
177+
// console.log("Unsubscribed from messages.");
178+
```
179+
180+
The subscribeToMessages method sets up a WebSocket connection to the message resource of the current day and listens for updates. It automatically handles transitioning to a new day's message resource.
181+
182+
### Removing a Message
183+
184+
You can remove a specific message by its ID.
185+
186+
```TypeScript
187+
async function deleteMessage(messageId: string) {
188+
try {
189+
await chat.removeMessage(messageId);
190+
console.log(`Message ${messageId} removed.`);
191+
} catch (error) {
192+
console.error("Error removing message:", error);
193+
}
194+
}
195+
196+
// Example: deleteMessage("http://localhost:3003/your-chat-container/2024/05/25/index.ttl#some-message-uuid");
197+
```
198+
199+
### Deleting a Chat
200+
201+
You can delete the entire chat container and its contents.
202+
203+
```TypeScript
204+
async function removeChat() {
205+
try {
206+
await chat.deleteChat();
207+
console.log("Chat deleted successfully.");
208+
} catch (error) {
209+
console.error("Error deleting chat:", error);
210+
}
211+
}
212+
213+
// removeChat();
214+
```
215+
216+
### Cleaning Up
217+
218+
When you are done with a Chat instance, especially if you've used subscriptions, call the destroy method to clean up any listeners or timers.
219+
220+
```TypeScript
221+
async function cleanupChat() {
222+
await chat.destroy();
223+
console.log("Chat instance cleaned up.");
224+
}
225+
226+
// Call this when the chat instance is no longer needed, e.g., when a component unmounts.
227+
// cleanupChat();
228+
```
229+
230+
231+
## Funding
232+
233+
This project is funded through [NGI0 Entrust](https://nlnet.nl/entrust), a fund established by [NLnet](https://nlnet.nl) with financial support from the European Commission's [Next Generation Internet](https://ngi.eu) program. Learn more at the [NLnet project page](https://nlnet.nl/SolidDataModules).
234+
235+
[<img src="https://nlnet.nl/logo/banner.png" alt="NLnet foundation logo" width="20%" />](https://nlnet.nl)
236+
[<img src="https://nlnet.nl/image/logos/NGI0_tag.svg" alt="NGI Zero Logo" width="20%" />](https://nlnet.nl/entrust)

0 commit comments

Comments
 (0)