rdfjs-jelly 0.2.0 → 0.2.1

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 CHANGED
@@ -13,7 +13,7 @@ Jelly-RDF and Jelly-SPARQL binary parsers and writers using RDF/JS terms, for No
13
13
  ## Support
14
14
 
15
15
  - Reads Jelly-RDF 1.0, 1.1, and 1.2 (protocol tags 1, 2, and 3).
16
- - Writes Jelly-RDF 1.1 by default; opt into 1.2 with `version: 3`.
16
+ - Writes packed Jelly-RDF 1.2 by default; use `version: 2` for Jelly 1.1.
17
17
  - Supports physical triple, quad, and graph streams; delimited and non-delimited encoding; lookup/repeated-term compression; namespaces; and message metadata.
18
18
  - Reads and writes Jelly-SPARQL 1.0 SELECT and ASK result sets, including punctuated streams.
19
19
  - Uses RDF/JS terms and accepts a custom RDF/JS data factory.
@@ -98,7 +98,9 @@ writer.end((error, bytes) => {
98
98
  });
99
99
  ```
100
100
 
101
- `Writer` emits a delimited Jelly 1.1 stream (protocol tag 2) by default. Set
101
+ `Writer`, Node `StreamWriter`, and browser `StreamWriter` emit delimited Jelly 1.2
102
+ streams (protocol tag 3) with message packing enabled by default. Use `version: 2`
103
+ for Jelly 1.1 compatibility. Set
102
104
  `delimited: false` for one bare protobuf frame. All output must fit in that frame;
103
105
  a Jelly 1.2 frame can contain several logical messages when packing is enabled.
104
106
 
@@ -108,7 +110,7 @@ a Jelly 1.2 frame can contain several logical messages when packing is enabled.
108
110
  introduces a column layout (protocol tag **3**), packed lookup entries, repeat
109
111
  runs, RDF 1.2 terms, explicit RDF Message boundaries, and concatenable streams.
110
112
  The parser selects the layout from the stream options. Existing 1.0/1.1 streams
111
- remain readable, and the default writer stays on 1.1 for older consumers.
113
+ remain readable; pass `version: 2` to write Jelly 1.1 for older consumers.
112
114
 
113
115
  ```ts
114
116
  import { DataFactory, Parser, Writer, RdfStreamType, RdfVersion } from 'rdfjs-jelly';
@@ -157,7 +159,7 @@ callback it throws. Flushing requires delimited output. Packing has no timer:
157
159
  use explicit flushes or `packMessages: false` for latency-sensitive delivery.
158
160
 
159
161
  The 1.2 layout supports `TRIPLES` and `QUADS`. Use `QUADS` for named graphs;
160
- `GRAPHS`, `addGraph()`, and `logicalType` belong to the older layout. Use
162
+ `GRAPHS`, `addGraph()`, and `logicalType` require `version: 2`. Use
161
163
  `streamType` (`FLAT` or `MESSAGES`) instead. `rdfVersion` defaults to RDF 1.2;
162
164
  writers reject terms that the declared version cannot represent. Custom factories
163
165
  must preserve direction and `rdf:dirLangString` for directional literals.
@@ -232,6 +234,57 @@ With `messages: true`, output items are wrapped entries and a `messageCounter`
232
234
  event accompanies each quad. Quad-only output cannot represent empty messages;
233
235
  retain the `message` events if forwarding a message stream.
234
236
 
237
+ ## Quad-pattern filtering
238
+
239
+ Since 0.2.1, `Parser`, Node `StreamParser`, and browser `StreamParser` accept
240
+ `quadPatterns`:
241
+
242
+ ```ts
243
+ import { DataFactory, Parser } from 'rdfjs-jelly';
244
+
245
+ const parser = new Parser({
246
+ quadPatterns: [
247
+ { predicate: DataFactory.namedNode('http://example.org/name') },
248
+ { predicate: DataFactory.namedNode('http://example.org/knows') },
249
+ ],
250
+ });
251
+ const selectedQuads = parser.parse(bytes);
252
+ ```
253
+
254
+ Patterns are combined with OR; positions within a pattern are combined with AND.
255
+ An omitted or `null` position is a wildcard. Omit `quadPatterns` to select all
256
+ quads; `[]` selects none, and `[{}]` selects all. Matching preserves input order
257
+ and duplicates, without duplicating quads that match several patterns.
258
+ `QuadPattern` is exported as a TypeScript type.
259
+
260
+ Jelly 1.2 matches column values before constructing RDF/JS terms or quads. When
261
+ every pattern pins the same position (subject, object, predicate or graph) to an
262
+ IRI, that column alone chooses the rows: each distinct IRI is judged once, and the
263
+ other columns, including literal text, are built only for the selected rows. Only
264
+ selected values reach your data factory. Patterns that also constrain other
265
+ positions are checked on those few candidates. Patterns that share no IRI-pinned
266
+ position (for example a literal-only object, or an OR of patterns on different
267
+ positions) use a slower path that, in our measurements, is not faster than
268
+ parsing everything and filtering afterwards.
269
+ Lookup updates and validation still run for rejected statements, so malformed
270
+ input is still rejected. Errors that depend on your data factory, such as a
271
+ directional literal it cannot build, surface only for selected statements. The
272
+ filter does not skip bytes, files or decompression.
273
+ Jelly 1.0/1.1 also support filtering, after term decoding and before quad creation.
274
+ Namespaces remain available regardless of the filter. See
275
+ [PERFORMANCE.md](PERFORMANCE.md#pushing-down-a-filter-to-the-parser) for measurements.
276
+
277
+ Filtering keeps empty messages, message counters and metadata. A message with no
278
+ matching quads becomes empty; use `parseMessages()` or stream `message` events to
279
+ retain its boundary. Plain quad output contains only selected statements.
280
+
281
+ Terms match by kind and value. Literal equality includes datatype, language
282
+ (case-insensitive) and direction; plain strings equal explicit `xsd:string`
283
+ literals. Triple terms match recursively. Graph patterns distinguish named,
284
+ blank-node and default graphs. Blank-node patterns use the labels in parser
285
+ output, including the opaque message scope in Jelly 1.2; raw labels from the
286
+ input are not identifiers across independent messages.
287
+
235
288
  ## SPARQL result sets
236
289
 
237
290
  [Jelly-SPARQL 1.0.0](https://jelly-rdf.github.io/1.2.x/specification/sparql/)
@@ -71,7 +71,18 @@ interface StreamOptions {
71
71
  streamType?: RdfStreamType;
72
72
  rdfVersion?: RdfVersion;
73
73
  }
74
+ /** Positions within a pattern are ANDed; patterns are ORed. Omitted or null
75
+ * positions are wildcards. Blank-node labels refer to parser output labels. */
76
+ interface QuadPattern {
77
+ subject?: RDF.Term | null;
78
+ predicate?: RDF.Term | null;
79
+ object?: RDF.Term | null;
80
+ graph?: RDF.Term | null;
81
+ }
74
82
  interface ParserOptions {
83
+ /** Select quads before RDF/JS materialization in Jelly 1.2. An empty array
84
+ * selects no quads. Message boundaries, counters and metadata are retained. */
85
+ quadPatterns?: readonly QuadPattern[];
75
86
  factory?: RDF.DataFactory;
76
87
  delimited?: boolean | 'auto';
77
88
  strict?: boolean;
@@ -105,7 +116,7 @@ interface WriterOptions {
105
116
  streamName?: string;
106
117
  namespaces?: Record<string, string | RDF.NamedNode>;
107
118
  lookup?: Partial<LookupPreset>;
108
- /** Protocol tag: 2 = Jelly 1.1 (default), 3 = Jelly 1.2. */
119
+ /** Protocol tag: 2 = Jelly 1.1, 3 = Jelly 1.2 (default). */
109
120
  version?: 2 | 3;
110
121
  streamType?: RdfStreamType;
111
122
  rdfVersion?: RdfVersion;
@@ -2976,6 +2987,7 @@ interface DecoderEvents {
2976
2987
  options?: OptionsListener;
2977
2988
  }
2978
2989
  declare class Decoder {
2990
+ private readonly patterns;
2979
2991
  private columns?;
2980
2992
  private columnReader?;
2981
2993
  private readonly parserOptions;
@@ -3009,6 +3021,7 @@ declare class Decoder {
3009
3021
  decodeProtoPayloadTo(rawReader: unknown, length: number, output: RDF.Quad[]): void;
3010
3022
  private consumeProtoRow;
3011
3023
  private emitQuad;
3024
+ private makeQuad;
3012
3025
  private decodeWireLookupEntry;
3013
3026
  private decodeWireTriple;
3014
3027
  /**
@@ -3197,10 +3210,18 @@ declare class LookupDecoder {
3197
3210
  * declare a large table without the parser paying for entries it never fills.
3198
3211
  */
3199
3212
  private readonly data;
3213
+ /** Version of each slot, changed by every assignment; zero while unassigned. */
3214
+ private readonly stamps;
3200
3215
  private lastAssignedIndex;
3201
3216
  private lastReusedIndex;
3217
+ /** Called with the index of an assigned entry just before it is overwritten, the only way a value derived from an entry can go stale. */
3218
+ onReplace?: (index: number) => void;
3219
+ /** Entries `1..contiguous` are all assigned, so a reference up to it needs no further check. */
3220
+ contiguous: number;
3202
3221
  constructor(size: number, limit?: number);
3203
3222
  assign(index: number, value: string): void;
3223
+ /** Version of the entry at `index`, or 0 when it is outside the table or unassigned. */
3224
+ stamp(index: number): number;
3204
3225
  /** Extend the backing array by doubling, staying packed and capped at the table size. */
3205
3226
  private reserve;
3206
3227
  private at;
@@ -3515,4 +3536,4 @@ declare class StreamWriter {
3515
3536
  import(stream: ReadableStream<RDF.Quad | MessageQuad>): ReadableStream<Uint8Array>;
3516
3537
  }
3517
3538
 
3518
- export { type BinaryInput, type BinaryOutput, BlankNode, type BrowserStreamChunk, ColumnEncoder, DEFAULT_LOOKUP_PRESET, DataFactory, Decoder, DefaultGraph, Encoder, JellyConformanceError, JellyError, JellySparqlResultError, JellyUnsupportedFeatureError, Literal, LogicalStreamType, LookupDecoder, LookupEncoder, type LookupPreset, MAX_LOOKUP_SIZE, MIN_NAME_LOOKUP_SIZE, Message, MessageDecoder, MessageEncoder, type MessageMetadata, type MessageQuad, type MessageQuadArray, NamedNode, type ParseCallback, Parser, type ParserOptions, type ParserOutput, type ParserOutputItem, PhysicalStreamType, Quad, RDF_DIR_LANG_STRING, RDF_LANG_STRING, RdfStreamType, RdfVersion, SMALL_LOOKUP_PRESET, SparqlAskResult, type SparqlBinding, type SparqlEvent, SparqlParser, type SparqlParserOptions, type SparqlResult, type SparqlResultInfo, type SparqlResultMetadata, type SparqlSelectResult, SparqlStreamParser, SparqlStreamType, SparqlStreamWriter, type SparqlTerm, type SparqlWritableResult, SparqlWriter, type SparqlWriterOptions, type StreamOptions, StreamParser, StreamWriter, Variable, Writer, type WriterEndCallback, type WriterOptions, XSD_STRING, delimitedJellyHint, isMessageQuad, normalizeLookupPreset, toMessages };
3539
+ export { type BinaryInput, type BinaryOutput, BlankNode, type BrowserStreamChunk, ColumnEncoder, DEFAULT_LOOKUP_PRESET, DataFactory, Decoder, DefaultGraph, Encoder, JellyConformanceError, JellyError, JellySparqlResultError, JellyUnsupportedFeatureError, Literal, LogicalStreamType, LookupDecoder, LookupEncoder, type LookupPreset, MAX_LOOKUP_SIZE, MIN_NAME_LOOKUP_SIZE, Message, MessageDecoder, MessageEncoder, type MessageMetadata, type MessageQuad, type MessageQuadArray, NamedNode, type ParseCallback, Parser, type ParserOptions, type ParserOutput, type ParserOutputItem, PhysicalStreamType, Quad, type QuadPattern, RDF_DIR_LANG_STRING, RDF_LANG_STRING, RdfStreamType, RdfVersion, SMALL_LOOKUP_PRESET, SparqlAskResult, type SparqlBinding, type SparqlEvent, SparqlParser, type SparqlParserOptions, type SparqlResult, type SparqlResultInfo, type SparqlResultMetadata, type SparqlSelectResult, SparqlStreamParser, SparqlStreamType, SparqlStreamWriter, type SparqlTerm, type SparqlWritableResult, SparqlWriter, type SparqlWriterOptions, type StreamOptions, StreamParser, StreamWriter, Variable, Writer, type WriterEndCallback, type WriterOptions, XSD_STRING, delimitedJellyHint, isMessageQuad, normalizeLookupPreset, toMessages };
@@ -71,7 +71,18 @@ interface StreamOptions {
71
71
  streamType?: RdfStreamType;
72
72
  rdfVersion?: RdfVersion;
73
73
  }
74
+ /** Positions within a pattern are ANDed; patterns are ORed. Omitted or null
75
+ * positions are wildcards. Blank-node labels refer to parser output labels. */
76
+ interface QuadPattern {
77
+ subject?: RDF.Term | null;
78
+ predicate?: RDF.Term | null;
79
+ object?: RDF.Term | null;
80
+ graph?: RDF.Term | null;
81
+ }
74
82
  interface ParserOptions {
83
+ /** Select quads before RDF/JS materialization in Jelly 1.2. An empty array
84
+ * selects no quads. Message boundaries, counters and metadata are retained. */
85
+ quadPatterns?: readonly QuadPattern[];
75
86
  factory?: RDF.DataFactory;
76
87
  delimited?: boolean | 'auto';
77
88
  strict?: boolean;
@@ -105,7 +116,7 @@ interface WriterOptions {
105
116
  streamName?: string;
106
117
  namespaces?: Record<string, string | RDF.NamedNode>;
107
118
  lookup?: Partial<LookupPreset>;
108
- /** Protocol tag: 2 = Jelly 1.1 (default), 3 = Jelly 1.2. */
119
+ /** Protocol tag: 2 = Jelly 1.1, 3 = Jelly 1.2 (default). */
109
120
  version?: 2 | 3;
110
121
  streamType?: RdfStreamType;
111
122
  rdfVersion?: RdfVersion;
@@ -2976,6 +2987,7 @@ interface DecoderEvents {
2976
2987
  options?: OptionsListener;
2977
2988
  }
2978
2989
  declare class Decoder {
2990
+ private readonly patterns;
2979
2991
  private columns?;
2980
2992
  private columnReader?;
2981
2993
  private readonly parserOptions;
@@ -3009,6 +3021,7 @@ declare class Decoder {
3009
3021
  decodeProtoPayloadTo(rawReader: unknown, length: number, output: RDF.Quad[]): void;
3010
3022
  private consumeProtoRow;
3011
3023
  private emitQuad;
3024
+ private makeQuad;
3012
3025
  private decodeWireLookupEntry;
3013
3026
  private decodeWireTriple;
3014
3027
  /**
@@ -3197,10 +3210,18 @@ declare class LookupDecoder {
3197
3210
  * declare a large table without the parser paying for entries it never fills.
3198
3211
  */
3199
3212
  private readonly data;
3213
+ /** Version of each slot, changed by every assignment; zero while unassigned. */
3214
+ private readonly stamps;
3200
3215
  private lastAssignedIndex;
3201
3216
  private lastReusedIndex;
3217
+ /** Called with the index of an assigned entry just before it is overwritten, the only way a value derived from an entry can go stale. */
3218
+ onReplace?: (index: number) => void;
3219
+ /** Entries `1..contiguous` are all assigned, so a reference up to it needs no further check. */
3220
+ contiguous: number;
3202
3221
  constructor(size: number, limit?: number);
3203
3222
  assign(index: number, value: string): void;
3223
+ /** Version of the entry at `index`, or 0 when it is outside the table or unassigned. */
3224
+ stamp(index: number): number;
3204
3225
  /** Extend the backing array by doubling, staying packed and capped at the table size. */
3205
3226
  private reserve;
3206
3227
  private at;
@@ -3515,4 +3536,4 @@ declare class StreamWriter {
3515
3536
  import(stream: ReadableStream<RDF.Quad | MessageQuad>): ReadableStream<Uint8Array>;
3516
3537
  }
3517
3538
 
3518
- export { type BinaryInput, type BinaryOutput, BlankNode, type BrowserStreamChunk, ColumnEncoder, DEFAULT_LOOKUP_PRESET, DataFactory, Decoder, DefaultGraph, Encoder, JellyConformanceError, JellyError, JellySparqlResultError, JellyUnsupportedFeatureError, Literal, LogicalStreamType, LookupDecoder, LookupEncoder, type LookupPreset, MAX_LOOKUP_SIZE, MIN_NAME_LOOKUP_SIZE, Message, MessageDecoder, MessageEncoder, type MessageMetadata, type MessageQuad, type MessageQuadArray, NamedNode, type ParseCallback, Parser, type ParserOptions, type ParserOutput, type ParserOutputItem, PhysicalStreamType, Quad, RDF_DIR_LANG_STRING, RDF_LANG_STRING, RdfStreamType, RdfVersion, SMALL_LOOKUP_PRESET, SparqlAskResult, type SparqlBinding, type SparqlEvent, SparqlParser, type SparqlParserOptions, type SparqlResult, type SparqlResultInfo, type SparqlResultMetadata, type SparqlSelectResult, SparqlStreamParser, SparqlStreamType, SparqlStreamWriter, type SparqlTerm, type SparqlWritableResult, SparqlWriter, type SparqlWriterOptions, type StreamOptions, StreamParser, StreamWriter, Variable, Writer, type WriterEndCallback, type WriterOptions, XSD_STRING, delimitedJellyHint, isMessageQuad, normalizeLookupPreset, toMessages };
3539
+ export { type BinaryInput, type BinaryOutput, BlankNode, type BrowserStreamChunk, ColumnEncoder, DEFAULT_LOOKUP_PRESET, DataFactory, Decoder, DefaultGraph, Encoder, JellyConformanceError, JellyError, JellySparqlResultError, JellyUnsupportedFeatureError, Literal, LogicalStreamType, LookupDecoder, LookupEncoder, type LookupPreset, MAX_LOOKUP_SIZE, MIN_NAME_LOOKUP_SIZE, Message, MessageDecoder, MessageEncoder, type MessageMetadata, type MessageQuad, type MessageQuadArray, NamedNode, type ParseCallback, Parser, type ParserOptions, type ParserOutput, type ParserOutputItem, PhysicalStreamType, Quad, type QuadPattern, RDF_DIR_LANG_STRING, RDF_LANG_STRING, RdfStreamType, RdfVersion, SMALL_LOOKUP_PRESET, SparqlAskResult, type SparqlBinding, type SparqlEvent, SparqlParser, type SparqlParserOptions, type SparqlResult, type SparqlResultInfo, type SparqlResultMetadata, type SparqlSelectResult, SparqlStreamParser, SparqlStreamType, SparqlStreamWriter, type SparqlTerm, type SparqlWritableResult, SparqlWriter, type SparqlWriterOptions, type StreamOptions, StreamParser, StreamWriter, Variable, Writer, type WriterEndCallback, type WriterOptions, XSD_STRING, delimitedJellyHint, isMessageQuad, normalizeLookupPreset, toMessages };