@lde/pipeline-shacl-sampler 0.9.4 → 0.9.6

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.
Files changed (2) hide show
  1. package/README.md +5 -160
  2. package/package.json +3 -3
package/README.md CHANGED
@@ -3,167 +3,12 @@
3
3
  Per-class sampling stages for [`@lde/pipeline`](../pipeline),
4
4
  derived from SHACL shapes.
5
5
 
6
- Given a SHACL shapes file, this package builds one
7
- [`Stage`](../pipeline/src/stage.ts) per `sh:targetClass`. Each stage
8
- pairs an [`ItemSelector`](../pipeline/src/sparql/selector.ts) that picks
9
- N instances of the target class from the distribution’s SPARQL endpoint
10
- with a CONSTRUCT executor that, for every path chain the SHACL declares
11
- (walked recursively through `sh:node`, `sh:class`,
12
- `sh:qualifiedValueShape`, and `sh:or` branches, stopping at leaf
13
- constraints or shape cycles), pulls in the triples reachable along that
14
- chain’s terminal node. The resulting quads are a sample subgraph rich
15
- enough for
16
- [`@lde/pipeline-shacl-validator`](../pipeline-shacl-validator) to
17
- validate without false-positive ‘missing nested node’ violations.
6
+ ## Installation
18
7
 
19
- ## Usage
20
-
21
- ```typescript
22
- import { Pipeline, FileWriter } from '@lde/pipeline';
23
- import { shaclSampleStages } from '@lde/pipeline-shacl-sampler';
24
- import { ShaclValidator } from '@lde/pipeline-shacl-validator';
25
-
26
- const shapesFile =
27
- 'https://raw.githubusercontent.com/netwerk-digitaal-erfgoed/schema-profile/main/shacl.ttl';
28
- const validator = new ShaclValidator({
29
- shapesFile,
30
- reportWriters: [new FileWriter({ outputDir: './validation', format: 'turtle' })],
31
- });
32
-
33
- const stages = await shaclSampleStages({
34
- shapesFile,
35
- samplesPerClass: 50,
36
- validator,
37
- });
38
-
39
- await new Pipeline({ /* … */, stages }).run();
40
- ```
41
-
42
- ## Options
43
-
44
- | Option | Default | Description |
45
- | ------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
46
- | `shapesFile` | — | URL or local path to the SHACL shapes file. Any format `rdf-dereference` accepts. |
47
- | `samplesPerClass` | `50` | Number of top-level resources to sample per `sh:targetClass`. |
48
- | `timeout` | `60000` | SPARQL query timeout in milliseconds. |
49
- | `batchSize` | `samplesPerClass` | Maximum sampled subjects per executor call. Lower values spread work across multiple parallel queries. |
50
- | `maxConcurrency` | `10` | Maximum concurrent in-flight executor batches per stage. |
51
- | `validator` | — | Optional [`Validator`](../pipeline/src/validator.ts) attached to every generated stage (typically a `ShaclValidator`). |
52
- | `onInvalid` | `'write'` | Behaviour when a sampled batch fails validation: `'write'` \| `'skip'` \| `'halt'`. Only used when `validator` is set. |
53
- | `namespaceAliases` | `[]` | Namespaces to treat as equivalent when matching `sh:targetClass` and when handing quads to the validator. See [Namespace aliases](#namespace-aliases). |
54
- | `excludeResources` | — | Hook returning a SPARQL fragment that subtracts resources from a target class’s sample. See [Excluding resources](#excluding-resources). |
55
-
56
- ## Namespace aliases
57
-
58
- Some vocabularies publish the same terms under multiple namespaces — most
59
- notably schema.org, which is reachable at both `http://schema.org/` and
60
- `https://schema.org/`. SHACL shapes can only declare one of those as the
61
- `sh:targetClass` namespace, so without help the sampler would silently
62
- skip resources typed under the other form, and the validator would
63
- report vacuously-conformant runs against datasets that mix the two.
64
-
65
- `namespaceAliases` closes the gap. For every declared pair the sampler:
66
-
67
- - broadens its subject-selection SELECT to `?s a ?type . FILTER(?type IN
68
- (<canonical/X>, <alias/X>))`, so instances typed under either
69
- namespace are picked up;
70
- - decorates the configured `validator` so any alias-namespace IRI in
71
- the sampled quads is rewritten to the canonical form before the SHACL
72
- engine sees it, allowing the canonical-namespace
73
- `sh:targetClass` / `sh:path` patterns to match.
74
-
75
- Defaults to no aliases. To cover schema.org datasets that publish under
76
- both HTTP and HTTPS:
77
-
78
- ```ts
79
- const stages = await shaclSampleStages({
80
- shapesFile,
81
- validator,
82
- namespaceAliases: [
83
- { canonical: 'https://schema.org/', alias: 'http://schema.org/' },
84
- ],
85
- });
86
- ```
87
-
88
- ## Excluding resources
89
-
90
- A profile may target a class that also describes a dataset’s own
91
- administrative metadata rather than its collection content. For example,
92
- SCHEMA-AP-NDE targets `schema:Organization`, so a dump containing nothing
93
- but a `schema:Dataset` and the publisher `Organization` that supports it
94
- would get that publisher sampled, found trivially conformant (only `name`
95
- is required), and reported as “tested and passed” — even though the
96
- dataset holds no real content.
97
-
98
- `excludeResources` lets the caller subtract such resources from a target
99
- class’s sample **without weakening the SHACL shapes**. It is a hook called
100
- once per `sh:targetClass`; the SPARQL fragment it returns is inlined
101
- verbatim into the subject-selector `WHERE` clause **after** the type
102
- pattern, so it can reference the bound `?s` (e.g. a `MINUS { … }` clause
103
- that removes `?s` when it is the dataset’s publisher). Return `''` to
104
- sample that class unchanged; omitting the option entirely leaves every
105
- generated query byte-for-byte the same.
106
-
107
- The fragment is interpolated verbatim and therefore caller-trusted — the
108
- same trust model as a distribution’s `subjectFilter`.
109
-
110
- ```ts
111
- const SCHEMA = 'https://schema.org/';
112
- const stages = await shaclSampleStages({
113
- shapesFile,
114
- validator,
115
- excludeResources: (targetClass) =>
116
- targetClass.value === `${SCHEMA}Organization`
117
- ? `MINUS { ?dataset a <${SCHEMA}Dataset> ; <${SCHEMA}publisher> ?s . }`
118
- : '',
119
- });
8
+ ```sh
9
+ npm install @lde/pipeline-shacl-sampler
120
10
  ```
121
11
 
122
- Anchoring the exclusion to the dataset node (rather than to the predicate
123
- alone) keeps genuine content resources in the sample: an `Organization`
124
- reached as the `creator` of a `CreativeWork`, say, is never the dataset’s
125
- publisher, so it is still sampled and validated.
126
-
127
- ## Limitations
128
-
129
- - Only plain-IRI `sh:path` values are supported. Sequence, alternative
130
- and inverse paths throw at extraction time.
131
- - `sh:targetClass` is the only target form recognised; `sh:targetNode`,
132
- `sh:targetSubjectsOf`, `sh:targetObjectsOf` and `sh:sparqlTarget` are
133
- not yet supported.
134
-
135
- ## Related work
136
-
137
- ### `extract-cbd-shape`
138
-
139
- The TREEcg / W3C TREE-incubation
140
- [`extract-cbd-shape`](https://github.com/TREEcg/extract-cbd-shape)
141
- library implements a per-entity walk over an in-memory `RdfStore`,
142
- falling back to an HTTP dereference of the focus node whenever a
143
- required path is missing from the local store. It is the right tool
144
- for streaming hypermedia consumers (e.g. LDES clients) that already
145
- hold a current context and can fetch more of it over HTTP.
146
-
147
- It is the wrong tool for this package’s setting. We assemble sample
148
- subgraphs against a remote SPARQL endpoint with millions of triples;
149
- the per-entity round-trip pattern would issue _N samples × M target
150
- classes_ dereferences per dataset and assumes content-negotiable
151
- entity IRIs that resolve to RDF — rarely true for the cultural
152
- heritage datasets this package was built for.
153
-
154
- ### SHACL2SPARQL
155
-
156
- The Corman, Reutter & Savković 2019
157
- [translation](https://link.springer.com/chapter/10.1007/978-3-030-30796-7_27)
158
- of SHACL constraints to SPARQL targets validation, not sample
159
- subgraph extraction. No production JavaScript implementation exists.
160
-
161
- ### Why batch CONSTRUCT per `sh:targetClass`
12
+ ## Documentation
162
13
 
163
- For each top-level shape, this package emits one `Stage` whose
164
- CONSTRUCT executor receives a batch of sampled subjects and walks
165
- every path chain the SHACL declares server-side. A capable SPARQL
166
- endpoint (e.g. QLever) evaluates the property-path UNIONs in a
167
- single round-trip per batch, regardless of chain count. The
168
- alternative — extracting per entity in the client — would multiply
169
- round-trips by the sample size.
14
+ See the [full documentation](https://ldelements.org/reference/pipeline-shacl-sampler).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lde/pipeline-shacl-sampler",
3
- "version": "0.9.4",
3
+ "version": "0.9.6",
4
4
  "description": "Per-class sampling stages for @lde/pipeline, derived from SHACL shapes",
5
5
  "repository": {
6
6
  "url": "git+https://github.com/ldelements/lde.git",
@@ -27,12 +27,12 @@
27
27
  "dependencies": {
28
28
  "@rdfjs/types": "^2.0.1",
29
29
  "@tpluscode/rdf-ns-builders": "^5.0.0",
30
- "n3": "^2.1.1",
30
+ "n3": "^2.1.2",
31
31
  "rdf-dereference": "^5.0.0",
32
32
  "tslib": "^2.3.0"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "@lde/dataset": "^0.7.9",
36
- "@lde/pipeline": "^0.35.4"
36
+ "@lde/pipeline": "^0.35.6"
37
37
  }
38
38
  }