@unrdf/kgn 5.0.1
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/LICENSE +21 -0
- package/README.md +210 -0
- package/package.json +90 -0
- package/src/MIGRATION_COMPLETE.md +186 -0
- package/src/PORT-MAP.md +302 -0
- package/src/base/filter-templates.js +479 -0
- package/src/base/index.js +92 -0
- package/src/base/injection-targets.js +583 -0
- package/src/base/macro-templates.js +298 -0
- package/src/base/macro-templates.js.bak +461 -0
- package/src/base/shacl-templates.js +617 -0
- package/src/base/template-base.js +388 -0
- package/src/core/attestor.js +381 -0
- package/src/core/filters.js +518 -0
- package/src/core/index.js +21 -0
- package/src/core/kgen-engine.js +372 -0
- package/src/core/parser.js +447 -0
- package/src/core/post-processor.js +313 -0
- package/src/core/renderer.js +469 -0
- package/src/doc-generator/cli.mjs +122 -0
- package/src/doc-generator/index.mjs +28 -0
- package/src/doc-generator/mdx-generator.mjs +71 -0
- package/src/doc-generator/nav-generator.mjs +136 -0
- package/src/doc-generator/parser.mjs +291 -0
- package/src/doc-generator/rdf-builder.mjs +306 -0
- package/src/doc-generator/scanner.mjs +189 -0
- package/src/engine/index.js +42 -0
- package/src/engine/pipeline.js +448 -0
- package/src/engine/renderer.js +604 -0
- package/src/engine/template-engine.js +566 -0
- package/src/filters/array.js +436 -0
- package/src/filters/data.js +479 -0
- package/src/filters/index.js +270 -0
- package/src/filters/rdf.js +264 -0
- package/src/filters/text.js +369 -0
- package/src/index.js +109 -0
- package/src/inheritance/index.js +40 -0
- package/src/injection/api.js +260 -0
- package/src/injection/atomic-writer.js +327 -0
- package/src/injection/constants.js +136 -0
- package/src/injection/idempotency-manager.js +295 -0
- package/src/injection/index.js +28 -0
- package/src/injection/injection-engine.js +378 -0
- package/src/injection/integration.js +339 -0
- package/src/injection/modes/index.js +341 -0
- package/src/injection/rollback-manager.js +373 -0
- package/src/injection/target-resolver.js +323 -0
- package/src/injection/tests/atomic-writer.test.js +382 -0
- package/src/injection/tests/injection-engine.test.js +611 -0
- package/src/injection/tests/integration.test.js +392 -0
- package/src/injection/tests/run-tests.js +283 -0
- package/src/injection/validation-engine.js +547 -0
- package/src/linter/determinism-linter.js +473 -0
- package/src/linter/determinism.js +410 -0
- package/src/linter/index.js +6 -0
- package/src/linter/test-doubles.js +475 -0
- package/src/parser/frontmatter.js +228 -0
- package/src/parser/variables.js +344 -0
- package/src/renderer/deterministic.js +245 -0
- package/src/renderer/index.js +6 -0
- package/src/templates/latex/academic-paper.njk +186 -0
- package/src/templates/latex/index.js +104 -0
- package/src/templates/nextjs/app-page.njk +66 -0
- package/src/templates/nextjs/index.js +80 -0
- package/src/templates/office/docx/document.njk +368 -0
- package/src/templates/office/index.js +79 -0
- package/src/templates/office/word-report.njk +129 -0
- package/src/utils/template-utils.js +426 -0
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KGEN Filter Templates - Deterministic filter definitions
|
|
3
|
+
*
|
|
4
|
+
* Provides templates for creating custom filters that maintain deterministic behavior
|
|
5
|
+
* All filter templates are designed to be composable and reusable
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import crypto from 'crypto';
|
|
9
|
+
|
|
10
|
+
export class KGenFilterTemplates {
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.options = {
|
|
13
|
+
deterministicMode: options.deterministicMode !== false,
|
|
14
|
+
staticBuildTime: options.staticBuildTime || '2024-01-01T00:00:00.000Z',
|
|
15
|
+
namespace: options.namespace || 'kgen',
|
|
16
|
+
...options
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
this.filterTemplates = new Map();
|
|
20
|
+
this.initializeFilterTemplates();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initialize built-in filter templates
|
|
25
|
+
*/
|
|
26
|
+
initializeFilterTemplates() {
|
|
27
|
+
// Basic filter template
|
|
28
|
+
this.registerFilterTemplate('basic_filter', {
|
|
29
|
+
name: '{{ filterName }}',
|
|
30
|
+
description: '{{ filterDescription | default("Custom filter") }}',
|
|
31
|
+
code: `(value, ...args) => {
|
|
32
|
+
// Input validation
|
|
33
|
+
if (value === null || value === undefined) {
|
|
34
|
+
return {{ defaultValue | default('value') }};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Filter logic
|
|
38
|
+
{{ filterLogic | default('return value;') }}
|
|
39
|
+
}`,
|
|
40
|
+
tests: [
|
|
41
|
+
{
|
|
42
|
+
input: '{{ testInput | default("test") }}',
|
|
43
|
+
expected: '{{ testOutput | default("test") }}',
|
|
44
|
+
description: 'Basic test case'
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Text processing filter template
|
|
50
|
+
this.registerFilterTemplate('text_filter', {
|
|
51
|
+
name: '{{ filterName }}',
|
|
52
|
+
description: 'Text processing filter: {{ filterDescription }}',
|
|
53
|
+
code: `(text, options = {}) => {
|
|
54
|
+
const str = String(text || '');
|
|
55
|
+
|
|
56
|
+
if (str === '') {
|
|
57
|
+
return {{ emptyValue | default('str') }};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Text processing options
|
|
61
|
+
const {
|
|
62
|
+
{{ filterOptions | join(',\n ') | default('trim = true') }}
|
|
63
|
+
} = options;
|
|
64
|
+
|
|
65
|
+
let result = str;
|
|
66
|
+
|
|
67
|
+
{{ textProcessingSteps | default('// Processing steps here') }}
|
|
68
|
+
|
|
69
|
+
return result;
|
|
70
|
+
}`,
|
|
71
|
+
tests: [
|
|
72
|
+
{
|
|
73
|
+
input: '" Hello World "',
|
|
74
|
+
expected: '"Hello World"',
|
|
75
|
+
description: 'Text trimming'
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Array processing filter template
|
|
81
|
+
this.registerFilterTemplate('array_filter', {
|
|
82
|
+
name: '{{ filterName }}',
|
|
83
|
+
description: 'Array processing filter: {{ filterDescription }}',
|
|
84
|
+
code: `(array, {{ filterParams | default('') }}) => {
|
|
85
|
+
if (!Array.isArray(array)) {
|
|
86
|
+
return {{ nonArrayDefault | default('[]') }};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (array.length === 0) {
|
|
90
|
+
return {{ emptyArrayDefault | default('array') }};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Array processing
|
|
94
|
+
const result = array{{ arrayMethod | default('.map(item => item)') }};
|
|
95
|
+
|
|
96
|
+
{{ additionalProcessing | default('// Additional processing') }}
|
|
97
|
+
|
|
98
|
+
return result;
|
|
99
|
+
}`,
|
|
100
|
+
tests: [
|
|
101
|
+
{
|
|
102
|
+
input: '[1, 2, 3, 4, 5]',
|
|
103
|
+
expected: '[1, 2, 3, 4, 5]',
|
|
104
|
+
description: 'Array processing test'
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Object processing filter template
|
|
110
|
+
this.registerFilterTemplate('object_filter', {
|
|
111
|
+
name: '{{ filterName }}',
|
|
112
|
+
description: 'Object processing filter: {{ filterDescription }}',
|
|
113
|
+
code: `(obj, {{ filterParams | default('') }}) => {
|
|
114
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
115
|
+
return {{ nonObjectDefault | default('{}') }};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const result = {{ objectDefault | default('{}') }};
|
|
119
|
+
|
|
120
|
+
{{ objectProcessing | default('// Object processing logic') }}
|
|
121
|
+
|
|
122
|
+
return result;
|
|
123
|
+
}`,
|
|
124
|
+
tests: [
|
|
125
|
+
{
|
|
126
|
+
input: '{ "name": "test" }',
|
|
127
|
+
expected: '{ "name": "test" }',
|
|
128
|
+
description: 'Object processing test'
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Deterministic filter template
|
|
134
|
+
this.registerFilterTemplate('deterministic_filter', {
|
|
135
|
+
name: '{{ filterName }}',
|
|
136
|
+
description: 'Deterministic filter: {{ filterDescription }}',
|
|
137
|
+
code: `(value, options = {}) => {
|
|
138
|
+
const { deterministicMode = ${this.options.deterministicMode} } = options;
|
|
139
|
+
|
|
140
|
+
// Deterministic behavior check
|
|
141
|
+
if (deterministicMode) {
|
|
142
|
+
{{ deterministicLogic | default('// Deterministic implementation') }}
|
|
143
|
+
} else {
|
|
144
|
+
{{ nonDeterministicLogic | default('// Non-deterministic implementation') }}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return value;
|
|
148
|
+
}`,
|
|
149
|
+
tests: [
|
|
150
|
+
{
|
|
151
|
+
input: '"test"',
|
|
152
|
+
options: '{ deterministicMode: true }',
|
|
153
|
+
expected: '"test"',
|
|
154
|
+
description: 'Deterministic mode test'
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Hash filter template
|
|
160
|
+
this.registerFilterTemplate('hash_filter', {
|
|
161
|
+
name: '{{ filterName }}',
|
|
162
|
+
description: 'Hash-based filter: {{ filterDescription }}',
|
|
163
|
+
code: `(content, algorithm = 'sha256', length = null) => {
|
|
164
|
+
const hash = crypto.createHash(algorithm)
|
|
165
|
+
.update(String(content || ''), 'utf8')
|
|
166
|
+
.digest('hex');
|
|
167
|
+
|
|
168
|
+
return length ? hash.substring(0, length) : hash;
|
|
169
|
+
}`,
|
|
170
|
+
tests: [
|
|
171
|
+
{
|
|
172
|
+
input: '"hello"',
|
|
173
|
+
expected: 'hash string',
|
|
174
|
+
description: 'Hash generation test'
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Validation filter template
|
|
180
|
+
this.registerFilterTemplate('validation_filter', {
|
|
181
|
+
name: '{{ filterName }}',
|
|
182
|
+
description: 'Validation filter: {{ filterDescription }}',
|
|
183
|
+
code: `(value, rules = {}) => {
|
|
184
|
+
const errors = [];
|
|
185
|
+
|
|
186
|
+
{{ validationRules | default('// Validation rules') }}
|
|
187
|
+
|
|
188
|
+
if (errors.length > 0) {
|
|
189
|
+
{{ onValidationError | default('throw new Error(\'Validation failed: \' + errors.join(\', \'));') }}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return value;
|
|
193
|
+
}`,
|
|
194
|
+
tests: [
|
|
195
|
+
{
|
|
196
|
+
input: '"valid_value"',
|
|
197
|
+
expected: '"valid_value"',
|
|
198
|
+
description: 'Valid input test'
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Format filter template
|
|
204
|
+
this.registerFilterTemplate('format_filter', {
|
|
205
|
+
name: '{{ filterName }}',
|
|
206
|
+
description: 'Format filter: {{ filterDescription }}',
|
|
207
|
+
code: `(value, format = '{{ defaultFormat | default("default") }}') => {
|
|
208
|
+
if (value === null || value === undefined) {
|
|
209
|
+
return '';
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
switch (format) {
|
|
213
|
+
{{ formatCases | default('case "default": return String(value);') }}
|
|
214
|
+
default:
|
|
215
|
+
return String(value);
|
|
216
|
+
}
|
|
217
|
+
}`,
|
|
218
|
+
tests: [
|
|
219
|
+
{
|
|
220
|
+
input: '"test"',
|
|
221
|
+
format: '"default"',
|
|
222
|
+
expected: '"test"',
|
|
223
|
+
description: 'Default format test'
|
|
224
|
+
}
|
|
225
|
+
]
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Composition filter template
|
|
229
|
+
this.registerFilterTemplate('composition_filter', {
|
|
230
|
+
name: '{{ filterName }}',
|
|
231
|
+
description: 'Composition filter: {{ filterDescription }}',
|
|
232
|
+
code: `(value, filters = [], context = {}) => {
|
|
233
|
+
let result = value;
|
|
234
|
+
|
|
235
|
+
for (const filter of filters) {
|
|
236
|
+
if (typeof filter === 'function') {
|
|
237
|
+
result = filter(result, context);
|
|
238
|
+
} else if (typeof filter === 'string' && context.filters && context.filters[filter]) {
|
|
239
|
+
result = context.filters[filter](result);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return result;
|
|
244
|
+
}`,
|
|
245
|
+
tests: [
|
|
246
|
+
{
|
|
247
|
+
input: '"test"',
|
|
248
|
+
filters: '[]',
|
|
249
|
+
expected: '"test"',
|
|
250
|
+
description: 'Empty composition test'
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Register a filter template
|
|
258
|
+
*/
|
|
259
|
+
registerFilterTemplate(name, template) {
|
|
260
|
+
this.filterTemplates.set(name, {
|
|
261
|
+
...template,
|
|
262
|
+
registered: this.options.staticBuildTime,
|
|
263
|
+
namespace: this.options.namespace
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Generate filter code from template
|
|
269
|
+
*/
|
|
270
|
+
generateFilter(templateName, context = {}) {
|
|
271
|
+
const template = this.filterTemplates.get(templateName);
|
|
272
|
+
if (!template) {
|
|
273
|
+
throw new Error(`Filter template '${templateName}' not found`);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Simple template substitution
|
|
277
|
+
let code = template.code;
|
|
278
|
+
|
|
279
|
+
// Replace template variables
|
|
280
|
+
for (const [key, value] of Object.entries(context)) {
|
|
281
|
+
const regex = new RegExp(`{{\\s*${key}\\s*(?:\\|[^}]*)?\\s*}}`, 'g');
|
|
282
|
+
|
|
283
|
+
// Handle default values
|
|
284
|
+
const matches = code.match(regex);
|
|
285
|
+
if (matches) {
|
|
286
|
+
for (const match of matches) {
|
|
287
|
+
const defaultMatch = match.match(/\|\s*default\('([^']*)'\)/);
|
|
288
|
+
const replacement = value !== undefined ? value : (defaultMatch ? defaultMatch[1] : match);
|
|
289
|
+
code = code.replace(match, replacement);
|
|
290
|
+
}
|
|
291
|
+
} else {
|
|
292
|
+
// Simple replacement without defaults
|
|
293
|
+
const simpleRegex = new RegExp(`{{\\s*${key}\\s*}}`, 'g');
|
|
294
|
+
code = code.replace(simpleRegex, String(value || ''));
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
name: this.interpolate(template.name, context),
|
|
300
|
+
description: this.interpolate(template.description, context),
|
|
301
|
+
code,
|
|
302
|
+
tests: template.tests?.map(test => ({
|
|
303
|
+
...test,
|
|
304
|
+
input: this.interpolate(test.input, context),
|
|
305
|
+
expected: this.interpolate(test.expected, context)
|
|
306
|
+
})) || []
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Generate complete filter module
|
|
312
|
+
*/
|
|
313
|
+
generateFilterModule(filters = [], moduleName = 'CustomFilters') {
|
|
314
|
+
const generatedFilters = filters.map(filter =>
|
|
315
|
+
this.generateFilter(filter.template, filter.context)
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
const code = [`/**`];
|
|
319
|
+
code.push(` * ${moduleName} - Generated KGEN Filters`);
|
|
320
|
+
code.push(` * `);
|
|
321
|
+
code.push(` * @generated ${this.options.staticBuildTime}`);
|
|
322
|
+
code.push(` * @namespace ${this.options.namespace}`);
|
|
323
|
+
code.push(` */`);
|
|
324
|
+
code.push('');
|
|
325
|
+
code.push('import crypto from \'crypto\';');
|
|
326
|
+
code.push('');
|
|
327
|
+
code.push(`export class ${moduleName} {`);
|
|
328
|
+
code.push(' constructor(options = {}) {');
|
|
329
|
+
code.push(' this.options = { ...options };');
|
|
330
|
+
code.push(' this.filters = new Map();');
|
|
331
|
+
code.push(' this.registerFilters();');
|
|
332
|
+
code.push(' }');
|
|
333
|
+
code.push('');
|
|
334
|
+
code.push(' registerFilters() {');
|
|
335
|
+
|
|
336
|
+
// Add each generated filter
|
|
337
|
+
for (const filter of generatedFilters) {
|
|
338
|
+
code.push(` // ${filter.description}`);
|
|
339
|
+
code.push(` this.filters.set('${filter.name}', ${filter.code});`);
|
|
340
|
+
code.push('');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
code.push(' }');
|
|
344
|
+
code.push('');
|
|
345
|
+
code.push(' getFilter(name) {');
|
|
346
|
+
code.push(' return this.filters.get(name);');
|
|
347
|
+
code.push(' }');
|
|
348
|
+
code.push('');
|
|
349
|
+
code.push(' getAllFilters() {');
|
|
350
|
+
code.push(' return Object.fromEntries(this.filters);');
|
|
351
|
+
code.push(' }');
|
|
352
|
+
code.push('}');
|
|
353
|
+
code.push('');
|
|
354
|
+
code.push(`export default ${moduleName};`);
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
code: code.join('\n'),
|
|
358
|
+
filters: generatedFilters,
|
|
359
|
+
metadata: {
|
|
360
|
+
moduleName,
|
|
361
|
+
filterCount: generatedFilters.length,
|
|
362
|
+
generated: this.options.staticBuildTime,
|
|
363
|
+
namespace: this.options.namespace
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Simple template interpolation
|
|
370
|
+
*/
|
|
371
|
+
interpolate(template, context) {
|
|
372
|
+
let result = template;
|
|
373
|
+
|
|
374
|
+
for (const [key, value] of Object.entries(context)) {
|
|
375
|
+
const regex = new RegExp(`{{\\s*${key}\\s*(?:\\|[^}]*)?\\s*}}`, 'g');
|
|
376
|
+
|
|
377
|
+
const matches = result.match(regex);
|
|
378
|
+
if (matches) {
|
|
379
|
+
for (const match of matches) {
|
|
380
|
+
const defaultMatch = match.match(/\|\s*default\('([^']*)'\)/);
|
|
381
|
+
const replacement = value !== undefined ? value : (defaultMatch ? defaultMatch[1] : match);
|
|
382
|
+
result = result.replace(match, replacement);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Get available filter template names
|
|
392
|
+
*/
|
|
393
|
+
getTemplateNames() {
|
|
394
|
+
return Array.from(this.filterTemplates.keys()).sort();
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Get filter template by name
|
|
399
|
+
*/
|
|
400
|
+
getTemplate(name) {
|
|
401
|
+
return this.filterTemplates.get(name);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Generate filter documentation
|
|
406
|
+
*/
|
|
407
|
+
generateDocs(templateNames = []) {
|
|
408
|
+
const templates = templateNames.length > 0
|
|
409
|
+
? templateNames.map(name => ({ name, ...this.filterTemplates.get(name) })).filter(t => t.name)
|
|
410
|
+
: Array.from(this.filterTemplates.entries()).map(([name, template]) => ({ name, ...template }));
|
|
411
|
+
|
|
412
|
+
const docs = ['# KGEN Filter Templates'];
|
|
413
|
+
docs.push('');
|
|
414
|
+
docs.push(`Generated: ${this.options.staticBuildTime}`);
|
|
415
|
+
docs.push(`Templates: ${templates.length}`);
|
|
416
|
+
docs.push('');
|
|
417
|
+
|
|
418
|
+
for (const template of templates.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
419
|
+
docs.push(`## ${template.name}`);
|
|
420
|
+
docs.push('');
|
|
421
|
+
docs.push(template.description);
|
|
422
|
+
docs.push('');
|
|
423
|
+
|
|
424
|
+
if (template.tests && template.tests.length > 0) {
|
|
425
|
+
docs.push('### Tests');
|
|
426
|
+
docs.push('');
|
|
427
|
+
|
|
428
|
+
for (const test of template.tests) {
|
|
429
|
+
docs.push(`- **${test.description}**`);
|
|
430
|
+
docs.push(` - Input: \`${test.input}\``);
|
|
431
|
+
docs.push(` - Expected: \`${test.expected}\``);
|
|
432
|
+
docs.push('');
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
docs.push('---');
|
|
437
|
+
docs.push('');
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return docs.join('\n');
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Export filter templates
|
|
445
|
+
*/
|
|
446
|
+
exportTemplates(templateNames = []) {
|
|
447
|
+
const templatesToExport = templateNames.length > 0
|
|
448
|
+
? templateNames.filter(name => this.filterTemplates.has(name))
|
|
449
|
+
: Array.from(this.filterTemplates.keys());
|
|
450
|
+
|
|
451
|
+
const exported = {
|
|
452
|
+
format: 'kgen-filter-templates',
|
|
453
|
+
version: '1.0.0',
|
|
454
|
+
generated: this.options.staticBuildTime,
|
|
455
|
+
namespace: this.options.namespace,
|
|
456
|
+
templates: {}
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
for (const name of templatesToExport) {
|
|
460
|
+
exported.templates[name] = this.filterTemplates.get(name);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return exported;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Get template statistics
|
|
468
|
+
*/
|
|
469
|
+
getStats() {
|
|
470
|
+
return {
|
|
471
|
+
totalTemplates: this.filterTemplates.size,
|
|
472
|
+
namespace: this.options.namespace,
|
|
473
|
+
deterministicMode: this.options.deterministicMode,
|
|
474
|
+
templates: Array.from(this.filterTemplates.keys()).sort()
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
export default KGenFilterTemplates;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KGEN Base Templates - Foundation template system
|
|
3
|
+
*
|
|
4
|
+
* Exports all base template classes and utilities for building
|
|
5
|
+
* deterministic, reusable template components
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Base template foundation
|
|
9
|
+
export { KGenTemplateBase } from './template-base.js';
|
|
10
|
+
|
|
11
|
+
// Macro system for reusable components
|
|
12
|
+
export { KGenMacroTemplates } from './macro-templates.js';
|
|
13
|
+
|
|
14
|
+
// Filter system for deterministic data processing
|
|
15
|
+
export { KGenFilterTemplates } from './filter-templates.js';
|
|
16
|
+
|
|
17
|
+
// SHACL validation templates for RDF knowledge graphs
|
|
18
|
+
export { KGenSHACLTemplates } from './shacl-templates.js';
|
|
19
|
+
|
|
20
|
+
// Injection targets for code modification
|
|
21
|
+
export { KGenInjectionTargets } from './injection-targets.js';
|
|
22
|
+
|
|
23
|
+
// Convenience factory function
|
|
24
|
+
export function createBaseTemplate(options = {}) {
|
|
25
|
+
return new KGenTemplateBase(options);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Template system factory
|
|
29
|
+
export function createTemplateSystem(options = {}) {
|
|
30
|
+
const base = new KGenTemplateBase(options);
|
|
31
|
+
const macros = new KGenMacroTemplates(options);
|
|
32
|
+
const filters = new KGenFilterTemplates(options);
|
|
33
|
+
const shacl = new KGenSHACLTemplates(options);
|
|
34
|
+
const injection = new KGenInjectionTargets(options);
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
base,
|
|
38
|
+
macros,
|
|
39
|
+
filters,
|
|
40
|
+
shacl,
|
|
41
|
+
injection,
|
|
42
|
+
|
|
43
|
+
// Convenience methods
|
|
44
|
+
generateTemplate(templateName, context = {}) {
|
|
45
|
+
return base.generateFromTemplate(templateName, context);
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
generateMacro(macroName, context = {}) {
|
|
49
|
+
const macro = macros.getMacro(macroName);
|
|
50
|
+
if (!macro) {
|
|
51
|
+
throw new Error(`Macro '${macroName}' not found`);
|
|
52
|
+
}
|
|
53
|
+
return base.engine.renderTemplate(macro.template, context);
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
generateFilter(filterName, context = {}) {
|
|
57
|
+
return filters.generateFilter(filterName, context);
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
generateSHACLShape(shapeName, context = {}) {
|
|
61
|
+
return shacl.generateShape(shapeName, context);
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
generateInjectionTarget(targetName, context = {}) {
|
|
65
|
+
return injection.generateTarget(targetName, context);
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
// System information
|
|
69
|
+
getStats() {
|
|
70
|
+
return {
|
|
71
|
+
base: base.getStats(),
|
|
72
|
+
macros: macros.getStats(),
|
|
73
|
+
filters: filters.getStats(),
|
|
74
|
+
shacl: shacl.getStats(),
|
|
75
|
+
injection: injection.getStats()
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Default export object
|
|
82
|
+
const BaseTemplates = {
|
|
83
|
+
get KGenTemplateBase() { return KGenTemplateBase; },
|
|
84
|
+
get KGenMacroTemplates() { return KGenMacroTemplates; },
|
|
85
|
+
get KGenFilterTemplates() { return KGenFilterTemplates; },
|
|
86
|
+
get KGenSHACLTemplates() { return KGenSHACLTemplates; },
|
|
87
|
+
get KGenInjectionTargets() { return KGenInjectionTargets; },
|
|
88
|
+
createBaseTemplate,
|
|
89
|
+
createTemplateSystem
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default BaseTemplates;
|