Skip to content

Commit 136b61d

Browse files
authored
Merge pull request #12 from solid/email_object
Addition of solid classes Email and Telephone
2 parents 071b909 + fa2769e commit 136b61d

8 files changed

Lines changed: 278 additions & 10 deletions

File tree

src/solid/Email.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { TermWrapper, ValueMappings, TermMappings } from 'rdfjs-wrapper';
2+
import { VCARD, RDF } from '../vocabulary/mod.js';
3+
4+
export class Email extends TermWrapper {
5+
get emailAddress(): string {
6+
return this.singular(VCARD.value, ValueMappings.literalToString);
7+
}
8+
9+
set emailAddress(value: string) {
10+
this.overwrite(VCARD.value, value, TermMappings.stringToLiteral);
11+
}
12+
13+
get emailType(): string | undefined {
14+
return this.singularNullable(RDF.type, ValueMappings.iriToString);
15+
}
16+
17+
set emailType(value: string | undefined) {
18+
this.overwriteNullable(RDF.type, value, TermMappings.stringToIri);
19+
}
20+
}

src/solid/EmailDataset.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { DatasetWrapper } from 'rdfjs-wrapper';
2+
import { VCARD } from '../vocabulary/mod.js';
3+
import { Email } from './Email.js';
4+
5+
export class EmailDataset extends DatasetWrapper {
6+
get emails(): Iterable<Email> {
7+
const objects = new Set([
8+
...this.instancesOf(VCARD.Email, Email),
9+
...this.objectsOf(VCARD.hasEmail, Email),
10+
...this.objectsOf(VCARD.email, Email),
11+
])
12+
13+
return objects
14+
}
15+
}

src/solid/Telephone.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { TermWrapper, ValueMappings, TermMappings } from 'rdfjs-wrapper';
2+
import { VCARD } from '../vocabulary/mod.js';
3+
4+
export class Telephone extends TermWrapper {
5+
get phoneNumber(): string {
6+
return this.singular(VCARD.hasValue, ValueMappings.literalToString);
7+
}
8+
9+
set phoneNumber(value: string) {
10+
this.overwrite(VCARD.hasValue, value, TermMappings.stringToLiteral);
11+
}
12+
13+
get phoneType(): string | undefined {
14+
return this.singularNullable(VCARD.telephoneType, ValueMappings.iriToString);
15+
}
16+
17+
set phoneType(value: string | undefined) {
18+
this.overwriteNullable(VCARD.telephoneType, value, TermMappings.stringToIri);
19+
}
20+
}

src/solid/TelephoneDataset.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { DatasetWrapper } from 'rdfjs-wrapper';
2+
import { VCARD } from '../vocabulary/vcard.js';
3+
import { Telephone } from './Telephone.js';
4+
5+
export class TelephoneDataset extends DatasetWrapper {
6+
get telephones(): Iterable<Telephone> {
7+
const objects = new Set([
8+
...this.objectsOf(VCARD.hasTelephone, Telephone),
9+
...this.objectsOf(VCARD.tel, Telephone),
10+
])
11+
12+
return objects
13+
}
14+
}

src/solid/mod.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
export * from "./Container.js"
22
export * from "./ContainerDataset.js"
33
export * from "./Resource.js"
4+
export * from "./Email.js";
5+
export * from "./EmailDataset.js";
6+
export * from "./Telephone.js";
7+
export * from "./TelephoneDataset.js";

src/vocabulary/vcard.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
21
export const VCARD = {
3-
fn: "http://www.w3.org/2006/vcard/ns#fn",
4-
hasEmail: "http://www.w3.org/2006/vcard/ns#hasEmail",
5-
hasValue: "http://www.w3.org/2006/vcard/ns#hasValue",
6-
hasPhoto: "http://www.w3.org/2006/vcard/ns#hasPhoto",
7-
hasTelephone: "http://www.w3.org/2006/vcard/ns#hasTelephone",
8-
title: "http://www.w3.org/2006/vcard/ns#title",
9-
hasUrl: "http://www.w3.org/2006/vcard/ns#hasUrl",
10-
organizationName: "http://www.w3.org/2006/vcard/ns#organization-name",
11-
role: "http://www.w3.org/2006/vcard/ns#organization-name",
2+
fn: "http://www.w3.org/2006/vcard/ns#fn",
3+
Email: "http://www.w3.org/2006/vcard/ns#Email",
4+
email: "http://www.w3.org/2006/vcard/ns#email",
5+
hasEmail: "http://www.w3.org/2006/vcard/ns#hasEmail",
6+
hasValue: "http://www.w3.org/2006/vcard/ns#hasValue",
7+
hasPhoto: "http://www.w3.org/2006/vcard/ns#hasPhoto",
8+
tel: "http://www.w3.org/2006/vcard/ns#tel",
9+
hasTelephone: "http://www.w3.org/2006/vcard/ns#hasTelephone",
10+
title: "http://www.w3.org/2006/vcard/ns#title",
11+
hasUrl: "http://www.w3.org/2006/vcard/ns#hasUrl",
12+
organizationName: "http://www.w3.org/2006/vcard/ns#organization-name",
13+
phone: "http://www.w3.org/2006/vcard/ns#phone",
14+
role: "http://www.w3.org/2006/vcard/ns#role",
15+
value: "http://www.w3.org/2006/vcard/ns#value",
16+
telephoneType: "http://www.w3.org/2006/vcard/ns#TelephoneType",
1217
} as const;

test/unit/email.test.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { DataFactory, Parser, Store } from "n3"
2+
import assert from "node:assert"
3+
import { describe, it } from "node:test"
4+
5+
import { Email } from "@solid/object";
6+
7+
describe("Email tests", () => {
8+
9+
const sampleRDF = `
10+
@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .
11+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
12+
13+
<https://example.org/person/1>
14+
a vcard:Individual ;
15+
vcard:fn "Alice" ;
16+
vcard:hasEmail <https://example.org/email/1> .
17+
18+
<https://example.org/email/1>
19+
a vcard:Email ;
20+
vcard:value "alice@example.org" ;
21+
rdf:type vcard:Work .
22+
`;
23+
24+
it("should parse and retrieve email address", () => {
25+
const store = new Store()
26+
store.addQuads(new Parser().parse(sampleRDF))
27+
28+
const email = new Email(
29+
DataFactory.namedNode("https://example.org/email/1"),
30+
store,
31+
DataFactory
32+
)
33+
34+
assert.equal(email.emailAddress, "alice@example.org")
35+
assert.equal(typeof email.emailAddress, "string")
36+
})
37+
38+
it("should allow setting email address", () => {
39+
const store = new Store()
40+
store.addQuads(new Parser().parse(sampleRDF))
41+
42+
const email = new Email(
43+
DataFactory.namedNode("https://example.org/email/1"),
44+
store,
45+
DataFactory
46+
)
47+
48+
email.emailAddress = "bob@example.org"
49+
50+
assert.equal(email.emailAddress, "bob@example.org")
51+
})
52+
53+
it("should parse and retrieve email type", () => {
54+
const store = new Store()
55+
store.addQuads(new Parser().parse(sampleRDF))
56+
57+
const email = new Email(
58+
DataFactory.namedNode("https://example.org/email/1"),
59+
store,
60+
DataFactory
61+
)
62+
63+
const emailType = DataFactory.namedNode("http://www.w3.org/2006/vcard/ns#Home")
64+
65+
assert.ok(emailType !== undefined)
66+
assert.equal(typeof emailType, "object")
67+
assert.equal(emailType.value, "http://www.w3.org/2006/vcard/ns#Home")
68+
})
69+
70+
it("should allow setting email type", () => {
71+
const store = new Store()
72+
73+
const email = new Email(
74+
DataFactory.namedNode("https://example.org/email/2"),
75+
store,
76+
DataFactory
77+
)
78+
79+
email.emailAddress = "test@example.org"
80+
email.emailType = "http://www.w3.org/2006/vcard/ns#Home"
81+
82+
assert.equal(email.emailType, "http://www.w3.org/2006/vcard/ns#Home")
83+
})
84+
85+
})

test/unit/telephone.test.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { DataFactory, Parser, Store } from "n3"
2+
import assert from "node:assert"
3+
import { describe, it } from "node:test"
4+
5+
import { Telephone } from "@solid/object";
6+
7+
describe("Telephone tests", () => {
8+
9+
const sampleRDF = `
10+
@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .
11+
12+
<https://example.org/person/1>
13+
a vcard:Individual ;
14+
vcard:fn "Alice" ;
15+
vcard:hasTelephone <https://example.org/phone/1> .
16+
17+
<https://example.org/phone/1>
18+
a vcard:Telephone ;
19+
vcard:hasValue "+1234567890" ;
20+
vcard:TelephoneType vcard:Cell .
21+
`;
22+
23+
it("should parse and retrieve phone number", () => {
24+
const store = new Store()
25+
store.addQuads(new Parser().parse(sampleRDF))
26+
27+
const telephone = new Telephone(
28+
DataFactory.namedNode("https://example.org/phone/1"),
29+
store,
30+
DataFactory
31+
)
32+
33+
assert.equal(telephone.phoneNumber, "+1234567890")
34+
assert.equal(typeof telephone.phoneNumber, "string")
35+
})
36+
37+
it("should allow setting phone number", () => {
38+
const store = new Store()
39+
store.addQuads(new Parser().parse(sampleRDF))
40+
41+
const telephone = new Telephone(
42+
DataFactory.namedNode("https://example.org/phone/1"),
43+
store,
44+
DataFactory
45+
)
46+
47+
telephone.phoneNumber = "+0987654321"
48+
49+
assert.equal(telephone.phoneNumber, "+0987654321")
50+
})
51+
52+
it("should parse and retrieve phone type", () => {
53+
const store = new Store()
54+
store.addQuads(new Parser().parse(sampleRDF))
55+
56+
const telephone = new Telephone(
57+
DataFactory.namedNode("https://example.org/phone/1"),
58+
store,
59+
DataFactory
60+
)
61+
62+
const phoneType = telephone.phoneType
63+
64+
assert.ok(phoneType !== undefined)
65+
assert.equal(typeof phoneType, "string")
66+
assert.equal(phoneType, "http://www.w3.org/2006/vcard/ns#Cell")
67+
})
68+
69+
it("should allow setting phone type", () => {
70+
const store = new Store()
71+
72+
const telephone = new Telephone(
73+
DataFactory.namedNode("https://example.org/phone/2"),
74+
store,
75+
DataFactory
76+
)
77+
78+
telephone.phoneNumber = "+1112223333"
79+
telephone.phoneType = "http://www.w3.org/2006/vcard/ns#Car"
80+
81+
assert.equal(telephone.phoneType, "http://www.w3.org/2006/vcard/ns#Car")
82+
})
83+
84+
it("should throw when phone number is missing", () => {
85+
const noPhoneRDF = `
86+
@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .
87+
88+
<https://example.org/phone/empty>
89+
a vcard:Telephone .
90+
`
91+
const store = new Store()
92+
store.addQuads(new Parser().parse(noPhoneRDF))
93+
94+
const telephone = new Telephone(
95+
DataFactory.namedNode("https://example.org/phone/empty"),
96+
store,
97+
DataFactory
98+
)
99+
100+
assert.throws(() => {
101+
telephone.phoneNumber
102+
})
103+
})
104+
105+
})

0 commit comments

Comments
 (0)