@unrdf/hooks 5.0.1 → 26.4.2
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/dist/index.d.mts +1738 -0
- package/dist/index.d.ts +1738 -0
- package/dist/index.mjs +1738 -0
- package/examples/basic.mjs +113 -0
- package/examples/hook-chains/README.md +263 -0
- package/examples/hook-chains/node_modules/.bin/validate-hooks +21 -0
- package/examples/hook-chains/node_modules/.bin/vitest +21 -0
- package/examples/hook-chains/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/examples/hook-chains/package.json +25 -0
- package/examples/hook-chains/src/index.mjs +348 -0
- package/examples/hook-chains/test/example.test.mjs +252 -0
- package/examples/hook-chains/vitest.config.mjs +14 -0
- package/examples/knowledge-hook-manager-usage.mjs +65 -0
- package/examples/policy-hooks/README.md +193 -0
- package/examples/policy-hooks/node_modules/.bin/validate-hooks +21 -0
- package/examples/policy-hooks/node_modules/.bin/vitest +21 -0
- package/examples/policy-hooks/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/examples/policy-hooks/package.json +25 -0
- package/examples/policy-hooks/src/index.mjs +275 -0
- package/examples/policy-hooks/test/example.test.mjs +204 -0
- package/examples/policy-hooks/vitest.config.mjs +14 -0
- package/examples/validate-hooks.mjs +154 -0
- package/package.json +29 -24
- package/src/hooks/builtin-hooks.mjs +72 -48
- package/src/hooks/condition-evaluator.mjs +1 -1
- package/src/hooks/define-hook.mjs +25 -9
- package/src/hooks/effect-sandbox-worker.mjs +1 -1
- package/src/hooks/effect-sandbox.mjs +5 -2
- package/src/hooks/file-resolver.mjs +2 -2
- package/src/hooks/hook-executor.mjs +12 -19
- package/src/hooks/policy-pack.mjs +3 -3
- package/src/hooks/query-optimizer.mjs +196 -0
- package/src/hooks/query.mjs +150 -0
- package/src/hooks/schemas.mjs +158 -0
- package/src/hooks/security/path-validator.mjs +1 -1
- package/src/hooks/security/sandbox-restrictions.mjs +2 -2
- package/src/hooks/store-cache.mjs +189 -0
- package/src/hooks/validate.mjs +133 -0
- package/src/index.mjs +62 -0
- package/src/policy-compiler.mjs +503 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @unrdf/hooks - Basic Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates basic usage of the Knowledge Hooks package.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createStore, dataFactory } from '@unrdf/oxigraph';
|
|
8
|
+
import {
|
|
9
|
+
defineHook,
|
|
10
|
+
createHookRegistry,
|
|
11
|
+
registerHook,
|
|
12
|
+
executeHooksByTrigger,
|
|
13
|
+
builtinHooks,
|
|
14
|
+
} from '../src/index.mjs';
|
|
15
|
+
|
|
16
|
+
const { namedNode, literal, quad } = dataFactory;
|
|
17
|
+
|
|
18
|
+
console.log('=== @unrdf/hooks Basic Example ===\n');
|
|
19
|
+
|
|
20
|
+
// 1. Define a custom validation hook
|
|
21
|
+
const validateEmailProperty = defineHook({
|
|
22
|
+
name: 'validate-email-property',
|
|
23
|
+
trigger: 'before-add',
|
|
24
|
+
validate: (quad) => {
|
|
25
|
+
if (quad.predicate.value === 'http://schema.org/email') {
|
|
26
|
+
if (quad.object.termType !== 'Literal') {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
const email = quad.object.value;
|
|
30
|
+
return email.includes('@') && email.includes('.');
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
},
|
|
34
|
+
metadata: {
|
|
35
|
+
description: 'Validates email format for schema:email properties',
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
console.log('1. Defined custom email validation hook');
|
|
40
|
+
|
|
41
|
+
// 2. Create registry and register hooks
|
|
42
|
+
const registry = createHookRegistry();
|
|
43
|
+
registerHook(registry, validateEmailProperty);
|
|
44
|
+
registerHook(registry, builtinHooks.validatePredicateIRI);
|
|
45
|
+
|
|
46
|
+
console.log('2. Registered hooks in registry\n');
|
|
47
|
+
|
|
48
|
+
// 3. Create test quads
|
|
49
|
+
const validQuad = quad(
|
|
50
|
+
namedNode('http://example.org/person1'),
|
|
51
|
+
namedNode('http://schema.org/email'),
|
|
52
|
+
literal('user@example.com')
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const invalidQuad = quad(
|
|
56
|
+
namedNode('http://example.org/person2'),
|
|
57
|
+
namedNode('http://schema.org/email'),
|
|
58
|
+
literal('invalid-email')
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// 4. Execute hooks on quads
|
|
62
|
+
console.log('3. Executing hooks on valid email quad:');
|
|
63
|
+
const result1 = executeHooksByTrigger(
|
|
64
|
+
[validateEmailProperty, builtinHooks.validatePredicateIRI],
|
|
65
|
+
'before-add',
|
|
66
|
+
validQuad
|
|
67
|
+
);
|
|
68
|
+
console.log(` Valid: ${result1.valid}`);
|
|
69
|
+
console.log(` Hooks executed: ${result1.results.length}\n`);
|
|
70
|
+
|
|
71
|
+
console.log('4. Executing hooks on invalid email quad:');
|
|
72
|
+
const result2 = executeHooksByTrigger(
|
|
73
|
+
[validateEmailProperty, builtinHooks.validatePredicateIRI],
|
|
74
|
+
'before-add',
|
|
75
|
+
invalidQuad
|
|
76
|
+
);
|
|
77
|
+
console.log(` Valid: ${result2.valid}`);
|
|
78
|
+
console.log(` Error: ${result2.error}\n`);
|
|
79
|
+
|
|
80
|
+
// 5. Demonstrate transformation hook
|
|
81
|
+
const normalizeEmail = defineHook({
|
|
82
|
+
name: 'normalize-email',
|
|
83
|
+
trigger: 'before-add',
|
|
84
|
+
transform: (quad) => {
|
|
85
|
+
if (quad.predicate.value === 'http://schema.org/email' &&
|
|
86
|
+
quad.object.termType === 'Literal') {
|
|
87
|
+
return dataFactory.quad(
|
|
88
|
+
quad.subject,
|
|
89
|
+
quad.predicate,
|
|
90
|
+
literal(quad.object.value.toLowerCase()),
|
|
91
|
+
quad.graph
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return quad;
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
console.log('5. Applying transformation hook:');
|
|
99
|
+
const upperEmail = quad(
|
|
100
|
+
namedNode('http://example.org/person3'),
|
|
101
|
+
namedNode('http://schema.org/email'),
|
|
102
|
+
literal('USER@EXAMPLE.COM')
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const result3 = executeHooksByTrigger(
|
|
106
|
+
[normalizeEmail],
|
|
107
|
+
'before-add',
|
|
108
|
+
upperEmail
|
|
109
|
+
);
|
|
110
|
+
console.log(` Original: ${upperEmail.object.value}`);
|
|
111
|
+
console.log(` Transformed: ${result3.quad.object.value}\n`);
|
|
112
|
+
|
|
113
|
+
console.log('=== Example Complete ===');
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# Hook Chains Example
|
|
2
|
+
|
|
3
|
+
This example demonstrates how to use **@unrdf/hooks** for creating sequential hook chains that validate and transform RDF quads through multiple stages.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Sequential Execution**: Hooks execute in defined order
|
|
8
|
+
- **Progressive Transformation**: Quads transform through pipeline stages
|
|
9
|
+
- **Early Termination**: Chain stops on first validation failure
|
|
10
|
+
- **Result Aggregation**: Complete execution history and results
|
|
11
|
+
- **Composable Patterns**: Mix and match hooks for different pipelines
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
Run the example:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pnpm start
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Run tests:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pnpm test
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Example Output
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
🔗 Hook Chains Example
|
|
37
|
+
|
|
38
|
+
============================================================
|
|
39
|
+
|
|
40
|
+
🧹 Data Cleaning Chain
|
|
41
|
+
────────────────────────────────────────────────────────────
|
|
42
|
+
Input: Alice Smith
|
|
43
|
+
" Alice Smith "
|
|
44
|
+
Status: ✅ SUCCESS
|
|
45
|
+
Steps: 3/3 passed
|
|
46
|
+
Output: Alice Smith
|
|
47
|
+
"Alice Smith"
|
|
48
|
+
|
|
49
|
+
Chain execution:
|
|
50
|
+
1. ✅ 🔄 trim-literals
|
|
51
|
+
2. ✅ 🔄 normalize-whitespace
|
|
52
|
+
3. ✅ validate-literal-length
|
|
53
|
+
|
|
54
|
+
🔍 Quality Assurance Chain
|
|
55
|
+
────────────────────────────────────────────────────────────
|
|
56
|
+
Input: Literal with 1500 characters
|
|
57
|
+
Status: ❌ FAILED
|
|
58
|
+
Steps: 3/4 passed
|
|
59
|
+
Failed at: validate-literal-length
|
|
60
|
+
Reason: validation failed
|
|
61
|
+
|
|
62
|
+
Chain execution (early termination):
|
|
63
|
+
1. ✅ standard-validation
|
|
64
|
+
2. ✅ validate-iris
|
|
65
|
+
3. ✅ validate-iri-format
|
|
66
|
+
4. ❌ validate-literal-length
|
|
67
|
+
|
|
68
|
+
⚙️ Complete Processing Chain
|
|
69
|
+
────────────────────────────────────────────────────────────
|
|
70
|
+
Input:
|
|
71
|
+
Object: " Chuck "
|
|
72
|
+
Graph: DefaultGraph
|
|
73
|
+
|
|
74
|
+
Status: ✅ SUCCESS
|
|
75
|
+
Steps: 5/5 passed
|
|
76
|
+
|
|
77
|
+
Output:
|
|
78
|
+
Object: "Chuck"
|
|
79
|
+
Graph: NamedNode
|
|
80
|
+
Graph IRI: http://example.org/provenance/1733288888888
|
|
81
|
+
|
|
82
|
+
Chain execution:
|
|
83
|
+
1. ✅ validate-iris
|
|
84
|
+
2. ✅ 🔄 normalize-whitespace
|
|
85
|
+
└─ Transformation applied
|
|
86
|
+
3. ✅ validate-literal-length
|
|
87
|
+
4. ✅ 🔄 add-provenance
|
|
88
|
+
└─ Transformation applied
|
|
89
|
+
5. ✅ final-validation
|
|
90
|
+
|
|
91
|
+
============================================================
|
|
92
|
+
✨ Hook Chains Example Complete
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Hook Chain Patterns
|
|
96
|
+
|
|
97
|
+
### 1. Data Cleaning Chain
|
|
98
|
+
|
|
99
|
+
Clean and normalize messy data:
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
const dataCleaningChain = [
|
|
103
|
+
builtinHooks.trimLiterals, // Remove leading/trailing whitespace
|
|
104
|
+
normalizeWhitespace, // Collapse multiple spaces
|
|
105
|
+
validateLiteralLength, // Ensure valid length
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
const result = executeHookChain(dataCleaningChain, store, quad);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 2. Quality Assurance Chain
|
|
112
|
+
|
|
113
|
+
Comprehensive validation pipeline:
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
const qualityAssuranceChain = [
|
|
117
|
+
builtinHooks.standardValidation, // RDF structure
|
|
118
|
+
validateIRIs, // IRI well-formedness
|
|
119
|
+
builtinHooks.validateIRIFormat, // URL validation
|
|
120
|
+
validateLiteralLength, // Length constraints
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
const result = executeHookChain(qualityAssuranceChain, store, quad);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 3. Complete Processing Chain
|
|
127
|
+
|
|
128
|
+
Full pipeline with validation and transformation:
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
const completeProcessingChain = [
|
|
132
|
+
validateIRIs, // 1. Validate structure
|
|
133
|
+
normalizeWhitespace, // 2. Clean data
|
|
134
|
+
validateLiteralLength, // 3. Check constraints
|
|
135
|
+
addProvenance, // 4. Add metadata
|
|
136
|
+
finalValidation, // 5. Final checks
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
const result = executeHookChain(completeProcessingChain, store, quad);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Custom Hooks
|
|
143
|
+
|
|
144
|
+
### Validation Hook
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
const validateIRIs = defineHook({
|
|
148
|
+
name: 'validate-iris',
|
|
149
|
+
trigger: 'before-add',
|
|
150
|
+
validate: quad => {
|
|
151
|
+
const validateIRI = term => {
|
|
152
|
+
if (term.termType !== 'NamedNode') return true;
|
|
153
|
+
try {
|
|
154
|
+
new URL(term.value);
|
|
155
|
+
return true;
|
|
156
|
+
} catch {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
return validateIRI(quad.subject) &&
|
|
162
|
+
validateIRI(quad.predicate) &&
|
|
163
|
+
validateIRI(quad.object);
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Transformation Hook
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
const normalizeWhitespace = defineHook({
|
|
172
|
+
name: 'normalize-whitespace',
|
|
173
|
+
trigger: 'before-add',
|
|
174
|
+
transform: quad => {
|
|
175
|
+
if (quad.object.termType !== 'Literal') {
|
|
176
|
+
return quad;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const normalized = quad.object.value
|
|
180
|
+
.trim()
|
|
181
|
+
.replace(/\s+/g, ' ');
|
|
182
|
+
|
|
183
|
+
return DataFactory.quad(
|
|
184
|
+
quad.subject,
|
|
185
|
+
quad.predicate,
|
|
186
|
+
DataFactory.literal(
|
|
187
|
+
normalized,
|
|
188
|
+
quad.object.language || quad.object.datatype
|
|
189
|
+
),
|
|
190
|
+
quad.graph
|
|
191
|
+
);
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Chain Execution
|
|
197
|
+
|
|
198
|
+
### Success Case
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const result = executeHookChain(chain, store, quad);
|
|
202
|
+
|
|
203
|
+
if (result.success) {
|
|
204
|
+
console.log('All hooks passed!');
|
|
205
|
+
console.log('Transformed quad:', result.quad);
|
|
206
|
+
console.log('Steps executed:', result.results.length);
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Failure Case (Early Termination)
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
const result = executeHookChain(chain, store, invalidQuad);
|
|
214
|
+
|
|
215
|
+
if (!result.success) {
|
|
216
|
+
const failedHook = result.results.find(r => !r.passed);
|
|
217
|
+
console.log('Failed at:', failedHook.hookName);
|
|
218
|
+
console.log('Reason:', failedHook.reason);
|
|
219
|
+
console.log('Steps before failure:', result.results.length);
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Tracking Transformations
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
const result = executeHookChain(chain, store, quad);
|
|
227
|
+
|
|
228
|
+
result.results.forEach((r, i) => {
|
|
229
|
+
console.log(`Step ${i + 1}: ${r.hookName}`);
|
|
230
|
+
if (r.transformed) {
|
|
231
|
+
console.log(' → Transformation applied');
|
|
232
|
+
}
|
|
233
|
+
if (!r.passed) {
|
|
234
|
+
console.log(' → Validation failed:', r.reason);
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Testing
|
|
240
|
+
|
|
241
|
+
The example includes comprehensive tests:
|
|
242
|
+
|
|
243
|
+
- Individual hook behavior
|
|
244
|
+
- Chain execution order
|
|
245
|
+
- Early termination on failures
|
|
246
|
+
- Progressive transformations
|
|
247
|
+
- Result aggregation
|
|
248
|
+
|
|
249
|
+
Run tests with:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
pnpm test
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Learn More
|
|
256
|
+
|
|
257
|
+
- [@unrdf/hooks Documentation](../../README.md)
|
|
258
|
+
- [Policy Hooks Example](../policy-hooks/)
|
|
259
|
+
- [UNRDF Core](../../../core/)
|
|
260
|
+
|
|
261
|
+
## License
|
|
262
|
+
|
|
263
|
+
MIT
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
+
|
|
4
|
+
case `uname` in
|
|
5
|
+
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
+
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
+
basedir=`cygpath -w "$basedir"`
|
|
8
|
+
fi
|
|
9
|
+
;;
|
|
10
|
+
esac
|
|
11
|
+
|
|
12
|
+
if [ -z "$NODE_PATH" ]; then
|
|
13
|
+
export NODE_PATH="/Users/sac/unrdf/packages/hooks/examples/node_modules:/Users/sac/unrdf/packages/hooks/node_modules:/Users/sac/unrdf/packages/node_modules:/Users/sac/unrdf/node_modules:/Users/sac/node_modules:/Users/node_modules:/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules"
|
|
14
|
+
else
|
|
15
|
+
export NODE_PATH="/Users/sac/unrdf/packages/hooks/examples/node_modules:/Users/sac/unrdf/packages/hooks/node_modules:/Users/sac/unrdf/packages/node_modules:/Users/sac/unrdf/node_modules:/Users/sac/node_modules:/Users/node_modules:/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
+
fi
|
|
17
|
+
if [ -x "$basedir/node" ]; then
|
|
18
|
+
exec "$basedir/node" "$basedir/../@unrdf/hooks/examples/validate-hooks.mjs" "$@"
|
|
19
|
+
else
|
|
20
|
+
exec node "$basedir/../@unrdf/hooks/examples/validate-hooks.mjs" "$@"
|
|
21
|
+
fi
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
+
|
|
4
|
+
case `uname` in
|
|
5
|
+
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
+
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
+
basedir=`cygpath -w "$basedir"`
|
|
8
|
+
fi
|
|
9
|
+
;;
|
|
10
|
+
esac
|
|
11
|
+
|
|
12
|
+
if [ -z "$NODE_PATH" ]; then
|
|
13
|
+
export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/vitest@4.0.15_@opentelemetry+api@1.9.0_@types+node@24.10.1_@vitest+ui@4.0.15_happy-dom@_4020ef6a5cc83a28d6954792bad1f77a/node_modules/vitest/node_modules:/Users/sac/unrdf/node_modules/.pnpm/vitest@4.0.15_@opentelemetry+api@1.9.0_@types+node@24.10.1_@vitest+ui@4.0.15_happy-dom@_4020ef6a5cc83a28d6954792bad1f77a/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules"
|
|
14
|
+
else
|
|
15
|
+
export NODE_PATH="/Users/sac/unrdf/node_modules/.pnpm/vitest@4.0.15_@opentelemetry+api@1.9.0_@types+node@24.10.1_@vitest+ui@4.0.15_happy-dom@_4020ef6a5cc83a28d6954792bad1f77a/node_modules/vitest/node_modules:/Users/sac/unrdf/node_modules/.pnpm/vitest@4.0.15_@opentelemetry+api@1.9.0_@types+node@24.10.1_@vitest+ui@4.0.15_happy-dom@_4020ef6a5cc83a28d6954792bad1f77a/node_modules:/Users/sac/unrdf/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
+
fi
|
|
17
|
+
if [ -x "$basedir/node" ]; then
|
|
18
|
+
exec "$basedir/node" "$basedir/../vitest/vitest.mjs" "$@"
|
|
19
|
+
else
|
|
20
|
+
exec node "$basedir/../vitest/vitest.mjs" "$@"
|
|
21
|
+
fi
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":"4.0.15","results":[[":test/example.test.mjs",{"duration":7.120207999999991,"failed":false}]]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@unrdf/hooks-example-chains",
|
|
3
|
+
"version": "5.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Hook Chains Example - Sequential hook execution and composition",
|
|
6
|
+
"private": true,
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node src/index.mjs",
|
|
9
|
+
"test": "vitest run",
|
|
10
|
+
"test:watch": "vitest",
|
|
11
|
+
"test:coverage": "vitest run --coverage"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@unrdf/core": "workspace:*",
|
|
15
|
+
"@unrdf/hooks": "workspace:*",
|
|
16
|
+
"n3": "^1.26.0",
|
|
17
|
+
"zod": "^4.1.13"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"vitest": "^4.0.15"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|