@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.
Files changed (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +210 -0
  3. package/package.json +90 -0
  4. package/src/MIGRATION_COMPLETE.md +186 -0
  5. package/src/PORT-MAP.md +302 -0
  6. package/src/base/filter-templates.js +479 -0
  7. package/src/base/index.js +92 -0
  8. package/src/base/injection-targets.js +583 -0
  9. package/src/base/macro-templates.js +298 -0
  10. package/src/base/macro-templates.js.bak +461 -0
  11. package/src/base/shacl-templates.js +617 -0
  12. package/src/base/template-base.js +388 -0
  13. package/src/core/attestor.js +381 -0
  14. package/src/core/filters.js +518 -0
  15. package/src/core/index.js +21 -0
  16. package/src/core/kgen-engine.js +372 -0
  17. package/src/core/parser.js +447 -0
  18. package/src/core/post-processor.js +313 -0
  19. package/src/core/renderer.js +469 -0
  20. package/src/doc-generator/cli.mjs +122 -0
  21. package/src/doc-generator/index.mjs +28 -0
  22. package/src/doc-generator/mdx-generator.mjs +71 -0
  23. package/src/doc-generator/nav-generator.mjs +136 -0
  24. package/src/doc-generator/parser.mjs +291 -0
  25. package/src/doc-generator/rdf-builder.mjs +306 -0
  26. package/src/doc-generator/scanner.mjs +189 -0
  27. package/src/engine/index.js +42 -0
  28. package/src/engine/pipeline.js +448 -0
  29. package/src/engine/renderer.js +604 -0
  30. package/src/engine/template-engine.js +566 -0
  31. package/src/filters/array.js +436 -0
  32. package/src/filters/data.js +479 -0
  33. package/src/filters/index.js +270 -0
  34. package/src/filters/rdf.js +264 -0
  35. package/src/filters/text.js +369 -0
  36. package/src/index.js +109 -0
  37. package/src/inheritance/index.js +40 -0
  38. package/src/injection/api.js +260 -0
  39. package/src/injection/atomic-writer.js +327 -0
  40. package/src/injection/constants.js +136 -0
  41. package/src/injection/idempotency-manager.js +295 -0
  42. package/src/injection/index.js +28 -0
  43. package/src/injection/injection-engine.js +378 -0
  44. package/src/injection/integration.js +339 -0
  45. package/src/injection/modes/index.js +341 -0
  46. package/src/injection/rollback-manager.js +373 -0
  47. package/src/injection/target-resolver.js +323 -0
  48. package/src/injection/tests/atomic-writer.test.js +382 -0
  49. package/src/injection/tests/injection-engine.test.js +611 -0
  50. package/src/injection/tests/integration.test.js +392 -0
  51. package/src/injection/tests/run-tests.js +283 -0
  52. package/src/injection/validation-engine.js +547 -0
  53. package/src/linter/determinism-linter.js +473 -0
  54. package/src/linter/determinism.js +410 -0
  55. package/src/linter/index.js +6 -0
  56. package/src/linter/test-doubles.js +475 -0
  57. package/src/parser/frontmatter.js +228 -0
  58. package/src/parser/variables.js +344 -0
  59. package/src/renderer/deterministic.js +245 -0
  60. package/src/renderer/index.js +6 -0
  61. package/src/templates/latex/academic-paper.njk +186 -0
  62. package/src/templates/latex/index.js +104 -0
  63. package/src/templates/nextjs/app-page.njk +66 -0
  64. package/src/templates/nextjs/index.js +80 -0
  65. package/src/templates/office/docx/document.njk +368 -0
  66. package/src/templates/office/index.js +79 -0
  67. package/src/templates/office/word-report.njk +129 -0
  68. package/src/utils/template-utils.js +426 -0
@@ -0,0 +1,260 @@
1
+ /**
2
+ * KGEN Injection API
3
+ *
4
+ * Main API for injection operations. Provides a clean interface
5
+ * for the template engine to perform atomic, idempotent injections.
6
+ */
7
+
8
+ import { InjectionEngine } from './injection-engine.js';
9
+ import { DEFAULT_CONFIG } from './constants.js';
10
+
11
+ // Global injection engine instance
12
+ let globalInjectionEngine = null;
13
+
14
+ /**
15
+ * Initialize injection system with configuration
16
+ */
17
+ export function initializeInjection(config = {}) {
18
+ globalInjectionEngine = new InjectionEngine({ ...DEFAULT_CONFIG, ...config });
19
+ return globalInjectionEngine;
20
+ }
21
+
22
+ /**
23
+ * Main injection function - atomic, idempotent, deterministic
24
+ */
25
+ export async function inject(templateConfig, content, variables = {}, options = {}) {
26
+ const engine = getInjectionEngine(options.config);
27
+
28
+ try {
29
+ return await engine.inject(templateConfig, content, variables);
30
+ } catch (error) {
31
+ // Enhance error with context
32
+ error.templateConfig = templateConfig;
33
+ error.variables = variables;
34
+ throw error;
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Perform dry run to see what would be injected
40
+ */
41
+ export async function dryRun(templateConfig, content, variables = {}, options = {}) {
42
+ const engine = getInjectionEngine(options.config);
43
+ return await engine.dryRun(templateConfig, content, variables);
44
+ }
45
+
46
+ /**
47
+ * Undo a previous injection operation
48
+ */
49
+ export async function undo(operationId, options = {}) {
50
+ const engine = getInjectionEngine(options.config);
51
+ return await engine.undo(operationId);
52
+ }
53
+
54
+ /**
55
+ * Get injection operation history
56
+ */
57
+ export function getOperationHistory(options = {}) {
58
+ const engine = getInjectionEngine(options.config);
59
+ return engine.getOperationHistory();
60
+ }
61
+
62
+ /**
63
+ * Batch injection operations
64
+ */
65
+ export async function batchInject(operations, options = {}) {
66
+ const engine = getInjectionEngine(options.config);
67
+ const results = [];
68
+ const errors = [];
69
+
70
+ for (const operation of operations) {
71
+ try {
72
+ const result = await engine.inject(
73
+ operation.templateConfig,
74
+ operation.content,
75
+ operation.variables || {}
76
+ );
77
+ results.push({ ...result, operation });
78
+ } catch (error) {
79
+ errors.push({ error, operation });
80
+
81
+ // Stop on first error unless continueOnError is true
82
+ if (!options.continueOnError) {
83
+ break;
84
+ }
85
+ }
86
+ }
87
+
88
+ return {
89
+ results,
90
+ errors,
91
+ totalOperations: operations.length,
92
+ successfulOperations: results.length,
93
+ failedOperations: errors.length
94
+ };
95
+ }
96
+
97
+ /**
98
+ * Validate injection configuration without executing
99
+ */
100
+ export async function validateInjectionConfig(templateConfig, variables = {}, options = {}) {
101
+ const engine = getInjectionEngine(options.config);
102
+
103
+ try {
104
+ // This would use internal validation methods
105
+ const targets = await engine.targetResolver.resolveTargets(templateConfig, variables);
106
+ const validationResults = await Promise.all(
107
+ targets.map(target => engine.validationEngine.validateTarget(target))
108
+ );
109
+
110
+ return {
111
+ valid: validationResults.every(r => r.valid),
112
+ targets: targets.length,
113
+ validationResults,
114
+ errors: validationResults.flatMap(r => r.errors),
115
+ warnings: validationResults.flatMap(r => r.warnings)
116
+ };
117
+ } catch (error) {
118
+ return {
119
+ valid: false,
120
+ error: error.message,
121
+ targets: 0
122
+ };
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Get injection system status and metrics
128
+ */
129
+ export function getInjectionStatus(options = {}) {
130
+ const engine = getInjectionEngine(options.config);
131
+
132
+ return {
133
+ initialized: !!engine,
134
+ config: engine.config,
135
+ activeOperations: engine.activeOperations.size,
136
+ operationHistory: engine.operationHistory.length,
137
+ cacheStats: {
138
+ idempotency: engine.idempotencyManager.contentCache.size,
139
+ validation: engine.validationEngine.validationCache.size
140
+ }
141
+ };
142
+ }
143
+
144
+ /**
145
+ * Clear all caches (useful for testing or memory management)
146
+ */
147
+ export function clearCaches(options = {}) {
148
+ const engine = getInjectionEngine(options.config);
149
+
150
+ engine.idempotencyManager.clearCache();
151
+ engine.validationEngine.clearCache();
152
+
153
+ return {
154
+ cleared: true,
155
+ timestamp: Date.now()
156
+ };
157
+ }
158
+
159
+ /**
160
+ * Helper function to get or create injection engine
161
+ */
162
+ function getInjectionEngine(config) {
163
+ if (config) {
164
+ // Create temporary engine with custom config
165
+ return new InjectionEngine(config);
166
+ }
167
+
168
+ if (!globalInjectionEngine) {
169
+ // Create default engine
170
+ globalInjectionEngine = new InjectionEngine(DEFAULT_CONFIG);
171
+ }
172
+
173
+ return globalInjectionEngine;
174
+ }
175
+
176
+ /**
177
+ * Export engine class for advanced usage
178
+ */
179
+ export { InjectionEngine };
180
+
181
+ /**
182
+ * Template integration helper - processes template with injection support
183
+ */
184
+ export async function processTemplate(template, data, options = {}) {
185
+ const { frontmatter, content } = parseTemplate(template);
186
+
187
+ // Check if this template has injection configuration
188
+ if (frontmatter.inject) {
189
+ return await inject(frontmatter, content, data, options);
190
+ }
191
+
192
+ // Regular template processing would go here
193
+ throw new Error('Regular template processing not implemented - injection only');
194
+ }
195
+
196
+ /**
197
+ * Simple frontmatter parser for templates
198
+ */
199
+ function parseTemplate(template) {
200
+ const frontmatterMatch = template.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
201
+
202
+ if (!frontmatterMatch) {
203
+ return {
204
+ frontmatter: {},
205
+ content: template
206
+ };
207
+ }
208
+
209
+ try {
210
+ // Simple YAML-like parsing - in production use proper YAML parser
211
+ const frontmatterText = frontmatterMatch[1];
212
+ const frontmatter = parseFrontmatter(frontmatterText);
213
+ const content = frontmatterMatch[2];
214
+
215
+ return { frontmatter, content };
216
+ } catch (error) {
217
+ throw new Error(`Failed to parse template frontmatter: ${error.message}`);
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Simple frontmatter parser (YAML-like)
223
+ */
224
+ function parseFrontmatter(text) {
225
+ const result = {};
226
+ const lines = text.split('\n');
227
+
228
+ for (const line of lines) {
229
+ const trimmed = line.trim();
230
+ if (!trimmed || trimmed.startsWith('#')) continue;
231
+
232
+ const colonIndex = trimmed.indexOf(':');
233
+ if (colonIndex === -1) continue;
234
+
235
+ const key = trimmed.substring(0, colonIndex).trim();
236
+ const value = trimmed.substring(colonIndex + 1).trim();
237
+
238
+ // Simple value parsing
239
+ if (value === 'true') {
240
+ result[key] = true;
241
+ } else if (value === 'false') {
242
+ result[key] = false;
243
+ } else if (/^\d+$/.test(value)) {
244
+ result[key] = parseInt(value);
245
+ } else if (value.startsWith('"') && value.endsWith('"')) {
246
+ result[key] = value.slice(1, -1);
247
+ } else if (value.startsWith("'") && value.endsWith("'")) {
248
+ result[key] = value.slice(1, -1);
249
+ } else {
250
+ result[key] = value;
251
+ }
252
+ }
253
+
254
+ return result;
255
+ }
256
+
257
+ /**
258
+ * Export all injection modes for reference
259
+ */
260
+ export { INJECTION_MODES, ERROR_CODES } from './constants.js';
@@ -0,0 +1,327 @@
1
+ /**
2
+ * KGEN Atomic Writer
3
+ *
4
+ * Provides atomic file write operations with backup, rollback,
5
+ * and transactional capabilities for deterministic file modifications.
6
+ */
7
+
8
+ import { promises as fs, createReadStream } from 'fs';
9
+ import { join, dirname, basename, extname } from 'path';
10
+ import { createHash } from 'crypto';
11
+ import { pipeline } from 'stream/promises';
12
+
13
+ import { ERROR_CODES, CHECKSUM_ALGORITHMS, LOCK_CONFIG } from './constants.js';
14
+
15
+ export class AtomicWriter {
16
+ constructor(config = {}) {
17
+ this.config = config;
18
+ this.activeLocks = new Map();
19
+ this.activeTransactions = new Map();
20
+ }
21
+
22
+ /**
23
+ * Write file atomically using temporary file + rename
24
+ */
25
+ async writeAtomic(filePath, content, options = {}) {
26
+ const {
27
+ backup = this.config.backupEnabled,
28
+ operationId,
29
+ preserveMetadata = this.config.preservePermissions,
30
+ encoding = 'utf8'
31
+ } = options;
32
+
33
+ // Acquire file lock
34
+ const lockId = await this._acquireLock(filePath);
35
+
36
+ try {
37
+ let backupPath = null;
38
+ let originalStats = null;
39
+
40
+ // Create backup if enabled and file exists
41
+ if (backup) {
42
+ try {
43
+ originalStats = await fs.stat(filePath);
44
+ backupPath = await this._createBackup(filePath, operationId);
45
+ } catch (error) {
46
+ if (error.code !== 'ENOENT') throw error;
47
+ // File doesn't exist, no backup needed
48
+ }
49
+ }
50
+
51
+ // Create temporary file in same directory for atomic rename
52
+ const tempPath = await this._createTempFile(filePath);
53
+
54
+ try {
55
+ // Write content to temporary file
56
+ await fs.writeFile(tempPath, content, encoding);
57
+
58
+ // Preserve original file metadata
59
+ if (preserveMetadata && originalStats) {
60
+ await fs.chmod(tempPath, originalStats.mode);
61
+ await fs.utimes(tempPath, originalStats.atime, originalStats.mtime);
62
+ }
63
+
64
+ // Calculate checksum
65
+ const checksum = await this._calculateChecksum(tempPath);
66
+
67
+ // Atomic rename (this is the atomic operation)
68
+ await fs.rename(tempPath, filePath);
69
+
70
+ return {
71
+ success: true,
72
+ filePath,
73
+ backupPath,
74
+ checksum,
75
+ tempPath: null // Cleaned up by rename
76
+ };
77
+
78
+ } catch (error) {
79
+ // Clean up temp file on failure
80
+ try {
81
+ await fs.unlink(tempPath);
82
+ } catch (cleanupError) {
83
+ console.warn('Failed to cleanup temp file:', tempPath, cleanupError.message);
84
+ }
85
+
86
+ // Restore from backup if available
87
+ if (backupPath) {
88
+ try {
89
+ await fs.copyFile(backupPath, filePath);
90
+ } catch (restoreError) {
91
+ console.error('Failed to restore from backup:', restoreError);
92
+ }
93
+ }
94
+
95
+ throw error;
96
+ }
97
+
98
+ } finally {
99
+ await this._releaseLock(lockId);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Begin transaction for multi-file atomic operations
105
+ */
106
+ async beginTransaction(operationId) {
107
+ if (this.activeTransactions.has(operationId)) {
108
+ throw new Error(`Transaction ${operationId} already active`);
109
+ }
110
+
111
+ const transaction = new AtomicTransaction(operationId, this.config);
112
+ this.activeTransactions.set(operationId, transaction);
113
+
114
+ return transaction;
115
+ }
116
+
117
+ /**
118
+ * Private Methods
119
+ */
120
+
121
+ async _acquireLock(filePath) {
122
+ const lockId = `${filePath}-${Date.now()}-${Math.random()}`;
123
+ const startTime = Date.now();
124
+
125
+ while (Date.now() - startTime < LOCK_CONFIG.TIMEOUT) {
126
+ // Simple file-based locking
127
+ const lockFile = `${filePath}.kgen-lock`;
128
+
129
+ try {
130
+ await fs.writeFile(lockFile, lockId, { flag: 'wx' }); // Exclusive create
131
+ this.activeLocks.set(lockId, lockFile);
132
+ return lockId;
133
+ } catch (error) {
134
+ if (error.code === 'EEXIST') {
135
+ // Lock exists, check if stale
136
+ try {
137
+ const lockStat = await fs.stat(lockFile);
138
+ if (Date.now() - lockStat.mtime > LOCK_CONFIG.TIMEOUT) {
139
+ // Stale lock, remove it
140
+ await fs.unlink(lockFile);
141
+ }
142
+ } catch (statError) {
143
+ // Lock file might have been removed, continue
144
+ }
145
+
146
+ // Wait and retry
147
+ await new Promise(resolve => setTimeout(resolve, LOCK_CONFIG.RETRY_DELAY));
148
+ continue;
149
+ }
150
+ throw error;
151
+ }
152
+ }
153
+
154
+ throw new Error(`Failed to acquire lock for ${filePath} within timeout`);
155
+ }
156
+
157
+ async _releaseLock(lockId) {
158
+ const lockFile = this.activeLocks.get(lockId);
159
+ if (lockFile) {
160
+ try {
161
+ await fs.unlink(lockFile);
162
+ } catch (error) {
163
+ console.warn('Failed to release lock:', lockFile, error.message);
164
+ }
165
+ this.activeLocks.delete(lockId);
166
+ }
167
+ }
168
+
169
+ async _createBackup(filePath, operationId) {
170
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
171
+ const ext = extname(filePath);
172
+ const base = basename(filePath, ext);
173
+ const dir = dirname(filePath);
174
+
175
+ const backupName = operationId
176
+ ? `${base}${this.config.backupSuffix}-${operationId}${ext}`
177
+ : `${base}${this.config.backupSuffix}-${timestamp}${ext}`;
178
+
179
+ const backupPath = join(dir, backupName);
180
+
181
+ await fs.copyFile(filePath, backupPath);
182
+ return backupPath;
183
+ }
184
+
185
+ async _createTempFile(filePath) {
186
+ const dir = dirname(filePath);
187
+ const base = basename(filePath);
188
+ const tempName = `.kgen-temp-${base}-${Date.now()}-${Math.random().toString(36)}`;
189
+ return join(dir, tempName);
190
+ }
191
+
192
+ async _calculateChecksum(filePath, algorithm = CHECKSUM_ALGORITHMS.SHA256) {
193
+ const hash = createHash(algorithm);
194
+ const stream = createReadStream(filePath);
195
+
196
+ await pipeline(stream, hash);
197
+ return hash.digest('hex');
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Transaction class for multi-file atomic operations
203
+ */
204
+ class AtomicTransaction {
205
+ constructor(operationId, config) {
206
+ this.operationId = operationId;
207
+ this.config = config;
208
+ this.preparedWrites = [];
209
+ this.backups = [];
210
+ this.locks = [];
211
+ this.committed = false;
212
+ }
213
+
214
+ async prepareWrite(filePath, content, options = {}) {
215
+ if (this.committed) {
216
+ throw new Error('Transaction already committed');
217
+ }
218
+
219
+ // Acquire lock
220
+ const atomicWriter = new AtomicWriter(this.config);
221
+ const lockId = await atomicWriter._acquireLock(filePath);
222
+ this.locks.push({ lockId, filePath, writer: atomicWriter });
223
+
224
+ // Create backup
225
+ let backupPath = null;
226
+ try {
227
+ backupPath = await atomicWriter._createBackup(filePath, this.operationId);
228
+ this.backups.push({ filePath, backupPath });
229
+ } catch (error) {
230
+ if (error.code !== 'ENOENT') throw error;
231
+ }
232
+
233
+ // Create temp file with content
234
+ const tempPath = await atomicWriter._createTempFile(filePath);
235
+ await fs.writeFile(tempPath, content, options.encoding || 'utf8');
236
+
237
+ // Calculate checksum
238
+ const checksum = await atomicWriter._calculateChecksum(tempPath);
239
+
240
+ const preparedWrite = {
241
+ filePath,
242
+ tempPath,
243
+ backupPath,
244
+ checksum,
245
+ options
246
+ };
247
+
248
+ this.preparedWrites.push(preparedWrite);
249
+
250
+ return { checksum };
251
+ }
252
+
253
+ async commit() {
254
+ if (this.committed) {
255
+ throw new Error('Transaction already committed');
256
+ }
257
+
258
+ try {
259
+ // Validate all temp files exist and are ready
260
+ for (const write of this.preparedWrites) {
261
+ await fs.access(write.tempPath);
262
+ }
263
+
264
+ // Atomically rename all temp files to their targets
265
+ for (const write of this.preparedWrites) {
266
+ await fs.rename(write.tempPath, write.filePath);
267
+ }
268
+
269
+ this.committed = true;
270
+
271
+ // Clean up locks
272
+ await this._releaseLocks();
273
+
274
+ return {
275
+ success: true,
276
+ filesWritten: this.preparedWrites.length,
277
+ backups: this.backups.map(b => b.backupPath)
278
+ };
279
+
280
+ } catch (error) {
281
+ await this.rollback();
282
+ throw new Error(`Transaction commit failed: ${error.message}`);
283
+ }
284
+ }
285
+
286
+ async rollback() {
287
+ try {
288
+ // Clean up temp files
289
+ for (const write of this.preparedWrites) {
290
+ try {
291
+ await fs.unlink(write.tempPath);
292
+ } catch (error) {
293
+ console.warn('Failed to cleanup temp file:', write.tempPath);
294
+ }
295
+ }
296
+
297
+ // Restore from backups if any files were partially written
298
+ for (const backup of this.backups) {
299
+ try {
300
+ const targetExists = await fs.access(backup.filePath).then(() => true, () => false);
301
+ if (targetExists) {
302
+ await fs.copyFile(backup.backupPath, backup.filePath);
303
+ }
304
+ } catch (error) {
305
+ console.error('Failed to restore backup:', backup, error);
306
+ }
307
+ }
308
+
309
+ await this._releaseLocks();
310
+
311
+ } catch (error) {
312
+ console.error('Rollback failed:', error);
313
+ throw new Error(`Transaction rollback failed: ${error.message}`);
314
+ }
315
+ }
316
+
317
+ async _releaseLocks() {
318
+ for (const { lockId, writer } of this.locks) {
319
+ try {
320
+ await writer._releaseLock(lockId);
321
+ } catch (error) {
322
+ console.warn('Failed to release lock:', lockId, error);
323
+ }
324
+ }
325
+ this.locks = [];
326
+ }
327
+ }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Constants for KGEN Injection System
3
+ *
4
+ * Defines all constants, error codes, and configuration values
5
+ * used throughout the injection operations system.
6
+ */
7
+
8
+ export const INJECTION_MODES = {
9
+ APPEND: 'append',
10
+ PREPEND: 'prepend',
11
+ BEFORE: 'before',
12
+ AFTER: 'after',
13
+ REPLACE: 'replace',
14
+ LINE_AT: 'lineAt',
15
+ CREATE: 'create'
16
+ };
17
+
18
+ export const SKIP_IF_LOGIC = {
19
+ AND: 'AND',
20
+ OR: 'OR'
21
+ };
22
+
23
+ export const VALIDATION_RULES = {
24
+ SYNTAX: 'syntax',
25
+ SEMANTICS: 'semantics',
26
+ CONFLICTS: 'conflicts',
27
+ ENCODING: 'encoding',
28
+ SIZE: 'size',
29
+ PERMISSIONS: 'permissions'
30
+ };
31
+
32
+ export const ERROR_CODES = {
33
+ TARGET_NOT_FOUND: 'TARGET_NOT_FOUND',
34
+ BINARY_FILE: 'BINARY_FILE',
35
+ READ_ONLY: 'READ_ONLY',
36
+ FILE_LOCKED: 'FILE_LOCKED',
37
+ PATH_TRAVERSAL: 'PATH_TRAVERSAL',
38
+ SIZE_EXCEEDED: 'SIZE_EXCEEDED',
39
+ VALIDATION_FAILED: 'VALIDATION_FAILED',
40
+ ATOMIC_FAILURE: 'ATOMIC_FAILURE',
41
+ ROLLBACK_FAILURE: 'ROLLBACK_FAILURE',
42
+ INSUFFICIENT_SPACE: 'INSUFFICIENT_SPACE',
43
+ ENCODING_ERROR: 'ENCODING_ERROR',
44
+ CONFLICT_DETECTED: 'CONFLICT_DETECTED'
45
+ };
46
+
47
+ export const DEFAULT_CONFIG = {
48
+ // Atomic operations
49
+ atomicWrites: true,
50
+ backupEnabled: true,
51
+ transactionTimeout: 30000, // 30 seconds
52
+
53
+ // File validation
54
+ maxFileSize: 10 * 1024 * 1024, // 10MB
55
+ maxLineCount: 10000,
56
+ validateEncoding: true,
57
+ preservePermissions: true,
58
+
59
+ // Deterministic behavior
60
+ sortGlobResults: true,
61
+ consistentLineEndings: true,
62
+ preserveWhitespace: true,
63
+
64
+ // Security
65
+ preventPathTraversal: true,
66
+ allowedExtensions: ['.js', '.ts', '.jsx', '.tsx', '.json', '.md', '.txt', '.html', '.css', '.scss'],
67
+
68
+ // Performance
69
+ streamLargeFiles: true,
70
+ streamThreshold: 1024 * 1024, // 1MB
71
+ maxConcurrentOperations: 5,
72
+
73
+ // Backup and recovery
74
+ backupSuffix: '.kgen-backup',
75
+ maxBackups: 10,
76
+ autoCleanup: true
77
+ };
78
+
79
+ export const REGEX_FLAGS = {
80
+ GLOBAL: 'g',
81
+ MULTILINE: 'm',
82
+ CASE_INSENSITIVE: 'i',
83
+ DOTALL: 's',
84
+ UNICODE: 'u'
85
+ };
86
+
87
+ export const LINE_ENDINGS = {
88
+ LF: '\n', // Unix/Linux/macOS
89
+ CRLF: '\r\n', // Windows
90
+ CR: '\r' // Classic Mac
91
+ };
92
+
93
+ export const ENCODINGS = {
94
+ UTF8: 'utf8',
95
+ UTF16: 'utf16le',
96
+ ASCII: 'ascii',
97
+ LATIN1: 'latin1'
98
+ };
99
+
100
+ export const CHECKSUM_ALGORITHMS = {
101
+ SHA256: 'sha256',
102
+ MD5: 'md5',
103
+ SHA1: 'sha1'
104
+ };
105
+
106
+ // File type detection patterns
107
+ export const BINARY_PATTERNS = [
108
+ /^\x00/, // Null bytes at start
109
+ /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/, // Control characters
110
+ /\uFFFD/, // Replacement character (indicates binary)
111
+ ];
112
+
113
+ // Content validation patterns
114
+ export const CONTENT_PATTERNS = {
115
+ IMPORT_STATEMENT: /^import\s+.*from\s+['"][^'"]+['"];?\s*$/gm,
116
+ EXPORT_STATEMENT: /^export\s+.*$/gm,
117
+ FUNCTION_DECLARATION: /^(async\s+)?function\s+\w+\s*\(/gm,
118
+ CLASS_DECLARATION: /^class\s+\w+/gm,
119
+ INTERFACE_DECLARATION: /^interface\s+\w+/gm,
120
+ TYPE_DECLARATION: /^type\s+\w+/gm
121
+ };
122
+
123
+ // Operation metadata
124
+ export const OPERATION_METADATA = {
125
+ CREATED_BY: 'KGEN Injection System',
126
+ VERSION: '1.0.0',
127
+ TIMESTAMP_FORMAT: 'YYYY-MM-DD HH:mm:ss UTC',
128
+ HASH_ALGORITHM: 'sha256'
129
+ };
130
+
131
+ // Concurrency control
132
+ export const LOCK_CONFIG = {
133
+ TIMEOUT: 10000, // 10 seconds
134
+ RETRY_DELAY: 100, // 100ms
135
+ MAX_RETRIES: 100
136
+ };