Skip to content

Commit cdf7499

Browse files
committed
Preparing for release v0.1.0 :).
1 parent 50a9caa commit cdf7499

6 files changed

Lines changed: 288 additions & 12 deletions

File tree

README.md

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
LevelGraph-JSONLD
2+
===========
3+
4+
![Logo](https://github.com/mcollina/node-levelgraph/raw/master/logo.png)
5+
6+
__LevelGraph-JSONLD__ is a plugin for
7+
[LevelGraph](http://github.com/mcollina/levelgraph) that adds the
8+
ability to store, retrieve and delete JSON-LD objects.
9+
In fact, it is a full-bown Object-Document-Mapper (ODM) for
10+
__LevelGraph__.
11+
12+
[![Build
13+
Status](https://travis-ci.org/mcollina/levelgraph-jsonld.png)](https://travis-ci.org/mcollina/levelgraph-jsonld)
14+
15+
## Install on Node.js
16+
17+
```
18+
npm install levelgraph levelgraph-jsonld --save
19+
```
20+
21+
At the moment it requires node v0.10.x, but the port to node v0.8.x
22+
should be straighforward.
23+
If you need it, just open a pull request.
24+
25+
## Install in the Browser
26+
27+
TO BE DONE!
28+
29+
## Usage
30+
31+
Adding support for JSON-LD to LevelGraph is easy:
32+
```
33+
var levelgraph = require("levelgraph")
34+
, jsonld = require("levelgraph-jsonld")
35+
, db = jsonld(levelgraph("yourdb"));
36+
```
37+
38+
### Put
39+
40+
Storing a JSON-LD file in the database is extremey easy:
41+
```
42+
var manu = {
43+
"@context": {
44+
"name": "http://xmlns.com/foaf/0.1/name"
45+
, "homepage": {
46+
"@id": "http://xmlns.com/foaf/0.1/homepage"
47+
, "@type": "@id"
48+
}
49+
}
50+
, "@id": "http://manu.sporny.org#person"
51+
, "name": "Manu Sporny"
52+
, "homepage": "http://manu.sporny.org/"
53+
}
54+
55+
db.jsonld.put(manu, function(err, obj) {
56+
// do something after the obj is inserted
57+
});
58+
```
59+
60+
if the object as no `'@id'` key, one will be generated for you,
61+
using a UUID and the `'base'` argument, like so:
62+
```
63+
delete manu["@id"];
64+
db.jsonld.put(manu, { base: "http://this/is/an/iri" }, function(err, obj) {
65+
// obj["@id"] will be something like
66+
http://this/is/an/iri/b1e783b0-eda6-11e2-9540-d7575689f4bc
67+
});
68+
```
69+
70+
`'base'` can also be specified when you create the db:
71+
```
72+
var levelgraph = require("levelgraph")
73+
, jsonld = require("levelgraph-jsonld")
74+
, opts = { base: "http://matteocollina.com/base" }
75+
, db = jsonld(levelgraph("yourdb"), opts);
76+
```
77+
78+
__LevelGraph-JSONLD__ also support nested objects, like so:
79+
```
80+
var nested = {
81+
"@context": {
82+
"name": "http://xmlns.com/foaf/0.1/name"
83+
, "knows": "http://xmlns.com/foaf/0.1/knows"
84+
}
85+
, "@id": "http://matteocollina.com"
86+
, "name": "matteo"
87+
, "knows": [{
88+
"name": "daniele"
89+
}, {
90+
"name": "lucio"
91+
}]
92+
};
93+
94+
db.jsonld.put(nested, function(err, obj) {
95+
// do something...
96+
});
97+
```
98+
99+
### Get
100+
101+
Retrieving a JSON-LD document from the store requires its `'@id'`:
102+
```
103+
db.jsonld.get(manu["@id"], { "@context": manu["@context"] }, function(err, obj) {
104+
// obj will be the very same of the manu object
105+
});
106+
```
107+
108+
The format of the loaded object is entirely specified by the
109+
`'@context'`, so have fun :).
110+
111+
As with `'put'` it correctly support nested objects, but it
112+
inserts `'@id'` properties for them, like so:
113+
```
114+
var nested = {
115+
"@context": {
116+
"name": "http://xmlns.com/foaf/0.1/name"
117+
, "knows": "http://xmlns.com/foaf/0.1/knows"
118+
}
119+
, "@id": "http://matteocollina.com"
120+
, "name": "matteo"
121+
, "knows": [{
122+
"name": "daniele"
123+
}, {
124+
"name": "lucio"
125+
}]
126+
};
127+
128+
db.jsonld.put(nested, function(err, obj) {
129+
// obj will be
130+
// {
131+
// "@context": {
132+
// "name": "http://xmlns.com/foaf/0.1/name"
133+
// , "knows": "http://xmlns.com/foaf/0.1/knows"
134+
// }
135+
// , "@id": "http://matteocollina.com"
136+
// , "name": "matteo"
137+
// , "knows": [{
138+
// "name": "daniele"
139+
// }, {
140+
// "name": "lucio"
141+
// }]
142+
// }
143+
});
144+
```
145+
146+
### Deleting
147+
148+
In order to delete an object, you can just pass it's `'@id'` to the
149+
`'@del'` method:
150+
```
151+
db.jsonld.del(manu["@id"], function(err) {
152+
// do something after it is deleted!
153+
});
154+
```
155+
156+
### Searching with LevelGraph
157+
158+
__LevelGraph-JSONLD__ does not support searching for objects, because
159+
that problem is already solved by __LevelGraph__ itself, like these:
160+
```
161+
var nested = {
162+
"@context": {
163+
"name": "http://xmlns.com/foaf/0.1/name"
164+
, "knows": "http://xmlns.com/foaf/0.1/knows"
165+
}
166+
, "@id": "http://matteocollina.com"
167+
, "name": "matteo"
168+
, "knows": [{
169+
"name": "daniele"
170+
}, {
171+
"name": "lucio"
172+
}]
173+
};
174+
175+
db.jsonld.put(nested, function(err) {
176+
db.join([{
177+
subject: db.v("person")
178+
, predicate: "http://xmlns.com/foaf/0.1/knows"
179+
, object: db.v("friend")
180+
}, {
181+
subject: db.v("friend")
182+
, predicate: "http://xmlns.com/foaf/0.1/knows"
183+
, object: "daniele"
184+
}], function(err, solutions) {
185+
// The solutions will be:
186+
// 1. { person: "http://matteocollina.com", friend: "_:abcde" }
187+
// 1. { person: "http://matteocollina.com", friend: "_:efghi" }
188+
});
189+
});
190+
```
191+
192+
## Contributing to LevelGraph-JSONLD
193+
194+
* Check out the latest master to make sure the feature hasn't been
195+
implemented or the bug hasn't been fixed yet
196+
* Check out the issue tracker to make sure someone already hasn't
197+
requested it and/or contributed it
198+
* Fork the project
199+
* Start a feature/bugfix branch
200+
* Commit and push until you are happy with your contribution
201+
* Make sure to add tests for it. This is important so I don't break it
202+
in a future version unintentionally.
203+
* Please try not to mess with the Makefile and package.json. If you
204+
want to have your own version, or is otherwise necessary, that is
205+
fine, but please isolate to its own commit so I can cherry-pick around
206+
it.
207+
208+
## LICENSE - "MIT License"
209+
210+
Copyright (c) 2013 Matteo Collina (http://matteocollina.com)
211+
212+
Permission is hereby granted, free of charge, to any person
213+
obtaining a copy of this software and associated documentation
214+
files (the "Software"), to deal in the Software without
215+
restriction, including without limitation the rights to use,
216+
copy, modify, merge, publish, distribute, sublicense, and/or sell
217+
copies of the Software, and to permit persons to whom the
218+
Software is furnished to do so, subject to the following
219+
conditions:
220+
221+
The above copyright notice and this permission notice shall be
222+
included in all copies or substantial portions of the Software.
223+
224+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
225+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
226+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
227+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
228+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
229+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
230+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
231+
OTHER DEALINGS IN THE SOFTWARE.

index.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,19 @@ function levelgraphJSONLD(db, jsonldOpts) {
131131
cb(null, acc);
132132
} else if (triple.object.indexOf("_:") !== 0) {
133133
acc[triple.subject][triple.predicate] = {};
134-
key = (triple.object.match(IRI) || triple.object.indexOf("_:") === 0) ? "@id" : "@value";
134+
key = (triple.object.match(IRI)) ? "@id" : "@value";
135135
acc[triple.subject][triple.predicate][key] = triple.object;
136136
cb(null, acc);
137137
} else {
138138
fetchExpandedTriples(triple.object, function(err, expanded) {
139-
acc[triple.subject][triple.predicate] = expanded[triple.object];
139+
if (!acc[triple.subject][triple.predicate]) {
140+
acc[triple.subject][triple.predicate] = expanded[triple.object];
141+
} else {
142+
if (!acc[triple.subject][triple.predicate].push) {
143+
acc[triple.subject][triple.predicate] = [acc[triple.subject][triple.predicate]];
144+
}
145+
acc[triple.subject][triple.predicate].push(expanded[triple.object]);
146+
}
140147
cb(err, acc);
141148
});
142149
}
@@ -155,12 +162,8 @@ function levelgraphJSONLD(db, jsonldOpts) {
155162
if (err || expanded === null) {
156163
return callback(err, expanded);
157164
}
158-
expanded = Object.keys(expanded).reduce(function(acc, key) {
159-
acc.push(expanded[key]);
160-
return acc;
161-
}, []);
162165

163-
jsonld.compact(expanded, context, options, callback);
166+
jsonld.compact(expanded[iri], context, options, callback);
164167
});
165168
};
166169

package.json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
{
22
"name": "levelgraph-jsonld",
3-
"version": "0.0.0",
4-
"description": "The Object Document Mapper of LevelGraph based on JSON-LD",
3+
"version": "0.1.0",
4+
"description": "The Object Document Mapper for LevelGraph based on JSON-LD",
55
"main": "index.js",
66
"scripts": {
77
"test": "./node_modules/.bin/mocha --recursive test"
88
},
9-
"repository": "",
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/mcollina/levelgraph-jsonld.git"
12+
},
13+
"bugs": {
14+
"url": "http://github.com/mcollina/levelgraph-jsonld/issues"
15+
},
1016
"keywords": [
1117
"object",
1218
"document",
@@ -20,7 +26,7 @@
2026
"rdf",
2127
"linked data"
2228
],
23-
"author": "",
29+
"author": "Matteo Collina <hello@matteocollina.com>",
2430
"license": "MIT",
2531
"dependencies": {
2632
"jsonld": "0.0.62",
@@ -33,7 +39,6 @@
3339
"devDependencies": {
3440
"mocha": "~1.10.0",
3541
"levelgraph": "~0.6.1",
36-
"levelgraph-n3": "~0.1.0",
3742
"level-test": "~1.4.0",
3843
"chai": "~1.7.2"
3944
}

test/fixture/nested.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"@context": {
3+
"name": "http://xmlns.com/foaf/0.1/name"
4+
, "knows": "http://xmlns.com/foaf/0.1/knows"
5+
}
6+
, "@id": "http://matteocollina.com"
7+
, "name": "matteo"
8+
, "knows": [{
9+
"name": "daniele"
10+
}, {
11+
"name": "lucio"
12+
}]
13+
}

test/get_spec.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,17 @@ describe("jsonld.get", function() {
5353
});
5454
});
5555
});
56+
57+
it("should support nested objects", function(done) {
58+
var nested = fixture("nested.json");
59+
60+
db.jsonld.put(nested, function(err, obj) {
61+
db.jsonld.get(obj["@id"], { "@context": obj["@context"] }, function(err, result) {
62+
delete result["knows"][0]["@id"];
63+
delete result["knows"][1]["@id"];
64+
expect(result).to.eql(nested);
65+
done();
66+
});
67+
});
68+
});
5669
});

test/put_spec.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,15 @@ describe("jsonld.put with default base", function() {
165165
});
166166
});
167167
});
168+
169+
it("should support nested objects", function(done) {
170+
var nested = fixture("nested.json");
171+
172+
db.jsonld.put(nested, function() {
173+
db.get({}, function(err, triples) {
174+
expect(triples).to.have.property("length", 5);
175+
done();
176+
});
177+
});
178+
});
168179
});

0 commit comments

Comments
 (0)