Skip to content

Commit 36488eb

Browse files
committed
complete merge with discovery code
1 parent 007c377 commit 36488eb

6 files changed

Lines changed: 86 additions & 96 deletions

File tree

src/inbox/inboxLogic.ts

Lines changed: 41 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,58 @@
1-
import { NamedNode, LiveStore, sym } from "rdflib";
2-
import { ProfileLogic } from "../profile/ProfileLogic";
3-
import { SolidNamespace } from "../types";
4-
import { UtilityLogic } from "../util/UtilityLogic";
1+
import { NamedNode, sym } from "rdflib";
2+
import { InboxLogic } from "../types";
3+
import { getArchiveUrl } from "../util/utils";
54

6-
/**
7-
* Inbox-related logic
8-
*/
9-
export class InboxLogic {
10-
store: LiveStore;
11-
ns: SolidNamespace;
12-
profile: ProfileLogic;
13-
util: UtilityLogic;
14-
15-
constructor(store: LiveStore, ns: SolidNamespace, profile: ProfileLogic, util: UtilityLogic) {
16-
this.store = store;
17-
this.ns = ns;
18-
this.profile = profile;
19-
this.util = util;
5+
export function createInboxLogic(store, profileLogic, utilityLogic, containerLogic, aclLogic): InboxLogic {
6+
7+
async function createInboxFor(peerWebId: string, nick: string) {
8+
const myWebId: NamedNode = await profileLogic.loadMe();
9+
const podRoot: NamedNode = await profileLogic.getPodRoot(myWebId);
10+
const ourInbox = `${podRoot.value}p2p-inboxes/${encodeURIComponent(nick)}/`;
11+
await containerLogic.createContainer(ourInbox);
12+
const aclDocUrl = await aclLogic.findAclDocUrl(sym(ourInbox))
13+
await utilityLogic.setSinglePeerAccess({
14+
ownerWebId: myWebId.value,
15+
peerWebId,
16+
accessToModes: 'acl:Append',
17+
target: ourInbox
18+
});
19+
return ourInbox;
2020
}
2121

22-
async getNewMessages(
23-
user?: NamedNode
24-
): Promise<NamedNode[]> {
25-
if (!user) {
26-
user = await this.profile.loadMe();
27-
}
28-
const inbox = await this.profile.getMainInbox(user);
29-
const urls = await this.util.getContainerMembers(inbox);
30-
return urls.filter(url => !this.util.isContainer(url));
22+
async function getNewMessages(
23+
user?: NamedNode
24+
): Promise<NamedNode[]> {
25+
if (!user) {
26+
user = await profileLogic.loadMe();
27+
}
28+
const inbox = await profileLogic.getMainInbox(user);
29+
const urls = await containerLogic.getContainerMembers(inbox);
30+
return urls.filter(url => !containerLogic.isContainer(url));
3131
}
32-
async createInboxFor(ourPeerWebId: NamedNode, nick: string) {
33-
const myWebId: NamedNode = (await this.profile.loadMe());
34-
const podRoot: NamedNode = await this.profile.getPodRoot(myWebId);
35-
const ourInbox = `${podRoot.value}p2p-inboxes/${encodeURIComponent(nick)}/`;
36-
const toNode: NamedNode = sym(ourInbox);
37-
await this.util.createContainer(toNode);
38-
const aclDocUrl = await this.util.findAclDocUrl(toNode);
39-
await this.util.setSinglePeerAccess({
40-
ownerWebId: myWebId.value,
41-
peerWebId: ourPeerWebId.value,
42-
accessToModes: 'acl:Append',
43-
target: ourInbox
44-
});
45-
return ourInbox;
46-
}
47-
async markAsRead(url: NamedNode, date: Date) {
48-
const nodeToStr = url.value;
49-
const downloaded = await this.store.fetcher._fetch(nodeToStr);
32+
33+
async function markAsRead(url: string, date: Date) {
34+
const downloaded = await store.fetcher._fetch(url);
5035
if (downloaded.status !== 200) {
5136
throw new Error(`Not OK! ${url}`);
5237
}
53-
const archiveUrl = this.util.getArchiveUrl(nodeToStr, date);
54-
const options = {
38+
const archiveUrl = getArchiveUrl(url, date);
39+
const options = {
5540
method: 'PUT',
5641
body: await downloaded.text(),
5742
headers: [
58-
[ 'Content-Type', downloaded.headers.get('Content-Type') || 'application/octet-stream' ]
43+
['Content-Type', downloaded.headers.get('Content-Type') || 'application/octet-stream']
5944
]
6045
};
61-
const uploaded = await this.store.fetcher._fetch(archiveUrl, options);
46+
const uploaded = await store.fetcher._fetch(archiveUrl, options);
6247
if (uploaded.status.toString()[0] === '2') {
63-
await this.store.fetcher?._fetch(nodeToStr, {
48+
await store.fetcher._fetch(url, {
6449
method: 'DELETE'
6550
});
6651
}
6752
}
68-
}
53+
return {
54+
createInboxFor,
55+
getNewMessages,
56+
markAsRead
57+
}
58+
}

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export interface AclLogic {
8989

9090
export interface InboxLogic {
9191
createInboxFor: (peerWebId: string, nick: string) => Promise<string>,
92-
getNewMessages: (user?: NamedNode) => Promise<string[]>,
92+
getNewMessages: (user?: NamedNode) => Promise<NamedNode[]>,
9393
markAsRead: (url: string, date: Date) => void
9494
}
9595

src/util/containerLogic.ts

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,43 @@ import { NamedNode, Statement, sym } from "rdflib";
66
export function createContainerLogic(store) {
77

88
function getContainerElements(containerNode: NamedNode): NamedNode[] {
9-
return store
10-
.statementsMatching(
11-
containerNode,
12-
sym("http://www.w3.org/ns/ldp#contains"),
13-
undefined,
14-
containerNode.doc()
15-
)
16-
.map((st: Statement) => st.object as NamedNode);
9+
return store
10+
.statementsMatching(
11+
containerNode,
12+
sym("http://www.w3.org/ns/ldp#contains"),
13+
undefined
14+
)
15+
.map((st: Statement) => st.object as NamedNode);
1716
}
1817

19-
function isContainer(url: string) {
20-
return url.charAt(url.length - 1) === "/";
18+
function isContainer(url: NamedNode) {
19+
const nodeToString = url.value;
20+
return nodeToString.charAt(nodeToString.length - 1) === "/";
2121
}
2222

2323
async function createContainer(url: string) {
24-
if (!isContainer(url)) {
25-
throw new Error(`Not a container URL ${url}`);
26-
}
27-
// Copied from https://github.com/solidos/solid-crud-tests/blob/v3.1.0/test/surface/create-container.test.ts#L56-L64
28-
const result = await store.fetcher._fetch(url, {
29-
method: "PUT",
30-
headers: {
31-
"Content-Type": "text/turtle",
32-
"If-None-Match": "*",
33-
Link: '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"', // See https://github.com/solidos/node-solid-server/issues/1465
34-
},
35-
body: " ", // work around https://github.com/michielbdejong/community-server/issues/4#issuecomment-776222863
36-
});
37-
if (result.status.toString()[0] !== '2') {
38-
throw new Error(`Not OK: got ${result.status} response while creating container at ${url}`);
39-
}
24+
const stringToNode = sym(url);
25+
if (!isContainer(stringToNode)) {
26+
throw new Error(`Not a container URL ${url}`);
27+
}
28+
// Copied from https://github.com/solidos/solid-crud-tests/blob/v3.1.0/test/surface/create-container.test.ts#L56-L64
29+
const result = await store.fetcher._fetch(url, {
30+
method: "PUT",
31+
headers: {
32+
"Content-Type": "text/turtle",
33+
"If-None-Match": "*",
34+
Link: '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"', // See https://github.com/solidos/node-solid-server/issues/1465
35+
},
36+
body: " ", // work around https://github.com/michielbdejong/community-server/issues/4#issuecomment-776222863
37+
});
38+
if (result.status.toString()[0] !== '2') {
39+
throw new Error(`Not OK: got ${result.status} response while creating container at ${url}`);
40+
}
4041
}
4142

42-
async function getContainerMembers(containerUrl: string): Promise<string[]> {
43-
const containerNode = store.sym(containerUrl);
44-
await store.fetcher.load(containerNode);
45-
const nodes = getContainerElements(containerNode);
46-
return nodes.map(node => node.value);
43+
async function getContainerMembers(containerUrl: NamedNode): Promise<NamedNode[]> {
44+
await store.fetcher.load(containerUrl);
45+
return getContainerElements(containerUrl);
4746
}
4847
return {
4948
isContainer,

src/util/utilityLogic.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@ import { differentOrigin } from "./utils";
55

66
export function createUtilityLogic(store, aclLogic, containerLogic) {
77

8-
async function recursiveDelete(url: string) {
8+
async function recursiveDelete(containerNode: NamedNode) {
99
try {
10-
if (containerLogic.isContainer(url)) {
11-
const aclDocUrl = await aclLogic.findAclDocUrl(sym(url));
10+
if (containerLogic.isContainer(containerNode)) {
11+
const aclDocUrl = await aclLogic.findAclDocUrl(containerNode)
1212
await store.fetcher._fetch(aclDocUrl, { method: "DELETE" });
13-
const containerMembers = await containerLogic.getContainerMembers(url);
13+
const containerMembers = await containerLogic.getContainerMembers(containerNode);
1414
await Promise.all(
1515
containerMembers.map((url) => recursiveDelete(url))
1616
);
1717
}
18-
return store.fetcher._fetch(url, { method: "DELETE" });
18+
const nodeToStringHere = containerNode.value;
19+
return store.fetcher._fetch(nodeToStringHere, { method: "DELETE" });
1920
} catch (e) {
2021
// debug.log(`Please manually remove ${url} from your system under test.`, e);
2122
}
@@ -126,7 +127,7 @@ export function createUtilityLogic(store, aclLogic, containerLogic) {
126127
''
127128
].join('\n')
128129
}
129-
const aclDocUrl = await aclLogic.findAclDocUrl(sym(options.target));
130+
const aclDocUrl = await aclLogic.findAclDocUrl(sym(options.target))
130131
return store.fetcher._fetch(aclDocUrl, {
131132
method: 'PUT',
132133
body: str,

test/container.test.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @jest-environment jsdom
33
*
44
*/
5-
import { UpdateManager, Store, Fetcher } from "rdflib";
5+
import { UpdateManager, Store, Fetcher, sym } from "rdflib";
66
import { createContainerLogic } from "../src/util/containerLogic";
77
import { alice } from "./helpers/dataSetup";
88

@@ -21,15 +21,16 @@ describe("Container", () => {
2121

2222
it("getContainerMembers - When container has some containment triples", async () => {
2323
containerHasSomeContainmentTriples()
24-
const result = await containerLogic.getContainerMembers('https://com/');
24+
const containerMembers = await containerLogic.getContainerMembers(sym('https://container.com/'));
25+
const result = containerMembers.map(oneResult => oneResult.value)
2526
expect(result.sort()).toEqual([
26-
'https://com/foo.txt',
27-
'https://com/bar/'
27+
'https://container.com/foo.txt',
28+
'https://container.com/bar/'
2829
].sort());
2930
});
3031
it("getContainerMembers- When container is empty - Resolves to an empty array", async () => {
3132
containerIsEmpty();
32-
const result = await containerLogic.getContainerMembers('https://container.com/');
33+
const result = await containerLogic.getContainerMembers(sym('https://container.com/'));
3334
expect(result).toEqual([]);
3435
});
3536

@@ -45,7 +46,7 @@ describe("Container", () => {
4546

4647
function containerHasSomeContainmentTriples() {
4748
fetchMock.mockOnceIf(
48-
"https://com/",
49+
"https://container.com/",
4950
"<.> <http://www.w3.org/ns/ldp#contains> <./foo.txt>, <./bar/> .",
5051
{
5152
headers: { "Content-Type": "text/turtle" },

test/inboxLogic.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ describe("Inbox logic", () => {
5454
inboxHasSomeContainmentTriples();
5555
const messages = await inboxLogic.getNewMessages(bob);
5656
result = messages.map(oneMessage => oneMessage.value)
57-
5857
});
5958
it("Resolves to an array with URLs of non-container resources in inbox", () => {
6059
expect(result.sort()).toEqual([

0 commit comments

Comments
 (0)