@unrdf/kgn 5.0.1 → 26.4.3

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 (59) hide show
  1. package/dist/index.mjs +9207 -0
  2. package/package.json +18 -14
  3. package/src/base/filter-templates.js +7 -1
  4. package/src/base/index.js +15 -10
  5. package/src/base/injection-targets.js +6 -0
  6. package/src/base/macro-templates.js +6 -0
  7. package/src/base/shacl-templates.js +6 -0
  8. package/src/base/template-base.js +7 -1
  9. package/src/core/attestor.js +50 -1
  10. package/src/core/filters.js +134 -1
  11. package/src/core/index.js +8 -1
  12. package/src/core/kgen-engine.js +49 -1
  13. package/src/core/parser.js +52 -1
  14. package/src/core/post-processor.js +7 -1
  15. package/src/core/renderer.js +67 -1
  16. package/src/doc-generator/mdx-generator.mjs +1 -1
  17. package/src/doc-generator/nav-generator.mjs +1 -1
  18. package/src/doc-generator/rdf-builder.mjs +2 -2
  19. package/src/engine/index.js +9 -0
  20. package/src/engine/pipeline.js +7 -1
  21. package/src/engine/renderer.js +18 -3
  22. package/src/engine/template-engine.js +12 -3
  23. package/src/filters/array.js +14 -6
  24. package/src/filters/index.js +165 -17
  25. package/src/filters/rdf.js +3 -3
  26. package/src/{index.js → index.mjs} +46 -0
  27. package/src/index.test.mjs +40 -0
  28. package/src/inheritance/index.js +19 -1
  29. package/src/injection/atomic-writer.js +22 -1
  30. package/src/injection/idempotency-manager.js +33 -0
  31. package/src/injection/injection-engine.js +46 -1
  32. package/src/injection/integration.js +3 -3
  33. package/src/injection/modes/index.js +30 -0
  34. package/src/injection/rollback-manager.js +26 -2
  35. package/src/injection/target-resolver.js +48 -3
  36. package/src/injection/tests/injection-engine.test.js +3 -3
  37. package/src/injection/tests/integration.test.js +2 -1
  38. package/src/injection/tests/run-tests.js +3 -0
  39. package/src/injection/validation-engine.js +71 -5
  40. package/src/linter/determinism-linter.js +20 -5
  41. package/src/linter/determinism.js +8 -2
  42. package/src/linter/index.js +3 -1
  43. package/src/linter/test-doubles.js +151 -4
  44. package/src/parser/frontmatter.js +6 -0
  45. package/src/parser/variables.js +7 -1
  46. package/src/rdf/filters.js +393 -0
  47. package/src/rdf/index.js +444 -0
  48. package/src/renderer/deterministic.js +6 -0
  49. package/src/renderer/index.js +3 -1
  50. package/src/templates/rdf/DELIVERY-SUMMARY.md +266 -0
  51. package/src/templates/rdf/README.md +595 -0
  52. package/src/templates/rdf/dataset.njk +83 -0
  53. package/src/templates/rdf/index.js +106 -0
  54. package/src/templates/rdf/jsonld-context.njk +63 -0
  55. package/src/templates/rdf/ontology.njk +107 -0
  56. package/src/templates/rdf/schema.njk +79 -0
  57. package/src/templates/rdf/shapes.njk +89 -0
  58. package/src/templates/rdf/sparql-queries.njk +70 -0
  59. package/src/templates/rdf/vocabulary.njk +79 -0
@@ -71,13 +71,21 @@ export const sort = (arr, key = null) => {
71
71
  };
72
72
 
73
73
  /**
74
- * Reverse array
75
- * @param {any} arr - Input array
76
- * @returns {Array} Reversed array
74
+ * Reverse array or string
75
+ * @param {any} value - Input array or string
76
+ * @returns {Array|string} Reversed array or string
77
77
  */
78
- export const reverse = (arr) => {
79
- if (!Array.isArray(arr)) return arr;
80
- return [...arr].reverse();
78
+ export const reverse = (value) => {
79
+ // Handle strings
80
+ if (typeof value === 'string') {
81
+ return value.split('').reverse().join('');
82
+ }
83
+ // Handle arrays
84
+ if (Array.isArray(value)) {
85
+ return [...value].reverse();
86
+ }
87
+ // Return other types unchanged
88
+ return value;
81
89
  };
82
90
 
83
91
  /**
@@ -29,6 +29,16 @@ export function createCustomFilters(options = {}) {
29
29
  ...dataFilters,
30
30
  ...rdfFilters,
31
31
 
32
+ // Smart reverse filter that works with both strings and arrays
33
+ reverse: input => {
34
+ if (Array.isArray(input)) {
35
+ return [...input].reverse();
36
+ }
37
+ // Treat as string
38
+ if (input === null || input === undefined) return '';
39
+ return String(input).split('').reverse().join('');
40
+ },
41
+
32
42
  // Enhanced deterministic filters that override or augment the base filters
33
43
 
34
44
  // Deterministic date/time formatting
@@ -61,9 +71,10 @@ export function createCustomFilters(options = {}) {
61
71
  const d = new Date(date);
62
72
  if (isNaN(d.getTime())) return '';
63
73
 
64
- const hours = d.getHours().toString().padStart(2, '0');
65
- const minutes = d.getMinutes().toString().padStart(2, '0');
66
- const seconds = d.getSeconds().toString().padStart(2, '0');
74
+ // Use UTC time to match test expectations
75
+ const hours = d.getUTCHours().toString().padStart(2, '0');
76
+ const minutes = d.getUTCMinutes().toString().padStart(2, '0');
77
+ const seconds = d.getUTCSeconds().toString().padStart(2, '0');
67
78
 
68
79
  switch (format) {
69
80
  case 'HH:mm:ss':
@@ -75,6 +86,48 @@ export function createCustomFilters(options = {}) {
75
86
  }
76
87
  },
77
88
 
89
+ // Date arithmetic - add days to a date
90
+ dateAdd: (date, amount, unit = 'day') => {
91
+ const d = new Date(date);
92
+ if (isNaN(d.getTime())) return '';
93
+
94
+ switch (unit.toLowerCase()) {
95
+ case 'day':
96
+ case 'days':
97
+ d.setUTCDate(d.getUTCDate() + amount);
98
+ break;
99
+ case 'month':
100
+ case 'months':
101
+ d.setUTCMonth(d.getUTCMonth() + amount);
102
+ break;
103
+ case 'year':
104
+ case 'years':
105
+ d.setUTCFullYear(d.getUTCFullYear() + amount);
106
+ break;
107
+ case 'hour':
108
+ case 'hours':
109
+ d.setUTCHours(d.getUTCHours() + amount);
110
+ break;
111
+ case 'minute':
112
+ case 'minutes':
113
+ d.setUTCMinutes(d.getUTCMinutes() + amount);
114
+ break;
115
+ case 'second':
116
+ case 'seconds':
117
+ d.setUTCSeconds(d.getUTCSeconds() + amount);
118
+ break;
119
+ default:
120
+ return '';
121
+ }
122
+
123
+ return d.toISOString();
124
+ },
125
+
126
+ // Date arithmetic - subtract days from a date
127
+ dateSub: (date, amount, unit = 'day') => {
128
+ return allFilters.dateAdd(date, -amount, unit);
129
+ },
130
+
78
131
  // Deterministic timestamp
79
132
  timestamp: () => {
80
133
  if (deterministicMode) {
@@ -93,7 +146,7 @@ export function createCustomFilters(options = {}) {
93
146
  },
94
147
 
95
148
  // File and path utilities
96
- filename: (filePath) => {
149
+ filename: filePath => {
97
150
  if (!filePath) return '';
98
151
  return filePath.split('/').pop().split('\\').pop();
99
152
  },
@@ -107,7 +160,7 @@ export function createCustomFilters(options = {}) {
107
160
  return dotIndex > 0 ? name.slice(0, dotIndex) : name;
108
161
  },
109
162
 
110
- dirname: (filePath) => {
163
+ dirname: filePath => {
111
164
  if (!filePath) return '';
112
165
  const parts = filePath.split('/');
113
166
  if (parts.length === 1) {
@@ -118,20 +171,104 @@ export function createCustomFilters(options = {}) {
118
171
  return parts.slice(0, -1).join('/');
119
172
  },
120
173
 
174
+ // Date arithmetic filters
175
+ dateAdd: (dateStr, amount, unit = 'day') => {
176
+ const date = new Date(dateStr);
177
+ switch (unit) {
178
+ case 'day':
179
+ date.setDate(date.getDate() + amount);
180
+ break;
181
+ case 'month':
182
+ date.setMonth(date.getMonth() + amount);
183
+ break;
184
+ case 'year':
185
+ date.setFullYear(date.getFullYear() + amount);
186
+ break;
187
+ default:
188
+ throw new Error(`Unknown unit: ${unit}`);
189
+ }
190
+ return date.toISOString();
191
+ },
192
+
193
+ dateSub: (dateStr, amount, unit = 'day') => {
194
+ const date = new Date(dateStr);
195
+ switch (unit) {
196
+ case 'day':
197
+ date.setDate(date.getDate() - amount);
198
+ break;
199
+ case 'month':
200
+ date.setMonth(date.getMonth() - amount);
201
+ break;
202
+ case 'year':
203
+ date.setFullYear(date.getFullYear() - amount);
204
+ break;
205
+ default:
206
+ throw new Error(`Unknown unit: ${unit}`);
207
+ }
208
+ return date.toISOString();
209
+ },
210
+
211
+ // Path utility filters
212
+ resolve: (base, relative) => {
213
+ // Simple path resolution (normalize and join)
214
+ const baseParts = base.split('/').filter(p => p);
215
+ const relativeParts = relative.split('/').filter(p => p);
216
+
217
+ for (const part of relativeParts) {
218
+ if (part === '..') {
219
+ baseParts.pop();
220
+ } else if (part !== '.') {
221
+ baseParts.push(part);
222
+ }
223
+ }
224
+
225
+ return '/' + baseParts.join('/');
226
+ },
227
+
228
+ relative: (from, to) => {
229
+ // Simple relative path calculation
230
+ const fromParts = from.split('/').filter(p => p);
231
+ const toParts = to.split('/').filter(p => p);
232
+
233
+ // Find common base
234
+ let i = 0;
235
+ while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {
236
+ i++;
237
+ }
238
+
239
+ // Go up from 'from' directory
240
+ const upCount = fromParts.length - i;
241
+ const upParts = Array(upCount).fill('..');
242
+
243
+ // Then append remaining 'to' parts
244
+ const remainingParts = toParts.slice(i);
245
+
246
+ return [...upParts, ...remainingParts].join('/');
247
+ },
248
+
121
249
  // Code generation helpers
122
250
  comment: (text, style = '//') => {
123
251
  if (!text) return '';
124
252
  switch (style) {
125
253
  case '//':
126
- return text.split('\n').map(line => `// ${line}`).join('\n');
254
+ return text
255
+ .split('\n')
256
+ .map(line => `// ${line}`)
257
+ .join('\n');
127
258
  case '#':
128
- return text.split('\n').map(line => `# ${line}`).join('\n');
259
+ return text
260
+ .split('\n')
261
+ .map(line => `# ${line}`)
262
+ .join('\n');
129
263
  case '/*':
130
264
  return `/* ${text} */`;
131
265
  case '<!--':
132
266
  return `<!-- ${text} -->`;
133
267
  default:
134
- return text.split('\n').map(line => `${style} ${line}`).join('\n');
268
+ return text
269
+ .split('\n')
270
+ .map(line => `${style} ${line}`)
271
+ .join('\n');
135
272
  }
136
273
  },
137
274
 
@@ -146,21 +283,27 @@ export function createCustomFilters(options = {}) {
146
283
  // Determinism blockers - these will throw in deterministic mode
147
284
  now: () => {
148
285
  if (deterministicMode) {
149
- throw new Error('Filter "now" is not allowed in deterministic mode. Use "timestamp" instead.');
286
+ throw new Error(
287
+ 'Filter "now" is not allowed in deterministic mode. Use "timestamp" instead.'
288
+ );
150
289
  }
151
290
  return new Date().toISOString();
152
291
  },
153
292
 
154
293
  random: () => {
155
294
  if (deterministicMode) {
156
- throw new Error('Filter "random" is not allowed in deterministic mode. Use "hash" for consistent randomness.');
295
+ throw new Error(
296
+ 'Filter "random" is not allowed in deterministic mode. Use "hash" for consistent randomness.'
297
+ );
157
298
  }
158
299
  return Math.random();
159
300
  },
160
301
 
161
302
  uuid: () => {
162
303
  if (deterministicMode) {
163
- throw new Error('Filter "uuid" is not allowed in deterministic mode. Use "hash" for consistent IDs.');
304
+ throw new Error(
305
+ 'Filter "uuid" is not allowed in deterministic mode. Use "hash" for consistent IDs.'
306
+ );
164
307
  }
165
308
  return crypto.randomUUID();
166
309
  },
@@ -175,7 +318,9 @@ export function createCustomFilters(options = {}) {
175
318
 
176
319
  // Get headers from first object
177
320
  if (headers && data.length > 0 && typeof data[0] === 'object') {
178
- const headerRow = Object.keys(data[0]).map(h => `${quote}${h}${quote}`).join(delimiter);
321
+ const headerRow = Object.keys(data[0])
322
+ .map(h => `${quote}${h}${quote}`)
323
+ .join(delimiter);
179
324
  lines.push(headerRow);
180
325
  }
181
326
 
@@ -214,9 +359,12 @@ export function createCustomFilters(options = {}) {
214
359
  // Separator row
215
360
  const separators = headers.map(() => {
216
361
  switch (align) {
217
- case 'center': return ':---:';
218
- case 'right': return '---:';
219
- default: return '---';
362
+ case 'center':
363
+ return ':---:';
364
+ case 'right':
365
+ return '---:';
366
+ default:
367
+ return '---';
220
368
  }
221
369
  });
222
370
  lines.push('| ' + separators.join(' | ') + ' |');
@@ -229,7 +377,7 @@ export function createCustomFilters(options = {}) {
229
377
  }
230
378
 
231
379
  return lines.join('\n');
232
- }
380
+ },
233
381
  };
234
382
 
235
383
  return allFilters;
@@ -267,4 +415,4 @@ export { textFilters, arrayFilters, dataFilters, rdfFilters };
267
415
  /**
268
416
  * Export default function
269
417
  */
270
- export default createCustomFilters;
418
+ export default createCustomFilters;
@@ -79,7 +79,7 @@ export const contract = (uri, prefixes = {}) => {
79
79
  * @param {any} dataset - Mock dataset (ignored in stub)
80
80
  * @returns {Array} Mock query results
81
81
  */
82
- export const sparql = async (query, dataset = null) => {
82
+ export const sparql = async (query, _dataset = null) => {
83
83
  if (!query || typeof query !== 'string') return [];
84
84
 
85
85
  // Return mock results for known queries
@@ -227,7 +227,7 @@ export const rdfDatatype = (value, datatype = 'string') => {
227
227
  * @param {any} shape - SHACL shape
228
228
  * @returns {Object} Mock validation result
229
229
  */
230
- export const shaclValidate = (data, shape) => {
230
+ export const shaclValidate = (_data, _shape) => {
231
231
  return {
232
232
  conforms: true,
233
233
  results: [],
@@ -241,7 +241,7 @@ export const shaclValidate = (data, shape) => {
241
241
  * @param {string} reasoner - Reasoner type
242
242
  * @returns {any} Original graph (no inference applied)
243
243
  */
244
- export const infer = (graph, reasoner = 'rdfs') => {
244
+ export const infer = (graph, _reasoner = 'rdfs') => {
245
245
  return graph; // No-op for stub
246
246
  };
247
247
 
@@ -11,6 +11,13 @@
11
11
  * - Marker-based targeting and rollback capabilities (NEW)
12
12
  */
13
13
 
14
+ // Import classes/functions for local use
15
+ import { TemplateEngine, EnhancedTemplateEngine } from './engine/template-engine.js';
16
+ import { TemplateInheritanceEngine } from './inheritance/index.js';
17
+ import { enhanceKgenWithInjection } from './injection/integration.js';
18
+ import { initializeInjection } from './injection/api.js';
19
+
20
+ // Re-export for external use
14
21
  export { TemplateEngine, EnhancedTemplateEngine } from './engine/template-engine.js';
15
22
  export { TemplateInheritanceEngine } from './inheritance/index.js';
16
23
  export { createCustomFilters } from './filters/index.js';
@@ -75,6 +82,9 @@ export {
75
82
  } from './injection/constants.js';
76
83
 
77
84
  // Enhanced engine factory with inheritance and injection support
85
+ /**
86
+ *
87
+ */
78
88
  export function createEngine(options = {}) {
79
89
  // Use EnhancedTemplateEngine by default for inheritance support
80
90
  const engineClass = options.useBasicEngine ? TemplateEngine : EnhancedTemplateEngine;
@@ -89,11 +99,17 @@ export function createEngine(options = {}) {
89
99
  }
90
100
 
91
101
  // Inheritance-specific engine factory
102
+ /**
103
+ *
104
+ */
92
105
  export function createInheritanceEngine(options = {}) {
93
106
  return new TemplateInheritanceEngine(options);
94
107
  }
95
108
 
96
109
  // Enhanced template engine factory (inheritance + all features)
110
+ /**
111
+ *
112
+ */
97
113
  export function createEnhancedEngine(options = {}) {
98
114
  return new EnhancedTemplateEngine({
99
115
  enableInheritance: true,
@@ -104,6 +120,36 @@ export function createEnhancedEngine(options = {}) {
104
120
  }
105
121
 
106
122
  // Injection-specific engine factory
123
+ /**
124
+ *
125
+ */
107
126
  export function createInjectionEngine(injectionConfig = {}) {
108
127
  return initializeInjection(injectionConfig);
128
+ }
129
+
130
+ // RDF TEMPLATE SYSTEM EXPORTS (NEW)
131
+ // RDF-aware template engine with @unrdf/core integration
132
+ export {
133
+ RdfTemplateEngine,
134
+ createRdfTemplateEngine,
135
+ renderRdfTemplate,
136
+ RdfTemplateEngineConfigSchema,
137
+ RdfRenderContextSchema,
138
+ SparqlTemplateSchema,
139
+ } from './rdf/index.js';
140
+
141
+ // RDF template filters
142
+ export {
143
+ rdfTemplateFilters,
144
+ toTurtle,
145
+ toSparql,
146
+ rdfPrefix,
147
+ blankNode,
148
+ literal,
149
+ } from './rdf/filters.js';
150
+
151
+ // RDF engine factory
152
+ export async function createRdfEngine(config = {}) {
153
+ const { RdfTemplateEngine } = await import('./rdf/index.js');
154
+ return new RdfTemplateEngine(config);
109
155
  }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @file KGN package basic tests
3
+ */
4
+
5
+ import { describe, it, expect } from 'vitest';
6
+ import {
7
+ createEngine,
8
+ createInheritanceEngine,
9
+ createEnhancedEngine,
10
+ TemplateEngine,
11
+ EnhancedTemplateEngine,
12
+ } from './index.mjs';
13
+
14
+ describe('@unrdf/kgn', () => {
15
+ it('should export main engine classes', () => {
16
+ expect(TemplateEngine).toBeDefined();
17
+ expect(EnhancedTemplateEngine).toBeDefined();
18
+ });
19
+
20
+ it('should create basic engine', () => {
21
+ const engine = createEngine({ useBasicEngine: true });
22
+ expect(engine).toBeDefined();
23
+ expect(engine).toBeInstanceOf(TemplateEngine);
24
+ });
25
+
26
+ it('should create enhanced engine by default', () => {
27
+ const engine = createEngine();
28
+ expect(engine).toBeDefined();
29
+ });
30
+
31
+ it('should create inheritance engine', () => {
32
+ const engine = createInheritanceEngine();
33
+ expect(engine).toBeDefined();
34
+ });
35
+
36
+ it('should create enhanced engine with options', () => {
37
+ const engine = createEnhancedEngine({ enableCache: false });
38
+ expect(engine).toBeDefined();
39
+ });
40
+ });
@@ -2,12 +2,21 @@
2
2
  * Template Inheritance System - Placeholder for future implementation
3
3
  */
4
4
 
5
+ /**
6
+ *
7
+ */
5
8
  export class TemplateInheritanceEngine {
9
+ /**
10
+ *
11
+ */
6
12
  constructor(options = {}) {
7
13
  this.options = options;
8
14
  }
9
15
 
10
- async processTemplate(templatePath, context = {}) {
16
+ /**
17
+ *
18
+ */
19
+ async processTemplate(templatePath, _context = {}) {
11
20
  // Basic implementation for build compatibility
12
21
  return {
13
22
  templatePath,
@@ -18,6 +27,9 @@ export class TemplateInheritanceEngine {
18
27
  };
19
28
  }
20
29
 
30
+ /**
31
+ *
32
+ */
21
33
  getStats() {
22
34
  return {
23
35
  templatesProcessed: 0,
@@ -28,10 +40,16 @@ export class TemplateInheritanceEngine {
28
40
  };
29
41
  }
30
42
 
43
+ /**
44
+ *
45
+ */
31
46
  async clearCache() {
32
47
  // No-op for now
33
48
  }
34
49
 
50
+ /**
51
+ *
52
+ */
35
53
  getConfig() {
36
54
  return this.options;
37
55
  }
@@ -10,9 +10,15 @@ import { join, dirname, basename, extname } from 'path';
10
10
  import { createHash } from 'crypto';
11
11
  import { pipeline } from 'stream/promises';
12
12
 
13
- import { ERROR_CODES, CHECKSUM_ALGORITHMS, LOCK_CONFIG } from './constants.js';
13
+ import { ERROR_CODES as _ERROR_CODES, CHECKSUM_ALGORITHMS, LOCK_CONFIG } from './constants.js';
14
14
 
15
+ /**
16
+ *
17
+ */
15
18
  export class AtomicWriter {
19
+ /**
20
+ *
21
+ */
16
22
  constructor(config = {}) {
17
23
  this.config = config;
18
24
  this.activeLocks = new Map();
@@ -118,6 +124,9 @@ export class AtomicWriter {
118
124
  * Private Methods
119
125
  */
120
126
 
127
+ /**
128
+ *
129
+ */
121
130
  async _acquireLock(filePath) {
122
131
  const lockId = `${filePath}-${Date.now()}-${Math.random()}`;
123
132
  const startTime = Date.now();
@@ -154,6 +163,9 @@ export class AtomicWriter {
154
163
  throw new Error(`Failed to acquire lock for ${filePath} within timeout`);
155
164
  }
156
165
 
166
+ /**
167
+ *
168
+ */
157
169
  async _releaseLock(lockId) {
158
170
  const lockFile = this.activeLocks.get(lockId);
159
171
  if (lockFile) {
@@ -166,6 +178,9 @@ export class AtomicWriter {
166
178
  }
167
179
  }
168
180
 
181
+ /**
182
+ *
183
+ */
169
184
  async _createBackup(filePath, operationId) {
170
185
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
171
186
  const ext = extname(filePath);
@@ -182,6 +197,9 @@ export class AtomicWriter {
182
197
  return backupPath;
183
198
  }
184
199
 
200
+ /**
201
+ *
202
+ */
185
203
  async _createTempFile(filePath) {
186
204
  const dir = dirname(filePath);
187
205
  const base = basename(filePath);
@@ -189,6 +207,9 @@ export class AtomicWriter {
189
207
  return join(dir, tempName);
190
208
  }
191
209
 
210
+ /**
211
+ *
212
+ */
192
213
  async _calculateChecksum(filePath, algorithm = CHECKSUM_ALGORITHMS.SHA256) {
193
214
  const hash = createHash(algorithm);
194
215
  const stream = createReadStream(filePath);
@@ -10,7 +10,13 @@ import { createHash } from 'crypto';
10
10
 
11
11
  import { SKIP_IF_LOGIC, CHECKSUM_ALGORITHMS } from './constants.js';
12
12
 
13
+ /**
14
+ *
15
+ */
13
16
  export class IdempotencyManager {
17
+ /**
18
+ *
19
+ */
14
20
  constructor(config = {}) {
15
21
  this.config = config;
16
22
  this.contentCache = new Map();
@@ -103,6 +109,9 @@ export class IdempotencyManager {
103
109
  * Private Methods
104
110
  */
105
111
 
112
+ /**
113
+ *
114
+ */
106
115
  async _evaluateSingleCondition(condition, target, content, variables) {
107
116
  // Built-in conditions
108
117
  if (condition === 'file_exists') {
@@ -155,6 +164,9 @@ export class IdempotencyManager {
155
164
  };
156
165
  }
157
166
 
167
+ /**
168
+ *
169
+ */
158
170
  async _evaluateMultipleConditions(conditions, target, content, variables) {
159
171
  const logic = target.skipIfLogic || SKIP_IF_LOGIC.OR;
160
172
  const results = [];
@@ -181,6 +193,9 @@ export class IdempotencyManager {
181
193
  }
182
194
  }
183
195
 
196
+ /**
197
+ *
198
+ */
184
199
  async _evaluateObjectCondition(conditionObj, target, content, variables) {
185
200
  // Complex object-based conditions
186
201
  const { pattern, exists, custom, hash } = conditionObj;
@@ -218,12 +233,18 @@ export class IdempotencyManager {
218
233
  return { skip: false, reason: 'Invalid object condition' };
219
234
  }
220
235
 
236
+ /**
237
+ *
238
+ */
221
239
  _interpolateVariables(template, variables) {
222
240
  return template.replace(/\{\{(\w+)\}\}/g, (match, variable) => {
223
241
  return variables[variable] || match;
224
242
  });
225
243
  }
226
244
 
245
+ /**
246
+ *
247
+ */
227
248
  async _getFileContent(filePath) {
228
249
  const cacheKey = filePath;
229
250
 
@@ -244,6 +265,9 @@ export class IdempotencyManager {
244
265
  }
245
266
  }
246
267
 
268
+ /**
269
+ *
270
+ */
247
271
  async _fileExists(filePath) {
248
272
  try {
249
273
  await fs.access(filePath);
@@ -253,6 +277,9 @@ export class IdempotencyManager {
253
277
  }
254
278
  }
255
279
 
280
+ /**
281
+ *
282
+ */
256
283
  async _getFileSize(filePath) {
257
284
  try {
258
285
  const stats = await fs.stat(filePath);
@@ -265,6 +292,9 @@ export class IdempotencyManager {
265
292
  }
266
293
  }
267
294
 
295
+ /**
296
+ *
297
+ */
268
298
  async _getLineCount(filePath) {
269
299
  try {
270
300
  const content = await this._getFileContent(filePath);
@@ -274,6 +304,9 @@ export class IdempotencyManager {
274
304
  }
275
305
  }
276
306
 
307
+ /**
308
+ *
309
+ */
277
310
  async _getExistingContentHash(target) {
278
311
  try {
279
312
  const content = await this._getFileContent(target.resolvedPath);