@lde/pipeline 0.6.12 → 0.6.13

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.
@@ -1,11 +1,13 @@
1
1
  import { Dataset, Distribution } from '@lde/dataset';
2
2
  import { SparqlEndpointFetcher } from 'fetch-sparql-endpoint';
3
- import type { Quad, Stream } from '@rdfjs/types';
3
+ import type { NamedNode, Quad, Stream } from '@rdfjs/types';
4
4
  import type { Readable } from 'node:stream';
5
5
  import { NotSupported } from '../step.js';
6
6
  export { NotSupported } from '../step.js';
7
+ /** A single row of variable bindings (variable name → NamedNode). */
8
+ export type VariableBindings = Record<string, NamedNode>;
7
9
  export interface Executor {
8
- execute(dataset: ExecutableDataset): Promise<AsyncIterable<Quad> | NotSupported>;
10
+ execute(dataset: ExecutableDataset, options?: SparqlConstructExecuteOptions): Promise<AsyncIterable<Quad> | NotSupported>;
9
11
  }
10
12
  /**
11
13
  * A quad stream that is both an RDFJS Stream and Node.js Readable (async iterable).
@@ -49,26 +51,18 @@ export interface SparqlConstructExecuteOptions {
49
51
  */
50
52
  endpoint?: URL;
51
53
  /**
52
- * Variable bindings to substitute in the query before standard template substitution.
53
- * Each key is a literal string to replace, each value is its replacement.
54
- *
55
- * @example
56
- * ```typescript
57
- * await executor.execute(dataset, {
58
- * bindings: { '<#class#>': '<http://schema.org/Person>' },
59
- * });
60
- * ```
54
+ * Variable bindings to inject as a VALUES clause into the query.
55
+ * When non-empty, a VALUES block is prepended to the WHERE clause.
61
56
  */
62
- bindings?: Record<string, string>;
57
+ bindings?: VariableBindings[];
63
58
  }
64
59
  /**
65
- * A streaming SPARQL CONSTRUCT executor with template substitution.
60
+ * A streaming SPARQL CONSTRUCT executor that parses the query once (in the
61
+ * constructor) and operates on the AST for graph and VALUES injection.
66
62
  *
67
- * Supports template substitution (applied in order):
68
- * 1. `bindings`any provided variable bindings
69
- * 2. `#subjectFilter#` — replaced with the distribution's subject filter or dataset's subjectFilter
70
- * 3. `#namedGraph#` — replaced with `FROM <graph>` clause if the distribution has a named graph
71
- * 4. `?dataset` — replaced with the dataset IRI
63
+ * Template substitution (applied in order):
64
+ * 1. `FROM <graph>` set via `withDefaultGraph` if the distribution has a named graph
65
+ * 2. `?dataset` — replaced with the dataset IRI (string substitution on the serialised query)
72
66
  *
73
67
  * @example
74
68
  * ```typescript
@@ -88,19 +82,16 @@ export interface SparqlConstructExecuteOptions {
88
82
  export declare class SparqlConstructExecutor implements Executor {
89
83
  private readonly query;
90
84
  private readonly fetcher;
85
+ private readonly generator;
91
86
  constructor(options: SparqlConstructExecutorOptions);
92
87
  /**
93
88
  * Execute the SPARQL CONSTRUCT query against the dataset's SPARQL endpoint.
94
89
  *
95
90
  * @param dataset The dataset to execute against.
96
- * @param options Optional endpoint override and variable bindings.
91
+ * @param options Optional endpoint override.
97
92
  * @returns AsyncIterable<Quad> stream of results, or NotSupported if no SPARQL endpoint available.
98
93
  */
99
94
  execute(dataset: ExecutableDataset, options?: SparqlConstructExecuteOptions): Promise<QuadStream | NotSupported>;
100
- /**
101
- * Substitute template variables in the query.
102
- */
103
- private substituteTemplates;
104
95
  /**
105
96
  * Create an executor from a query file.
106
97
  *
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/sparql/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,QAAQ;IACvB,OAAO,CACL,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;CAChD;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO;IAChD;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,QAAQ,CAAC,EAAE,GAAG,CAAC;IAEf;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,uBAAwB,YAAW,QAAQ;IACtD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;gBAEpC,OAAO,EAAE,8BAA8B;IASnD;;;;;;OAMG;IACG,OAAO,CACX,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,6BAA6B,GACtC,OAAO,CAAC,UAAU,GAAG,YAAY,CAAC;IAyBrC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAQ3B;;;;;OAKG;WACiB,QAAQ,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,IAAI,CAAC,8BAA8B,EAAE,OAAO,CAAC,GACtD,OAAO,CAAC,uBAAuB,CAAC;CAIpC;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,OAAO,EAAE,iBAAiB,GACzB,MAAM,CAYR;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAErE"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/sparql/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAI5C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,qEAAqE;AACrE,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEzD,MAAM,WAAW,QAAQ;IACvB,OAAO,CACL,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,6BAA6B,GACtC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;CAChD;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO;IAChD;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,QAAQ,CAAC,EAAE,GAAG,CAAC;IAEf;;;OAGG;IACH,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,uBAAwB,YAAW,QAAQ;IACtD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;gBAEjC,OAAO,EAAE,8BAA8B;IAcnD;;;;;;OAMG;IACG,OAAO,CACX,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,6BAA6B,GACtC,OAAO,CAAC,UAAU,GAAG,YAAY,CAAC;IA4BrC;;;;;OAKG;WACiB,QAAQ,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,IAAI,CAAC,8BAA8B,EAAE,OAAO,CAAC,GACtD,OAAO,CAAC,uBAAuB,CAAC;CAIpC;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,OAAO,EAAE,iBAAiB,GACzB,MAAM,CAYR;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAErE"}
@@ -1,17 +1,19 @@
1
1
  import { SparqlEndpointFetcher } from 'fetch-sparql-endpoint';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import { resolve } from 'node:path';
4
+ import { Generator, Parser } from 'sparqljs';
4
5
  import { NotSupported } from '../step.js';
6
+ import { withDefaultGraph } from './graph.js';
7
+ import { injectValues } from './values.js';
5
8
  // Re-export for convenience
6
9
  export { NotSupported } from '../step.js';
7
10
  /**
8
- * A streaming SPARQL CONSTRUCT executor with template substitution.
11
+ * A streaming SPARQL CONSTRUCT executor that parses the query once (in the
12
+ * constructor) and operates on the AST for graph and VALUES injection.
9
13
  *
10
- * Supports template substitution (applied in order):
11
- * 1. `bindings`any provided variable bindings
12
- * 2. `#subjectFilter#` — replaced with the distribution's subject filter or dataset's subjectFilter
13
- * 3. `#namedGraph#` — replaced with `FROM <graph>` clause if the distribution has a named graph
14
- * 4. `?dataset` — replaced with the dataset IRI
14
+ * Template substitution (applied in order):
15
+ * 1. `FROM <graph>` set via `withDefaultGraph` if the distribution has a named graph
16
+ * 2. `?dataset` — replaced with the dataset IRI (string substitution on the serialised query)
15
17
  *
16
18
  * @example
17
19
  * ```typescript
@@ -31,8 +33,14 @@ export { NotSupported } from '../step.js';
31
33
  export class SparqlConstructExecutor {
32
34
  query;
33
35
  fetcher;
36
+ generator = new Generator();
34
37
  constructor(options) {
35
- this.query = options.query;
38
+ const parser = new Parser();
39
+ const parsed = parser.parse(options.query);
40
+ if (parsed.type !== 'query' || parsed.queryType !== 'CONSTRUCT') {
41
+ throw new Error('Query must be a CONSTRUCT query');
42
+ }
43
+ this.query = parsed;
36
44
  this.fetcher =
37
45
  options.fetcher ??
38
46
  new SparqlEndpointFetcher({
@@ -43,7 +51,7 @@ export class SparqlConstructExecutor {
43
51
  * Execute the SPARQL CONSTRUCT query against the dataset's SPARQL endpoint.
44
52
  *
45
53
  * @param dataset The dataset to execute against.
46
- * @param options Optional endpoint override and variable bindings.
54
+ * @param options Optional endpoint override.
47
55
  * @returns AsyncIterable<Quad> stream of results, or NotSupported if no SPARQL endpoint available.
48
56
  */
49
57
  async execute(dataset, options) {
@@ -55,22 +63,18 @@ export class SparqlConstructExecutor {
55
63
  }
56
64
  endpoint = distribution.accessUrl;
57
65
  }
58
- let query = this.query;
59
- // Apply bindings first.
60
- if (options?.bindings) {
61
- for (const [variable, value] of Object.entries(options.bindings)) {
62
- query = query.replaceAll(variable, value);
63
- }
66
+ let ast = structuredClone(this.query);
67
+ if (distribution?.namedGraph) {
68
+ withDefaultGraph(ast, distribution.namedGraph);
69
+ }
70
+ const bindings = options?.bindings;
71
+ if (bindings !== undefined && bindings.length > 0) {
72
+ ast = injectValues(ast, bindings);
64
73
  }
65
- query = this.substituteTemplates(query, distribution, dataset);
74
+ let query = this.generator.stringify(ast);
75
+ query = query.replaceAll('?dataset', `<${dataset.iri}>`);
66
76
  return await this.fetcher.fetchTriples(endpoint.toString(), query);
67
77
  }
68
- /**
69
- * Substitute template variables in the query.
70
- */
71
- substituteTemplates(query, distribution, dataset) {
72
- return substituteQueryTemplates(query, distribution, dataset);
73
- }
74
78
  /**
75
79
  * Create an executor from a query file.
76
80
  *
@@ -0,0 +1,8 @@
1
+ import type { ConstructQuery } from 'sparqljs';
2
+ /**
3
+ * Set the default graph (FROM clause) on a parsed CONSTRUCT query.
4
+ *
5
+ * Mutates the query in place, replacing any existing FROM clause.
6
+ */
7
+ export declare function withDefaultGraph(query: ConstructQuery, graphIri: string): void;
8
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/sparql/graph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,MAAM,GACf,IAAI,CAEN"}
@@ -0,0 +1,9 @@
1
+ import { DataFactory } from 'n3';
2
+ /**
3
+ * Set the default graph (FROM clause) on a parsed CONSTRUCT query.
4
+ *
5
+ * Mutates the query in place, replacing any existing FROM clause.
6
+ */
7
+ export function withDefaultGraph(query, graphIri) {
8
+ query.from = { default: [DataFactory.namedNode(graphIri)], named: [] };
9
+ }
@@ -1,4 +1,6 @@
1
- export { SparqlConstructExecutor, substituteQueryTemplates, NotSupported, readQueryFile, type ExecutableDataset, type Executor, type SparqlConstructExecuteOptions, type SparqlConstructExecutorOptions, type QuadStream, } from './executor.js';
1
+ export { SparqlConstructExecutor, substituteQueryTemplates, NotSupported, readQueryFile, type ExecutableDataset, type Executor, type SparqlConstructExecuteOptions, type SparqlConstructExecutorOptions, type QuadStream, type VariableBindings, } from './executor.js';
2
2
  export { collect } from './collect.js';
3
3
  export { SparqlSelector, type SparqlSelectorOptions } from './selector.js';
4
+ export { injectValues } from './values.js';
5
+ export { withDefaultGraph } from './graph.js';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sparql/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,YAAY,EACZ,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EACnC,KAAK,UAAU,GAChB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sparql/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,YAAY,EACZ,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EACnC,KAAK,UAAU,EACf,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
@@ -1,3 +1,5 @@
1
1
  export { SparqlConstructExecutor, substituteQueryTemplates, NotSupported, readQueryFile, } from './executor.js';
2
2
  export { collect } from './collect.js';
3
3
  export { SparqlSelector } from './selector.js';
4
+ export { injectValues } from './values.js';
5
+ export { withDefaultGraph } from './graph.js';
@@ -1,5 +1,6 @@
1
1
  import { SparqlEndpointFetcher } from 'fetch-sparql-endpoint';
2
- import type { StageSelectorBindings, StageSelector } from '../stage.js';
2
+ import type { StageSelector } from '../stage.js';
3
+ import type { VariableBindings } from './executor.js';
3
4
  export interface SparqlSelectorOptions {
4
5
  /** SELECT query projecting at least one named variable. A LIMIT in the query sets the default page size. */
5
6
  query: string;
@@ -25,6 +26,6 @@ export declare class SparqlSelector implements StageSelector {
25
26
  private readonly pageSize;
26
27
  private readonly fetcher;
27
28
  constructor(options: SparqlSelectorOptions);
28
- [Symbol.asyncIterator](): AsyncIterableIterator<StageSelectorBindings>;
29
+ [Symbol.asyncIterator](): AsyncIterableIterator<VariableBindings>;
29
30
  }
30
31
  //# sourceMappingURL=selector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../../src/sparql/selector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAQ9D,OAAO,KAAK,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKxE,MAAM,WAAW,qBAAqB;IACpC,4GAA4G;IAC5G,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,QAAQ,EAAE,GAAG,CAAC;IACd,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED;;;;;;;;GAQG;AACH,qBAAa,cAAe,YAAW,aAAa;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAM;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;gBAEpC,OAAO,EAAE,qBAAqB;IAmBnC,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,qBAAqB,CAAC;CAkC9E"}
1
+ {"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../../src/sparql/selector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAQ9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAKtD,MAAM,WAAW,qBAAqB;IACpC,4GAA4G;IAC5G,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,QAAQ,EAAE,GAAG,CAAC;IACd,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED;;;;;;;;GAQG;AACH,qBAAa,cAAe,YAAW,aAAa;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAM;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;gBAEpC,OAAO,EAAE,qBAAqB;IAmBnC,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,gBAAgB,CAAC;CAkCzE"}
@@ -0,0 +1,13 @@
1
+ import type { ConstructQuery } from 'sparqljs';
2
+ import type { VariableBindings } from './executor.js';
3
+ /**
4
+ * Inject a VALUES clause into a parsed CONSTRUCT query for the given binding rows.
5
+ *
6
+ * Each row's keys become `?`-prefixed SPARQL variables; NamedNode values
7
+ * become IRIs in the VALUES block. The VALUES clause is prepended to the
8
+ * query's WHERE patterns.
9
+ *
10
+ * The caller owns parsing and stringifying; this function operates on the AST.
11
+ */
12
+ export declare function injectValues(query: ConstructQuery, bindings: VariableBindings[]): ConstructQuery;
13
+ //# sourceMappingURL=values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../src/sparql/values.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,UAAU,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,cAAc,CAchB"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Inject a VALUES clause into a parsed CONSTRUCT query for the given binding rows.
3
+ *
4
+ * Each row's keys become `?`-prefixed SPARQL variables; NamedNode values
5
+ * become IRIs in the VALUES block. The VALUES clause is prepended to the
6
+ * query's WHERE patterns.
7
+ *
8
+ * The caller owns parsing and stringifying; this function operates on the AST.
9
+ */
10
+ export function injectValues(query, bindings) {
11
+ const valuesPattern = {
12
+ type: 'values',
13
+ values: bindings.map((row) => Object.fromEntries(Object.entries(row).map(([name, node]) => [`?${name}`, node]))),
14
+ };
15
+ return {
16
+ ...query,
17
+ where: [valuesPattern, ...(query.where ?? [])],
18
+ };
19
+ }
package/dist/stage.d.ts CHANGED
@@ -1,19 +1,20 @@
1
- import type { NamedNode, Quad } from '@rdfjs/types';
2
- import type { ExecutableDataset, Executor } from './sparql/executor.js';
1
+ import type { Quad } from '@rdfjs/types';
2
+ import type { ExecutableDataset, Executor, VariableBindings } from './sparql/executor.js';
3
3
  import { NotSupported } from './sparql/executor.js';
4
4
  export interface StageOptions {
5
5
  name: string;
6
6
  executors: Executor | Executor[];
7
+ selector?: StageSelector;
7
8
  }
8
9
  export declare class Stage {
9
10
  readonly name: string;
10
11
  private readonly executors;
12
+ private readonly selector?;
11
13
  constructor(options: StageOptions);
12
14
  run(dataset: ExecutableDataset): Promise<AsyncIterable<Quad> | NotSupported>;
15
+ private collectBindings;
13
16
  }
14
- /** A single row of variable bindings from a selector query. */
15
- export type StageSelectorBindings = Record<string, NamedNode>;
16
17
  /** Stage-level selector that yields variable bindings for use in executor queries. Pagination is an implementation detail. */
17
- export interface StageSelector extends AsyncIterable<StageSelectorBindings> {
18
+ export interface StageSelector extends AsyncIterable<VariableBindings> {
18
19
  }
19
20
  //# sourceMappingURL=stage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../src/stage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAAC;CAClC;AAED,qBAAa,KAAK;IAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;gBAE3B,OAAO,EAAE,YAAY;IAO3B,GAAG,CACP,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC;CAgB/C;AAUD,+DAA+D;AAC/D,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE9D,8HAA8H;AAE9H,MAAM,WAAW,aAAc,SAAQ,aAAa,CAAC,qBAAqB,CAAC;CAAG"}
1
+ {"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../src/stage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EACV,iBAAiB,EACjB,QAAQ,EACR,gBAAgB,EACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,qBAAa,KAAK;IAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAgB;gBAE9B,OAAO,EAAE,YAAY;IAQ3B,GAAG,CACP,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC;YAoBhC,eAAe;CAW9B;AAUD,8HAA8H;AAE9H,MAAM,WAAW,aAAc,SAAQ,aAAa,CAAC,gBAAgB,CAAC;CAAG"}
package/dist/stage.js CHANGED
@@ -2,16 +2,20 @@ import { NotSupported } from './sparql/executor.js';
2
2
  export class Stage {
3
3
  name;
4
4
  executors;
5
+ selector;
5
6
  constructor(options) {
6
7
  this.name = options.name;
7
8
  this.executors = Array.isArray(options.executors)
8
9
  ? options.executors
9
10
  : [options.executors];
11
+ this.selector = options.selector;
10
12
  }
11
13
  async run(dataset) {
14
+ const bindings = await this.collectBindings();
15
+ const executeOptions = bindings.length > 0 ? { bindings } : undefined;
12
16
  const streams = [];
13
17
  for (const executor of this.executors) {
14
- const result = await executor.execute(dataset);
18
+ const result = await executor.execute(dataset, executeOptions);
15
19
  if (!(result instanceof NotSupported)) {
16
20
  streams.push(result);
17
21
  }
@@ -21,6 +25,16 @@ export class Stage {
21
25
  }
22
26
  return mergeStreams(streams);
23
27
  }
28
+ async collectBindings() {
29
+ if (this.selector === undefined) {
30
+ return [];
31
+ }
32
+ const bindings = [];
33
+ for await (const row of this.selector) {
34
+ bindings.push(row);
35
+ }
36
+ return bindings;
37
+ }
24
38
  }
25
39
  async function* mergeStreams(streams) {
26
40
  for (const stream of streams) {
@@ -1,4 +1,4 @@
1
- import { DataEmittingStep } from './../step.js';
1
+ import { DataEmittingStep, NotSupported } from './../step.js';
2
2
  import { Dataset } from '@lde/dataset';
3
3
  import { SparqlEndpointFetcher } from 'fetch-sparql-endpoint';
4
4
  /**
@@ -17,13 +17,15 @@ export interface Args {
17
17
  * Executes a SPARQL CONSTRUCT query and emits the resulting quads.
18
18
  *
19
19
  * This step wraps the SparqlConstructExecutor to provide the DataEmittingStep interface
20
- * for use in pipelines.
20
+ * for use in pipelines. Supports legacy template substitution (`#namedGraph#`,
21
+ * `#subjectFilter#`, `?dataset`); for new code prefer the AST-based executor directly.
21
22
  */
22
23
  export declare class SparqlQuery implements DataEmittingStep {
23
24
  readonly identifier: string;
24
- private readonly executor;
25
+ private readonly query;
26
+ private readonly fetcher?;
25
27
  constructor({ identifier, query, fetcher }: Args);
26
- execute(dataset: Dataset): Promise<import("./../step.js").NotSupported | import("../sparql/executor.js").QuadStream>;
28
+ execute(dataset: Dataset): Promise<NotSupported | import("../sparql/executor.js").QuadStream>;
27
29
  static fromFile(filename: string): Promise<SparqlQuery>;
28
30
  }
29
31
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"sparqlQuery.d.ts","sourceRoot":"","sources":["../../src/step/sparqlQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG9D;;;;;;GAMG;AACH,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED;;;;;GAKG;AACH,qBAAa,WAAY,YAAW,gBAAgB;IAClD,SAAgB,UAAU,SAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;gBAEvC,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI;IAQ1C,OAAO,CAAC,OAAO,EAAE,OAAO;WAIV,QAAQ,CAAC,QAAQ,EAAE,MAAM;CAM9C;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,mBAE9C"}
1
+ {"version":3,"file":"sparqlQuery.d.ts","sourceRoot":"","sources":["../../src/step/sparqlQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAO9D;;;;;;GAMG;AACH,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED;;;;;;GAMG;AACH,qBAAa,WAAY,YAAW,gBAAgB;IAClD,SAAgB,UAAU,SAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAwB;gBAErC,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI;IAM1C,OAAO,CAAC,OAAO,EAAE,OAAO;WAiBV,QAAQ,CAAC,QAAQ,EAAE,MAAM;CAM9C;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,mBAE9C"}
@@ -1,22 +1,32 @@
1
- import { SparqlConstructExecutor, readQueryFile } from '../sparql/index.js';
1
+ import { NotSupported } from './../step.js';
2
+ import { SparqlConstructExecutor, substituteQueryTemplates, readQueryFile, } from '../sparql/index.js';
2
3
  /**
3
4
  * Executes a SPARQL CONSTRUCT query and emits the resulting quads.
4
5
  *
5
6
  * This step wraps the SparqlConstructExecutor to provide the DataEmittingStep interface
6
- * for use in pipelines.
7
+ * for use in pipelines. Supports legacy template substitution (`#namedGraph#`,
8
+ * `#subjectFilter#`, `?dataset`); for new code prefer the AST-based executor directly.
7
9
  */
8
10
  export class SparqlQuery {
9
11
  identifier;
10
- executor;
12
+ query;
13
+ fetcher;
11
14
  constructor({ identifier, query, fetcher }) {
12
15
  this.identifier = identifier;
13
- this.executor = new SparqlConstructExecutor({
14
- query,
15
- fetcher,
16
- });
16
+ this.query = query;
17
+ this.fetcher = fetcher;
17
18
  }
18
19
  async execute(dataset) {
19
- return await this.executor.execute(dataset);
20
+ const distribution = dataset.getSparqlDistribution();
21
+ if (distribution === null || !distribution.isValid) {
22
+ return new NotSupported('No SPARQL distribution available');
23
+ }
24
+ const substituted = substituteQueryTemplates(this.query, distribution, dataset);
25
+ const executor = new SparqlConstructExecutor({
26
+ query: substituted,
27
+ fetcher: this.fetcher,
28
+ });
29
+ return await executor.execute(dataset);
20
30
  }
21
31
  static async fromFile(filename) {
22
32
  return new this({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lde/pipeline",
3
- "version": "0.6.12",
3
+ "version": "0.6.13",
4
4
  "repository": {
5
5
  "url": "https://github.com/ldengine/lde",
6
6
  "directory": "packages/pipeline"
@@ -35,10 +35,10 @@
35
35
  "!**/*.tsbuildinfo"
36
36
  ],
37
37
  "dependencies": {
38
- "@lde/dataset": "0.6.6",
39
- "@lde/dataset-registry-client": "0.6.12",
40
- "@lde/sparql-importer": "0.2.6",
41
- "@lde/sparql-server": "0.4.6",
38
+ "@lde/dataset": "0.6.7",
39
+ "@lde/dataset-registry-client": "0.6.13",
40
+ "@lde/sparql-importer": "0.2.7",
41
+ "@lde/sparql-server": "0.4.7",
42
42
  "@rdfjs/types": "^2.0.1",
43
43
  "c12": "^3.0.2",
44
44
  "fetch-sparql-endpoint": "^6.0.0",