n3.js-messages 0.1.1 → 0.1.4
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 +6 -2
- package/index.d.ts +10 -0
- package/lib/MessageStreamWriter.js +3 -2
- package/lib/MessageWriter.js +61 -5
- package/lib/index.js +2 -1
- package/package.json +4 -4
- package/src/MessageStreamWriter.js +4 -2
- package/src/MessageWriter.js +62 -6
package/README.md
CHANGED
|
@@ -108,8 +108,12 @@ const text = writeMessages(messages, { format: 'N-Quads' }); // synchronous, re
|
|
|
108
108
|
message survives a round trip.
|
|
109
109
|
- Each message starts from a clean serializer state, so consecutive messages in the same named graph are valid. Prefixes (and `baseIRI` with
|
|
110
110
|
`writeBase: true`) are declared once; `addPrefix` declares more before the next message.
|
|
111
|
-
-
|
|
112
|
-
|
|
111
|
+
- Quads can also be streamed within a message, with constant memory: `beginMessage()` (optional), `addQuad(quad)` (written immediately),
|
|
112
|
+
`endMessage()` (writes the delimiter and resets the serializer state; without an open message it writes an empty one). `end()` closes an open message.
|
|
113
|
+
Alternatively, tag quads as in rdf-writer-ts, `addQuad(quad, messageIndex)`: a change of index ends the current message and writes the empty messages in
|
|
114
|
+
between; a lower index is an error. `addMessage(quads)` is shorthand for begin, add all, end, and fails if a message is open.
|
|
115
|
+
- `addMessage`, `addQuad`, `beginMessage`, `endMessage` and `end` accept a callback or return a promise. They complete when the output stream has accepted the data, not when it was queued.
|
|
116
|
+
- `MessageStreamWriter` is the `Transform` equivalent: messages in (object mode), text out. It also accepts `{ quad, messageIndex }` objects.
|
|
113
117
|
|
|
114
118
|
## Blank node semantics
|
|
115
119
|
|
package/index.d.ts
CHANGED
|
@@ -101,6 +101,16 @@ export class MessageWriter {
|
|
|
101
101
|
constructor(outputStream?: MessageOutputStream | NodeJS.WritableStream | null, options?: MessageWriterOptions);
|
|
102
102
|
addMessage(quads: RDF.BaseQuad[], done: (error: Error | null) => void): void;
|
|
103
103
|
addMessage(quads: RDF.BaseQuad[]): Promise<void>;
|
|
104
|
+
/** Opens a message; optional, as `addQuad` opens one implicitly. */
|
|
105
|
+
beginMessage(done: (error: Error | null) => void): void;
|
|
106
|
+
beginMessage(): Promise<void>;
|
|
107
|
+
/** Writes a quad right away. With a 0-based `messageIndex`, a change of index ends the message and writes empty messages for gaps; a lower index is an error. */
|
|
108
|
+
addQuad(quad: RDF.BaseQuad, messageIndex: number | undefined, done: (error: Error | null) => void): void;
|
|
109
|
+
addQuad(quad: RDF.BaseQuad, done: (error: Error | null) => void): void;
|
|
110
|
+
addQuad(quad: RDF.BaseQuad, messageIndex?: number): Promise<void>;
|
|
111
|
+
/** Ends the open message (writes an empty message if none is open). */
|
|
112
|
+
endMessage(done: (error: Error | null) => void): void;
|
|
113
|
+
endMessage(): Promise<void>;
|
|
104
114
|
addPrefix(prefix: string, iri: RDF.NamedNode | string, done: (error: Error | null) => void): void;
|
|
105
115
|
addPrefix(prefix: string, iri: RDF.NamedNode | string): Promise<void>;
|
|
106
116
|
/** Without an output stream, the result is the written string. */
|
|
@@ -9,7 +9,7 @@ var _MessageWriter = _interopRequireDefault(require("./MessageWriter.js"));
|
|
|
9
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
10
|
// **MessageStreamWriter** is a Node.js stream that serializes RDF Messages.
|
|
11
11
|
//
|
|
12
|
-
// It consumes messages (arrays of quads) and produces text.
|
|
12
|
+
// It consumes messages (arrays of quads), or `{ quad, messageIndex }` objects, and produces text.
|
|
13
13
|
|
|
14
14
|
class MessageStreamWriter extends _stream.Transform {
|
|
15
15
|
constructor(options) {
|
|
@@ -26,7 +26,8 @@ class MessageStreamWriter extends _stream.Transform {
|
|
|
26
26
|
}));
|
|
27
27
|
}
|
|
28
28
|
_transform(message, encoding, done) {
|
|
29
|
-
|
|
29
|
+
// A message (array of quads), or a quad of a message: `{ quad, messageIndex }`
|
|
30
|
+
if (Array.isArray(message)) this._writer.addMessage(message, done);else this._writer.addQuad(message.quad, message.messageIndex, done);
|
|
30
31
|
}
|
|
31
32
|
_flush(done) {
|
|
32
33
|
this._writer.end(done);
|
package/lib/MessageWriter.js
CHANGED
|
@@ -40,6 +40,8 @@ class MessageWriter {
|
|
|
40
40
|
this._error = null;
|
|
41
41
|
this._started = false;
|
|
42
42
|
this._ended = false;
|
|
43
|
+
this._open = false;
|
|
44
|
+
this._count = 0; // messages begun so far: the index of the next message
|
|
43
45
|
this._declared = Object.assign({}, options.prefixes);
|
|
44
46
|
this._newPrefixes = {};
|
|
45
47
|
// The N3.js writer writes to this sink, which it never ends
|
|
@@ -53,8 +55,37 @@ class MessageWriter {
|
|
|
53
55
|
// The callback (or returned promise) completes once the output is flushed.
|
|
54
56
|
addMessage(quads, done) {
|
|
55
57
|
return this._complete(done, () => {
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
58
|
+
if (this._open) throw new Error('A message is already open');
|
|
59
|
+
this._begin();
|
|
60
|
+
for (const quad of quads || []) this._add(quad);
|
|
61
|
+
this._close();
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ### `beginMessage` opens a message. It is optional: the first `addQuad` opens one implicitly.
|
|
66
|
+
beginMessage(done) {
|
|
67
|
+
return this._complete(done, () => {
|
|
68
|
+
if (this._open) throw new Error('A message is already open');
|
|
69
|
+
this._begin();
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ### `addQuad` writes a quad into the open message right away (a message is opened if there is none).
|
|
74
|
+
// With a `messageIndex` (0-based), a change of index ends the current message and writes the empty
|
|
75
|
+
// messages in between, as rdf-writer-ts does; a lower index than the current one is an error.
|
|
76
|
+
addQuad(quad, messageIndex, done) {
|
|
77
|
+
if (typeof messageIndex === 'function') done = messageIndex, messageIndex = undefined;
|
|
78
|
+
return this._complete(done, () => {
|
|
79
|
+
if (messageIndex !== undefined && messageIndex !== null) this._moveTo(messageIndex);else if (!this._open) this._begin();
|
|
80
|
+
this._add(quad);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ### `endMessage` ends the open message with a delimiter. Without an open message, it writes an empty one.
|
|
85
|
+
endMessage(done) {
|
|
86
|
+
return this._complete(done, () => {
|
|
87
|
+
if (!this._open) this._begin();
|
|
88
|
+
this._close();
|
|
58
89
|
});
|
|
59
90
|
}
|
|
60
91
|
|
|
@@ -72,6 +103,7 @@ class MessageWriter {
|
|
|
72
103
|
// Ending twice is harmless
|
|
73
104
|
if (this._ended) return typeof done === 'function' ? done(null) : Promise.resolve();
|
|
74
105
|
this._start();
|
|
106
|
+
if (this._open) this._close();
|
|
75
107
|
if (typeof done === 'function') return this._finish(done);
|
|
76
108
|
return new Promise((resolve, reject) => this._finish((error, result) => error ? reject(error) : resolve(result)));
|
|
77
109
|
}
|
|
@@ -150,16 +182,40 @@ class MessageWriter {
|
|
|
150
182
|
});
|
|
151
183
|
}
|
|
152
184
|
}
|
|
153
|
-
|
|
185
|
+
|
|
186
|
+
// Opens a message: declares the prefixes that were added since the previous one
|
|
187
|
+
_begin() {
|
|
188
|
+
this._start();
|
|
154
189
|
const writer = this._writer;
|
|
155
190
|
for (const prefix of Object.keys(this._newPrefixes)) {
|
|
156
191
|
writer.addPrefix(prefix, this._newPrefixes[prefix]);
|
|
157
192
|
this._declared[prefix] = this._newPrefixes[prefix];
|
|
158
193
|
}
|
|
159
194
|
this._newPrefixes = {};
|
|
195
|
+
this._open = true;
|
|
196
|
+
this._count++;
|
|
197
|
+
}
|
|
198
|
+
_add(quad) {
|
|
160
199
|
const record = error => error && (this._error = this._error || error);
|
|
161
|
-
|
|
162
|
-
|
|
200
|
+
this._writer.addQuad(quad.subject, quad.predicate, quad.object, quad.graph, record);
|
|
201
|
+
}
|
|
202
|
+
_close() {
|
|
203
|
+
this._open = false;
|
|
204
|
+
this._writer.addDelimiter();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Makes message `index` the open message, writing empty messages for the gap
|
|
208
|
+
_moveTo(index) {
|
|
209
|
+
const current = this._count - 1;
|
|
210
|
+
if (!Number.isInteger(index) || index < 0) throw new RangeError(`Invalid message index: ${index}`);
|
|
211
|
+
if (this._open && index === current) return;
|
|
212
|
+
if (index <= current) throw new RangeError(`Message index ${index} is lower than the current message index ${current}`);
|
|
213
|
+
if (this._open) this._close();
|
|
214
|
+
while (this._count < index) {
|
|
215
|
+
this._begin();
|
|
216
|
+
this._close();
|
|
217
|
+
}
|
|
218
|
+
this._begin();
|
|
163
219
|
}
|
|
164
220
|
}
|
|
165
221
|
|
package/lib/index.js
CHANGED
|
@@ -44,4 +44,5 @@ var _MessageStreamParser = _interopRequireDefault(require("./MessageStreamParser
|
|
|
44
44
|
var _MessageWriter = _interopRequireWildcard(require("./MessageWriter.js"));
|
|
45
45
|
var _MessageStreamWriter = _interopRequireDefault(require("./MessageStreamWriter.js"));
|
|
46
46
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
47
|
-
|
|
47
|
+
var cache;
|
|
48
|
+
function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var r, c, a = Object.defineProperty, n = { __proto__: null, default: e }; if (Object(e) !== e) return n; if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) { if (cache.has(e)) return cache.get(e); cache.set(e, n); } for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]); return n; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n3.js-messages",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "RDF Messages (message-delimited Turtle, TriG, N-Triples and N-Quads) for N3.js: message-aware parser, streaming parser and writer.",
|
|
5
5
|
"author": "Pieter Colpaert",
|
|
6
6
|
"license": "MIT",
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
"spec:update": "node scripts/update-spec.js"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@babel/cli": "^
|
|
66
|
-
"@babel/core": "^
|
|
67
|
-
"@babel/preset-env": "^
|
|
65
|
+
"@babel/cli": "^8.0.6",
|
|
66
|
+
"@babel/core": "^8.0.7",
|
|
67
|
+
"@babel/preset-env": "^8.0.7",
|
|
68
68
|
"@types/n3": "^1.26.4",
|
|
69
69
|
"@types/node": "^26.6.4",
|
|
70
70
|
"babel-jest": "^30.5.2",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// **MessageStreamWriter** is a Node.js stream that serializes RDF Messages.
|
|
2
2
|
//
|
|
3
|
-
// It consumes messages (arrays of quads) and produces text.
|
|
3
|
+
// It consumes messages (arrays of quads), or `{ quad, messageIndex }` objects, and produces text.
|
|
4
4
|
import { Transform } from 'stream';
|
|
5
5
|
import MessageWriter from './MessageWriter.js';
|
|
6
6
|
|
|
@@ -13,7 +13,9 @@ export default class MessageStreamWriter extends Transform {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
_transform(message, encoding, done) {
|
|
16
|
-
|
|
16
|
+
// A message (array of quads), or a quad of a message: `{ quad, messageIndex }`
|
|
17
|
+
if (Array.isArray(message)) this._writer.addMessage(message, done);
|
|
18
|
+
else this._writer.addQuad(message.quad, message.messageIndex, done);
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
_flush(done) {
|
package/src/MessageWriter.js
CHANGED
|
@@ -37,6 +37,8 @@ export default class MessageWriter {
|
|
|
37
37
|
this._error = null;
|
|
38
38
|
this._started = false;
|
|
39
39
|
this._ended = false;
|
|
40
|
+
this._open = false;
|
|
41
|
+
this._count = 0; // messages begun so far: the index of the next message
|
|
40
42
|
this._declared = Object.assign({}, options.prefixes);
|
|
41
43
|
this._newPrefixes = {};
|
|
42
44
|
// The N3.js writer writes to this sink, which it never ends
|
|
@@ -48,8 +50,38 @@ export default class MessageWriter {
|
|
|
48
50
|
// The callback (or returned promise) completes once the output is flushed.
|
|
49
51
|
addMessage(quads, done) {
|
|
50
52
|
return this._complete(done, () => {
|
|
51
|
-
this.
|
|
52
|
-
this.
|
|
53
|
+
if (this._open) throw new Error('A message is already open');
|
|
54
|
+
this._begin();
|
|
55
|
+
for (const quad of quads || []) this._add(quad);
|
|
56
|
+
this._close();
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ### `beginMessage` opens a message. It is optional: the first `addQuad` opens one implicitly.
|
|
61
|
+
beginMessage(done) {
|
|
62
|
+
return this._complete(done, () => {
|
|
63
|
+
if (this._open) throw new Error('A message is already open');
|
|
64
|
+
this._begin();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ### `addQuad` writes a quad into the open message right away (a message is opened if there is none).
|
|
69
|
+
// With a `messageIndex` (0-based), a change of index ends the current message and writes the empty
|
|
70
|
+
// messages in between, as rdf-writer-ts does; a lower index than the current one is an error.
|
|
71
|
+
addQuad(quad, messageIndex, done) {
|
|
72
|
+
if (typeof messageIndex === 'function') done = messageIndex, messageIndex = undefined;
|
|
73
|
+
return this._complete(done, () => {
|
|
74
|
+
if (messageIndex !== undefined && messageIndex !== null) this._moveTo(messageIndex);
|
|
75
|
+
else if (!this._open) this._begin();
|
|
76
|
+
this._add(quad);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ### `endMessage` ends the open message with a delimiter. Without an open message, it writes an empty one.
|
|
81
|
+
endMessage(done) {
|
|
82
|
+
return this._complete(done, () => {
|
|
83
|
+
if (!this._open) this._begin();
|
|
84
|
+
this._close();
|
|
53
85
|
});
|
|
54
86
|
}
|
|
55
87
|
|
|
@@ -69,6 +101,8 @@ export default class MessageWriter {
|
|
|
69
101
|
if (this._ended)
|
|
70
102
|
return typeof done === 'function' ? done(null) : Promise.resolve();
|
|
71
103
|
this._start();
|
|
104
|
+
if (this._open)
|
|
105
|
+
this._close();
|
|
72
106
|
if (typeof done === 'function')
|
|
73
107
|
return this._finish(done);
|
|
74
108
|
return new Promise((resolve, reject) => this._finish((error, result) => error ? reject(error) : resolve(result)));
|
|
@@ -165,17 +199,39 @@ export default class MessageWriter {
|
|
|
165
199
|
}
|
|
166
200
|
}
|
|
167
201
|
|
|
168
|
-
|
|
202
|
+
// Opens a message: declares the prefixes that were added since the previous one
|
|
203
|
+
_begin() {
|
|
204
|
+
this._start();
|
|
169
205
|
const writer = this._writer;
|
|
170
206
|
for (const prefix of Object.keys(this._newPrefixes)) {
|
|
171
207
|
writer.addPrefix(prefix, this._newPrefixes[prefix]);
|
|
172
208
|
this._declared[prefix] = this._newPrefixes[prefix];
|
|
173
209
|
}
|
|
174
210
|
this._newPrefixes = {};
|
|
211
|
+
this._open = true;
|
|
212
|
+
this._count++;
|
|
213
|
+
}
|
|
214
|
+
_add(quad) {
|
|
175
215
|
const record = error => error && (this._error = this._error || error);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
216
|
+
this._writer.addQuad(quad.subject, quad.predicate, quad.object, quad.graph, record);
|
|
217
|
+
}
|
|
218
|
+
_close() {
|
|
219
|
+
this._open = false;
|
|
220
|
+
this._writer.addDelimiter();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Makes message `index` the open message, writing empty messages for the gap
|
|
224
|
+
_moveTo(index) {
|
|
225
|
+
const current = this._count - 1;
|
|
226
|
+
if (!Number.isInteger(index) || index < 0) throw new RangeError(`Invalid message index: ${index}`);
|
|
227
|
+
if (this._open && index === current) return;
|
|
228
|
+
if (index <= current) throw new RangeError(`Message index ${index} is lower than the current message index ${current}`);
|
|
229
|
+
if (this._open) this._close();
|
|
230
|
+
while (this._count < index) {
|
|
231
|
+
this._begin();
|
|
232
|
+
this._close();
|
|
233
|
+
}
|
|
234
|
+
this._begin();
|
|
179
235
|
}
|
|
180
236
|
}
|
|
181
237
|
|