@blackcatinformatics/purrdf 0.4.3 → 0.5.0

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
@@ -73,7 +73,7 @@ const names = engine.select(
73
73
  reparsed,
74
74
  "SELECT ?message WHERE { <https://ex/s> <https://ex/says> ?message }",
75
75
  );
76
- console.log(names.rows[0].message.value);
76
+ console.log(names.rows.take(0)?.message.value);
77
77
  ```
78
78
 
79
79
  ## API surface
@@ -95,7 +95,9 @@ console.log(names.rows[0].message.value);
95
95
  - `QueryEngine` — a reusable SPARQL execution context with a native plan cache,
96
96
  typed `select` / `ask` / `construct` / `describe` helpers, atomic `update`,
97
97
  and `queryRaw` serialization for SPARQL Results JSON/XML/CSV/TSV plus graph
98
- formats. `Dataset.query(...)` remains as the compatibility raw-string helper.
98
+ formats. SELECT `rows` are a single-owner iterable; use `take(index)`,
99
+ `toArray()`, or iteration, and call `free()` when abandoning unconsumed rows.
100
+ `Dataset.query(...)` remains as the compatibility raw-string helper.
99
101
  - `shaclValidateToSarif(shapesTtl, dataNt)` / `shaclEntail(shapesTtl, dataNt)` — SHACL
100
102
  validation to a SARIF 2.1.0 report and SHACL-AF `sh:rule` entailment to N-Triples.
101
103
  - `Sink`, `datasetToStream`, `streamToDataset` — the async RDF/JS
package/index.d.ts CHANGED
@@ -63,10 +63,26 @@ export interface QueryRawOptions extends QueryOptions {
63
63
 
64
64
  export type QueryBindingRow = Record<string, RdfTerm | undefined>;
65
65
 
66
+ export interface QueryBindingRows extends IterableIterator<QueryBindingRow> {
67
+ /** Total row count, including rows already consumed. */
68
+ readonly length: number;
69
+ /** Rows not yet consumed. */
70
+ readonly remaining: number;
71
+ /** Move one row out by result index. Each index can be consumed once. */
72
+ take(index: number): QueryBindingRow | undefined;
73
+ /** Materialize all remaining rows and exhaust the stream. */
74
+ toArray(): QueryBindingRow[];
75
+ /** Release unconsumed wasm result storage. */
76
+ free(): void;
77
+ }
78
+
66
79
  export interface SelectResult {
67
80
  readonly kind: "select";
68
81
  readonly variables: string[];
69
- readonly rows: QueryBindingRow[];
82
+ readonly rowCount: number;
83
+ readonly rows: QueryBindingRows;
84
+ /** Release unconsumed wasm result storage. */
85
+ free(): void;
70
86
  }
71
87
 
72
88
  export interface AskResult {
package/index.mjs CHANGED
@@ -70,21 +70,63 @@ function visualizationOptionsJson(options) {
70
70
 
71
71
  function selectResultToObject(raw) {
72
72
  const variables = raw.variables;
73
- const rawRows = raw.rows;
74
- try {
75
- const rows = rawRows.map((row) => {
73
+ const length = raw.rowCount;
74
+ let closed = false;
75
+
76
+ const close = () => {
77
+ if (closed) return;
78
+ closed = true;
79
+ raw.free?.();
80
+ };
81
+ if (length === 0) close();
82
+ const materialize = (row) => {
83
+ try {
76
84
  const out = Object.create(null);
77
- for (const variable of variables) {
78
- const value = row.get(variable);
85
+ for (let index = 0; index < variables.length; index += 1) {
86
+ const variable = variables[index];
87
+ const value = row.takeValue(index);
79
88
  if (value !== undefined) out[variable] = value;
80
89
  }
81
90
  return out;
82
- });
83
- return { kind: "select", variables, rows };
84
- } finally {
85
- for (const row of rawRows) row.free?.();
86
- raw.free?.();
87
- }
91
+ } finally {
92
+ row.free?.();
93
+ if (raw.remaining === 0) close();
94
+ }
95
+ };
96
+ const rows = {
97
+ get length() {
98
+ return length;
99
+ },
100
+ get remaining() {
101
+ return closed ? 0 : raw.remaining;
102
+ },
103
+ take(index) {
104
+ if (closed) return undefined;
105
+ const row = raw.takeRow(index);
106
+ return row === undefined ? undefined : materialize(row);
107
+ },
108
+ next() {
109
+ if (closed) return { done: true, value: undefined };
110
+ const row = raw.nextRow();
111
+ if (row === undefined) {
112
+ close();
113
+ return { done: true, value: undefined };
114
+ }
115
+ return { done: false, value: materialize(row) };
116
+ },
117
+ return() {
118
+ close();
119
+ return { done: true, value: undefined };
120
+ },
121
+ toArray() {
122
+ return Array.from(this);
123
+ },
124
+ free: close,
125
+ [Symbol.iterator]() {
126
+ return this;
127
+ },
128
+ };
129
+ return { kind: "select", variables, rowCount: length, rows, free: close };
88
130
  }
89
131
 
90
132
  function queryResultToObject(raw) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blackcatinformatics/purrdf",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "description": "A wasm32, in-memory RDF 1.2 engine with an idiomatic RDF/JS (DataFactory/Dataset/Stream) API. Quoted-triple terms and directional literals included.",
5
5
  "type": "module",
6
6
  "license": "MIT OR Apache-2.0",
@@ -282,14 +282,26 @@ export class SelectResult {
282
282
  private constructor();
283
283
  free(): void;
284
284
  [Symbol.dispose](): void;
285
+ /**
286
+ * Move the next unconsumed row out of the result.
287
+ */
288
+ nextRow(): SelectRow | undefined;
289
+ /**
290
+ * Move a row out by result index. Each row can be consumed once.
291
+ */
292
+ takeRow(index: number): SelectRow | undefined;
285
293
  /**
286
294
  * The result discriminator.
287
295
  */
288
296
  readonly kind: string;
289
297
  /**
290
- * SELECT rows, one object-like row per solution.
298
+ * Number of rows that have not yet been consumed.
291
299
  */
292
- readonly rows: SelectRow[];
300
+ readonly remaining: number;
301
+ /**
302
+ * Total number of SELECT rows, including rows already consumed.
303
+ */
304
+ readonly rowCount: number;
293
305
  /**
294
306
  * Projected variables, in SELECT projection order.
295
307
  */
@@ -307,6 +319,11 @@ export class SelectRow {
307
319
  * Return the bound term for a variable name, or `undefined` for unbound/absent.
308
320
  */
309
321
  get(variable: string): Term | undefined;
322
+ /**
323
+ * Move one value out by projection index, or return `undefined` when the
324
+ * cell is unbound, absent, or was already consumed.
325
+ */
326
+ takeValue(index: number): Term | undefined;
310
327
  /**
311
328
  * Variables projected by this row, in SELECT projection order.
312
329
  */
@@ -474,9 +491,13 @@ export interface InitOutput {
474
491
  readonly queryresult_takeDataset: (a: number) => number;
475
492
  readonly queryresult_takeSelect: (a: number) => number;
476
493
  readonly selectresult_kind: (a: number, b: number) => void;
477
- readonly selectresult_rows: (a: number, b: number) => void;
494
+ readonly selectresult_nextRow: (a: number) => number;
495
+ readonly selectresult_remaining: (a: number) => number;
496
+ readonly selectresult_row_count: (a: number) => number;
497
+ readonly selectresult_takeRow: (a: number, b: number) => number;
478
498
  readonly selectresult_variables: (a: number, b: number) => void;
479
499
  readonly selectrow_get: (a: number, b: number, c: number) => number;
500
+ readonly selectrow_takeValue: (a: number, b: number) => number;
480
501
  readonly selectrow_variables: (a: number, b: number) => void;
481
502
  readonly shaclEntail: (a: number, b: number, c: number, d: number, e: number) => void;
482
503
  readonly shaclValidateToSarif: (a: number, b: number, c: number, d: number, e: number) => void;
@@ -1112,21 +1112,37 @@ export class SelectResult {
1112
1112
  }
1113
1113
  }
1114
1114
  /**
1115
- * SELECT rows, one object-like row per solution.
1116
- * @returns {SelectRow[]}
1115
+ * Move the next unconsumed row out of the result.
1116
+ * @returns {SelectRow | undefined}
1117
1117
  */
1118
- get rows() {
1119
- try {
1120
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1121
- wasm.selectresult_rows(retptr, this.__wbg_ptr);
1122
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1123
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1124
- var v1 = getArrayJsValueFromWasm0(r0, r1).slice();
1125
- wasm.__wbindgen_export3(r0, r1 * 4, 4);
1126
- return v1;
1127
- } finally {
1128
- wasm.__wbindgen_add_to_stack_pointer(16);
1129
- }
1118
+ nextRow() {
1119
+ const ret = wasm.selectresult_nextRow(this.__wbg_ptr);
1120
+ return ret === 0 ? undefined : SelectRow.__wrap(ret);
1121
+ }
1122
+ /**
1123
+ * Number of rows that have not yet been consumed.
1124
+ * @returns {number}
1125
+ */
1126
+ get remaining() {
1127
+ const ret = wasm.selectresult_remaining(this.__wbg_ptr);
1128
+ return ret >>> 0;
1129
+ }
1130
+ /**
1131
+ * Total number of SELECT rows, including rows already consumed.
1132
+ * @returns {number}
1133
+ */
1134
+ get rowCount() {
1135
+ const ret = wasm.selectresult_row_count(this.__wbg_ptr);
1136
+ return ret >>> 0;
1137
+ }
1138
+ /**
1139
+ * Move a row out by result index. Each row can be consumed once.
1140
+ * @param {number} index
1141
+ * @returns {SelectRow | undefined}
1142
+ */
1143
+ takeRow(index) {
1144
+ const ret = wasm.selectresult_takeRow(this.__wbg_ptr, index);
1145
+ return ret === 0 ? undefined : SelectRow.__wrap(ret);
1130
1146
  }
1131
1147
  /**
1132
1148
  * Projected variables, in SELECT projection order.
@@ -1179,6 +1195,16 @@ export class SelectRow {
1179
1195
  const ret = wasm.selectrow_get(this.__wbg_ptr, ptr0, len0);
1180
1196
  return ret === 0 ? undefined : Term.__wrap(ret);
1181
1197
  }
1198
+ /**
1199
+ * Move one value out by projection index, or return `undefined` when the
1200
+ * cell is unbound, absent, or was already consumed.
1201
+ * @param {number} index
1202
+ * @returns {Term | undefined}
1203
+ */
1204
+ takeValue(index) {
1205
+ const ret = wasm.selectrow_takeValue(this.__wbg_ptr, index);
1206
+ return ret === 0 ? undefined : Term.__wrap(ret);
1207
+ }
1182
1208
  /**
1183
1209
  * Variables projected by this row, in SELECT projection order.
1184
1210
  * @returns {string[]}
@@ -1544,10 +1570,6 @@ function __wbg_get_imports() {
1544
1570
  const ret = Math.random();
1545
1571
  return ret;
1546
1572
  },
1547
- __wbg_selectrow_new: function(arg0) {
1548
- const ret = SelectRow.__wrap(arg0);
1549
- return addHeapObject(ret);
1550
- },
1551
1573
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
1552
1574
  // Cast intrinsic for `Ref(String) -> Externref`.
1553
1575
  const ret = getStringFromWasm0(arg0, arg1);
Binary file
@@ -57,9 +57,13 @@ export const queryresult_kind: (a: number, b: number) => void;
57
57
  export const queryresult_takeDataset: (a: number) => number;
58
58
  export const queryresult_takeSelect: (a: number) => number;
59
59
  export const selectresult_kind: (a: number, b: number) => void;
60
- export const selectresult_rows: (a: number, b: number) => void;
60
+ export const selectresult_nextRow: (a: number) => number;
61
+ export const selectresult_remaining: (a: number) => number;
62
+ export const selectresult_row_count: (a: number) => number;
63
+ export const selectresult_takeRow: (a: number, b: number) => number;
61
64
  export const selectresult_variables: (a: number, b: number) => void;
62
65
  export const selectrow_get: (a: number, b: number, c: number) => number;
66
+ export const selectrow_takeValue: (a: number, b: number) => number;
63
67
  export const selectrow_variables: (a: number, b: number) => void;
64
68
  export const shaclEntail: (a: number, b: number, c: number, d: number, e: number) => void;
65
69
  export const shaclValidateToSarif: (a: number, b: number, c: number, d: number, e: number) => void;