@lde/pipeline-shacl-sampler 0.3.1 → 0.4.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
@@ -19,12 +19,15 @@ validate without false-positive ‘missing nested node’ violations.
19
19
  ## Usage
20
20
 
21
21
  ```typescript
22
- import { Pipeline } from '@lde/pipeline';
22
+ import { Pipeline, FileWriter } from '@lde/pipeline';
23
23
  import { shaclSampleStages } from '@lde/pipeline-shacl-sampler';
24
24
  import { ShaclValidator } from '@lde/pipeline-shacl-validator';
25
25
 
26
26
  const shapesFile = 'https://docs.nde.nl/schema-profile/shacl.ttl';
27
- const validator = new ShaclValidator({ shapesFile, reportDir: './validation' });
27
+ const validator = new ShaclValidator({
28
+ shapesFile,
29
+ reportWriters: [new FileWriter({ outputDir: './validation', format: 'turtle' })],
30
+ });
28
31
 
29
32
  const stages = await shaclSampleStages({
30
33
  shapesFile,
@@ -37,15 +40,48 @@ await new Pipeline({ /* … */, stages }).run();
37
40
 
38
41
  ## Options
39
42
 
40
- | Option | Default | Description |
41
- | ----------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------- |
42
- | `shapesFile` | — | URL or local path to the SHACL shapes file. Any format `rdf-dereference` accepts. |
43
- | `samplesPerClass` | `50` | Number of top-level resources to sample per `sh:targetClass`. |
44
- | `timeout` | `60000` | SPARQL query timeout in milliseconds. |
45
- | `batchSize` | `samplesPerClass` | Maximum sampled subjects per executor call. Lower values spread work across multiple parallel queries. |
46
- | `maxConcurrency` | `10` | Maximum concurrent in-flight executor batches per stage. |
47
- | `validator` | — | Optional [`Validator`](../pipeline/src/validator.ts) attached to every generated stage (typically a `ShaclValidator`). |
48
- | `onInvalid` | `'write'` | Behaviour when a sampled batch fails validation: `'write'` \| `'skip'` \| `'halt'`. Only used when `validator` is set. |
43
+ | Option | Default | Description |
44
+ | ------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
45
+ | `shapesFile` | — | URL or local path to the SHACL shapes file. Any format `rdf-dereference` accepts. |
46
+ | `samplesPerClass` | `50` | Number of top-level resources to sample per `sh:targetClass`. |
47
+ | `timeout` | `60000` | SPARQL query timeout in milliseconds. |
48
+ | `batchSize` | `samplesPerClass` | Maximum sampled subjects per executor call. Lower values spread work across multiple parallel queries. |
49
+ | `maxConcurrency` | `10` | Maximum concurrent in-flight executor batches per stage. |
50
+ | `validator` | — | Optional [`Validator`](../pipeline/src/validator.ts) attached to every generated stage (typically a `ShaclValidator`). |
51
+ | `onInvalid` | `'write'` | Behaviour when a sampled batch fails validation: `'write'` \| `'skip'` \| `'halt'`. Only used when `validator` is set. |
52
+ | `namespaceAliases` | `[]` | Namespaces to treat as equivalent when matching `sh:targetClass` and when handing quads to the validator. See [Namespace aliases](#namespace-aliases). |
53
+
54
+ ## Namespace aliases
55
+
56
+ Some vocabularies publish the same terms under multiple namespaces — most
57
+ notably schema.org, which is reachable at both `http://schema.org/` and
58
+ `https://schema.org/`. SHACL shapes can only declare one of those as the
59
+ `sh:targetClass` namespace, so without help the sampler would silently
60
+ skip resources typed under the other form, and the validator would
61
+ report vacuously-conformant runs against datasets that mix the two.
62
+
63
+ `namespaceAliases` closes the gap. For every declared pair the sampler:
64
+
65
+ - broadens its subject-selection SELECT to `?s a ?type . FILTER(?type IN
66
+ (<canonical/X>, <alias/X>))`, so instances typed under either
67
+ namespace are picked up;
68
+ - decorates the configured `validator` so any alias-namespace IRI in
69
+ the sampled quads is rewritten to the canonical form before the SHACL
70
+ engine sees it, allowing the canonical-namespace
71
+ `sh:targetClass` / `sh:path` patterns to match.
72
+
73
+ Defaults to no aliases. To cover schema.org datasets that publish under
74
+ both HTTP and HTTPS:
75
+
76
+ ```ts
77
+ const stages = await shaclSampleStages({
78
+ shapesFile,
79
+ validator,
80
+ namespaceAliases: [
81
+ { canonical: 'https://schema.org/', alias: 'http://schema.org/' },
82
+ ],
83
+ });
84
+ ```
49
85
 
50
86
  ## Limitations
51
87
 
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { extractTargetShapes, type TargetShape } from './pathExtractor.js';
2
- export { shaclSampleStages, type ShaclSampleStagesOptions, } from './sampleStages.js';
2
+ export { shaclSampleStages, wrapValidatorWithAliasNormalization, type NamespaceAlias, type ShaclSampleStagesOptions, type SubjectSelectorQueryOptions, } from './sampleStages.js';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,GAC9B,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EACL,iBAAiB,EACjB,mCAAmC,EACnC,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,GACjC,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export { extractTargetShapes } from './pathExtractor.js';
2
- export { shaclSampleStages, } from './sampleStages.js';
2
+ export { shaclSampleStages, wrapValidatorWithAliasNormalization, } from './sampleStages.js';
@@ -2,6 +2,29 @@ import { Stage, type StageOptions, type Validator } from '@lde/pipeline';
2
2
  import type { NamedNode } from '@rdfjs/types';
3
3
  import { type TargetShape } from './pathExtractor.js';
4
4
  type OnInvalid = NonNullable<StageOptions['validation']>['onInvalid'];
5
+ /**
6
+ * Declares that two namespaces should be treated as equivalent when
7
+ * sampling and validating, working around vocabularies that publish under
8
+ * both HTTP and HTTPS variants of the same IRI (notably schema.org).
9
+ *
10
+ * The sampler accepts subjects typed under the {@link alias} namespace in
11
+ * addition to the SHACL `sh:targetClass` IRI under {@link canonical}, and
12
+ * rewrites alias-namespace IRIs to canonical ones in the sampled quads
13
+ * before validation so SHACL `sh:targetClass` and `sh:path` patterns
14
+ * match.
15
+ */
16
+ export interface NamespaceAlias {
17
+ /**
18
+ * The namespace declared in the SHACL shapes file (e.g.
19
+ * `https://schema.org/`).
20
+ */
21
+ canonical: string;
22
+ /**
23
+ * The equivalent namespace that may appear in source data (e.g.
24
+ * `http://schema.org/`).
25
+ */
26
+ alias: string;
27
+ }
5
28
  /** Options for {@link shaclSampleStages}. */
6
29
  export interface ShaclSampleStagesOptions {
7
30
  /** URL or local path to the SHACL shapes file. */
@@ -38,6 +61,19 @@ export interface ShaclSampleStagesOptions {
38
61
  * @default 'write'
39
62
  */
40
63
  onInvalid?: OnInvalid;
64
+ /**
65
+ * Namespace pairs to treat as equivalent when matching `sh:targetClass`
66
+ * and when handing quads to the validator. For each pair, the sampler
67
+ * broadens its subject-selection SELECT so resources typed under either
68
+ * namespace are picked up, and wraps the configured {@link validator}
69
+ * so alias-namespace IRIs in the sampled quads are rewritten to the
70
+ * canonical form before SHACL evaluates them.
71
+ *
72
+ * Defaults to no aliases. To cover schema.org datasets that publish
73
+ * under both `http://schema.org/` and `https://schema.org/`, pass
74
+ * `[{ canonical: 'https://schema.org/', alias: 'http://schema.org/' }]`.
75
+ */
76
+ namespaceAliases?: NamespaceAlias[];
41
77
  }
42
78
  /**
43
79
  * Build one sampling {@link Stage} per `sh:targetClass` declared in the SHACL
@@ -50,12 +86,31 @@ export interface ShaclSampleStagesOptions {
50
86
  * Pass a {@link Validator} to attach it to every generated stage:
51
87
  *
52
88
  * ```ts
53
- * const validator = new ShaclValidator({ shapesFile, reportDir });
89
+ * const validator = new ShaclValidator({ shapesFile, reportWriters: [...] });
54
90
  * const stages = await shaclSampleStages({ shapesFile, validator });
55
91
  * ```
56
92
  */
57
93
  export declare function shaclSampleStages(options: ShaclSampleStagesOptions): Promise<Stage[]>;
58
- export declare function buildSubjectSelectorQuery(targetClass: NamedNode, subjectFilter?: string, namedGraph?: string): string;
94
+ /** Options for {@link buildSubjectSelectorQuery}. */
95
+ export interface SubjectSelectorQueryOptions {
96
+ /** SHACL `sh:targetClass` to match. */
97
+ targetClass: NamedNode;
98
+ /** Optional extra triple pattern restricting subjects (interpolated verbatim). */
99
+ subjectFilter?: string;
100
+ /** Restrict to a single named graph via `FROM <…>`. */
101
+ namedGraph?: string;
102
+ /** Equivalent namespaces to broaden the type match across. @default [] */
103
+ namespaceAliases?: NamespaceAlias[];
104
+ }
105
+ export declare function buildSubjectSelectorQuery({ targetClass, subjectFilter, namedGraph, namespaceAliases, }: SubjectSelectorQueryOptions): string;
59
106
  export declare function buildSampleQuery(shape: TargetShape): string;
107
+ /**
108
+ * Decorate a {@link Validator} so every quad it receives has any IRI in an
109
+ * alias namespace rewritten to the corresponding canonical namespace.
110
+ * Without this, SHACL shapes declared under the canonical namespace would
111
+ * silently skip resources whose types and predicates use the alias form,
112
+ * producing vacuously-conformant reports.
113
+ */
114
+ export declare function wrapValidatorWithAliasNormalization(inner: Validator, namespaceAliases: NamespaceAlias[]): Validator;
60
115
  export {};
61
116
  //# sourceMappingURL=sampleStages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sampleStages.d.ts","sourceRoot":"","sources":["../src/sampleStages.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAIL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE3E,KAAK,SAAS,GAAG,WAAW,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;AAEtE,6CAA6C;AAC7C,MAAM,WAAW,wBAAwB;IACvC,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,KAAK,EAAE,CAAC,CAwBlB;AAmBD,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,SAAS,EACtB,aAAa,CAAC,EAAE,MAAM,EACtB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAWR;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAuB3D"}
1
+ {"version":3,"file":"sampleStages.d.ts","sourceRoot":"","sources":["../src/sampleStages.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAIL,KAAK,YAAY,EAGjB,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,SAAS,EAAQ,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAI3E,KAAK,SAAS,GAAG,WAAW,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED,6CAA6C;AAC7C,MAAM,WAAW,wBAAwB;IACvC,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,cAAc,EAAE,CAAC;CACrC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,KAAK,EAAE,CAAC,CAmClB;AAwBD,qDAAqD;AACrD,MAAM,WAAW,2BAA2B;IAC1C,uCAAuC;IACvC,WAAW,EAAE,SAAS,CAAC;IACvB,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,cAAc,EAAE,CAAC;CACrC;AAED,wBAAgB,yBAAyB,CAAC,EACxC,WAAW,EACX,aAAa,EACb,UAAU,EACV,gBAAqB,GACtB,EAAE,2BAA2B,GAAG,MAAM,CAYtC;AA+BD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAuB3D;AAED;;;;;;GAMG;AACH,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,SAAS,EAChB,gBAAgB,EAAE,cAAc,EAAE,GACjC,SAAS,CAeX"}
@@ -1,6 +1,8 @@
1
1
  import { Stage, SparqlConstructExecutor, SparqlItemSelector, } from '@lde/pipeline';
2
2
  import { assertSafeIri } from '@lde/dataset';
3
+ import { DataFactory } from 'n3';
3
4
  import { extractTargetShapes } from './pathExtractor.js';
5
+ const { namedNode, quad } = DataFactory;
4
6
  /**
5
7
  * Build one sampling {@link Stage} per `sh:targetClass` declared in the SHACL
6
8
  * shapes file. Each stage pairs a SELECT-based {@link ItemSelector} that picks
@@ -12,7 +14,7 @@ import { extractTargetShapes } from './pathExtractor.js';
12
14
  * Pass a {@link Validator} to attach it to every generated stage:
13
15
  *
14
16
  * ```ts
15
- * const validator = new ShaclValidator({ shapesFile, reportDir });
17
+ * const validator = new ShaclValidator({ shapesFile, reportWriters: [...] });
16
18
  * const stages = await shaclSampleStages({ shapesFile, validator });
17
19
  * ```
18
20
  */
@@ -21,13 +23,17 @@ export async function shaclSampleStages(options) {
21
23
  const timeout = options.timeout ?? 60_000;
22
24
  const batchSize = options.batchSize ?? samplesPerClass;
23
25
  const maxConcurrency = options.maxConcurrency;
26
+ const namespaceAliases = options.namespaceAliases ?? [];
24
27
  const validation = options.validator
25
- ? { validator: options.validator, onInvalid: options.onInvalid ?? 'write' }
28
+ ? {
29
+ validator: wrapValidatorWithAliasNormalization(options.validator, namespaceAliases),
30
+ onInvalid: options.onInvalid ?? 'write',
31
+ }
26
32
  : undefined;
27
33
  const shapes = await extractTargetShapes(options.shapesFile);
28
34
  return shapes.map((shape) => new Stage({
29
35
  name: `shacl-sample-${localName(shape.targetClass.value)}`,
30
- itemSelector: subjectSelector(shape.targetClass, samplesPerClass),
36
+ itemSelector: subjectSelector(shape.targetClass, samplesPerClass, namespaceAliases),
31
37
  executors: new SparqlConstructExecutor({
32
38
  query: buildSampleQuery(shape),
33
39
  timeout,
@@ -37,11 +43,16 @@ export async function shaclSampleStages(options) {
37
43
  validation,
38
44
  }));
39
45
  }
40
- function subjectSelector(targetClass, limit) {
46
+ function subjectSelector(targetClass, limit, namespaceAliases) {
41
47
  assertSafeIri(targetClass.value);
42
48
  return {
43
49
  select(distribution, batchSize) {
44
- const query = buildSubjectSelectorQuery(targetClass, distribution.subjectFilter, distribution.namedGraph);
50
+ const query = buildSubjectSelectorQuery({
51
+ targetClass,
52
+ subjectFilter: distribution.subjectFilter,
53
+ namedGraph: distribution.namedGraph,
54
+ namespaceAliases,
55
+ });
45
56
  return new SparqlItemSelector({
46
57
  query,
47
58
  maxResults: limit,
@@ -49,18 +60,41 @@ function subjectSelector(targetClass, limit) {
49
60
  },
50
61
  };
51
62
  }
52
- export function buildSubjectSelectorQuery(targetClass, subjectFilter, namedGraph) {
63
+ export function buildSubjectSelectorQuery({ targetClass, subjectFilter, namedGraph, namespaceAliases = [], }) {
53
64
  let fromClause = '';
54
65
  if (namedGraph) {
55
66
  assertSafeIri(namedGraph);
56
67
  fromClause = `FROM <${namedGraph}>`;
57
68
  }
69
+ const typePattern = buildTypePattern(targetClass, namespaceAliases);
58
70
  return [
59
71
  'SELECT DISTINCT ?s',
60
72
  fromClause,
61
- `WHERE { ${subjectFilter ?? ''} ?s a <${targetClass.value}> . }`,
73
+ `WHERE { ${subjectFilter ?? ''} ${typePattern} }`,
62
74
  ].join('\n');
63
75
  }
76
+ function buildTypePattern(targetClass, namespaceAliases) {
77
+ const equivalents = expandTargetClass(targetClass, namespaceAliases);
78
+ for (const iri of equivalents)
79
+ assertSafeIri(iri);
80
+ if (equivalents.length === 1) {
81
+ return `?s a <${equivalents[0]}> .`;
82
+ }
83
+ const iriList = equivalents.map((iri) => `<${iri}>`).join(', ');
84
+ return `?s a ?type . FILTER(?type IN (${iriList}))`;
85
+ }
86
+ function expandTargetClass(targetClass, namespaceAliases) {
87
+ const iri = targetClass.value;
88
+ for (const { canonical, alias } of namespaceAliases) {
89
+ if (iri.startsWith(canonical)) {
90
+ return [iri, alias + iri.slice(canonical.length)];
91
+ }
92
+ if (iri.startsWith(alias)) {
93
+ return [iri, canonical + iri.slice(alias.length)];
94
+ }
95
+ }
96
+ return [iri];
97
+ }
64
98
  export function buildSampleQuery(shape) {
65
99
  for (const chain of shape.pathChains) {
66
100
  for (const path of chain)
@@ -82,6 +116,49 @@ WHERE {
82
116
  }${chainBranches}
83
117
  }`;
84
118
  }
119
+ /**
120
+ * Decorate a {@link Validator} so every quad it receives has any IRI in an
121
+ * alias namespace rewritten to the corresponding canonical namespace.
122
+ * Without this, SHACL shapes declared under the canonical namespace would
123
+ * silently skip resources whose types and predicates use the alias form,
124
+ * producing vacuously-conformant reports.
125
+ */
126
+ export function wrapValidatorWithAliasNormalization(inner, namespaceAliases) {
127
+ if (namespaceAliases.length === 0) {
128
+ return inner;
129
+ }
130
+ return {
131
+ validate(quads, dataset) {
132
+ return inner.validate(quads.map((q) => normalizeQuad(q, namespaceAliases)), dataset);
133
+ },
134
+ report(dataset) {
135
+ return inner.report(dataset);
136
+ },
137
+ };
138
+ }
139
+ function normalizeQuad(q, namespaceAliases) {
140
+ const subject = rewriteIfAlias(q.subject, namespaceAliases) ?? q.subject;
141
+ const predicate = rewriteIfAlias(q.predicate, namespaceAliases) ?? q.predicate;
142
+ const object = rewriteIfAlias(q.object, namespaceAliases) ?? q.object;
143
+ const graph = rewriteIfAlias(q.graph, namespaceAliases) ?? q.graph;
144
+ if (subject === q.subject &&
145
+ predicate === q.predicate &&
146
+ object === q.object &&
147
+ graph === q.graph) {
148
+ return q;
149
+ }
150
+ return quad(subject, predicate, object, graph);
151
+ }
152
+ function rewriteIfAlias(term, namespaceAliases) {
153
+ if (term.termType !== 'NamedNode')
154
+ return undefined;
155
+ for (const { canonical, alias } of namespaceAliases) {
156
+ if (term.value.startsWith(alias)) {
157
+ return namedNode(canonical + term.value.slice(alias.length));
158
+ }
159
+ }
160
+ return undefined;
161
+ }
85
162
  function localName(iri) {
86
163
  const match = /[#/]([^#/]+)$/.exec(iri);
87
164
  return (match?.[1] ?? iri).replace(/[^A-Za-z0-9_-]/g, '_');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lde/pipeline-shacl-sampler",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
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",
@@ -32,6 +32,6 @@
32
32
  },
33
33
  "peerDependencies": {
34
34
  "@lde/dataset": "0.7.4",
35
- "@lde/pipeline": "0.29.1"
35
+ "@lde/pipeline": "0.30.0"
36
36
  }
37
37
  }