@memberjunction/metadata-sync 2.112.0 → 2.113.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.
Files changed (42) hide show
  1. package/README.md +136 -61
  2. package/dist/constants/metadata-keywords.d.ts +282 -0
  3. package/dist/constants/metadata-keywords.js +364 -0
  4. package/dist/constants/metadata-keywords.js.map +1 -0
  5. package/dist/lib/EntityPropertyExtractor.d.ts +1 -1
  6. package/dist/lib/EntityPropertyExtractor.js +4 -18
  7. package/dist/lib/EntityPropertyExtractor.js.map +1 -1
  8. package/dist/lib/FieldExternalizer.d.ts +1 -1
  9. package/dist/lib/FieldExternalizer.js +6 -5
  10. package/dist/lib/FieldExternalizer.js.map +1 -1
  11. package/dist/lib/RecordProcessor.d.ts +1 -1
  12. package/dist/lib/RecordProcessor.js +14 -12
  13. package/dist/lib/RecordProcessor.js.map +1 -1
  14. package/dist/lib/RelatedEntityHandler.d.ts +1 -1
  15. package/dist/lib/RelatedEntityHandler.js +5 -5
  16. package/dist/lib/RelatedEntityHandler.js.map +1 -1
  17. package/dist/lib/json-preprocessor.js +7 -6
  18. package/dist/lib/json-preprocessor.js.map +1 -1
  19. package/dist/lib/provider-utils.d.ts +1 -1
  20. package/dist/lib/provider-utils.js +19 -16
  21. package/dist/lib/provider-utils.js.map +1 -1
  22. package/dist/lib/record-dependency-analyzer.js +44 -37
  23. package/dist/lib/record-dependency-analyzer.js.map +1 -1
  24. package/dist/lib/singleton-manager.d.ts +1 -1
  25. package/dist/lib/singleton-manager.js.map +1 -1
  26. package/dist/lib/sync-engine.d.ts +1 -1
  27. package/dist/lib/sync-engine.js +36 -44
  28. package/dist/lib/sync-engine.js.map +1 -1
  29. package/dist/services/PullService.d.ts +1 -1
  30. package/dist/services/PullService.js +18 -22
  31. package/dist/services/PullService.js.map +1 -1
  32. package/dist/services/PushService.d.ts +1 -1
  33. package/dist/services/PushService.js +21 -15
  34. package/dist/services/PushService.js.map +1 -1
  35. package/dist/services/ValidationService.js +32 -44
  36. package/dist/services/ValidationService.js.map +1 -1
  37. package/dist/services/WatchService.d.ts +1 -1
  38. package/dist/services/WatchService.js +14 -13
  39. package/dist/services/WatchService.js.map +1 -1
  40. package/dist/types/validation.d.ts +6 -1
  41. package/dist/types/validation.js.map +1 -1
  42. package/package.json +7 -6
@@ -1 +1 @@
1
- {"version":3,"file":"WatchService.js","sourceRoot":"","sources":["../../src/services/WatchService.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs-extra';\nimport path from 'path';\nimport chokidar from 'chokidar';\nimport { BaseEntity, Metadata } from '@memberjunction/global';\nimport { SyncEngine, RecordData } from '../lib/sync-engine';\nimport { loadEntityConfig, loadSyncConfig } from '../config';\nimport { findEntityDirectories } from '../lib/provider-utils';\nimport { configManager } from '../lib/config-manager';\nimport { JsonWriteHelper } from '../lib/json-write-helper';\nimport type { SqlLoggingSession } from '@memberjunction/sqlserver-dataprovider';\n\nexport interface WatchOptions {\n dir?: string;\n debounceMs?: number;\n ignorePatterns?: string[];\n}\n\nexport interface WatchCallbacks {\n onFileAdd?: (filePath: string, entityDir: string, entityConfig: any) => void;\n onFileChange?: (filePath: string, entityDir: string, entityConfig: any) => void;\n onFileDelete?: (filePath: string, entityDir: string, entityConfig: any) => void;\n onLog?: (message: string) => void;\n onWarn?: (message: string) => void;\n onError?: (error: Error) => void;\n onRecordCreated?: (entity: BaseEntity, entityConfig: any) => void;\n onRecordUpdated?: (entity: BaseEntity, changes: any, entityConfig: any) => void;\n onRecordSaved?: (entity: BaseEntity, isNew: boolean, entityConfig: any) => void;\n}\n\nexport interface WatchResult {\n watchers: chokidar.FSWatcher[];\n stop: () => Promise<void>;\n}\n\nexport class WatchService {\n private syncEngine: SyncEngine;\n private debounceTimers: Map<string, NodeJS.Timeout> = new Map();\n private sqlLoggingSession: SqlLoggingSession | null = null;\n\n constructor(syncEngine: SyncEngine) {\n this.syncEngine = syncEngine;\n }\n\n async watch(options: WatchOptions = {}, callbacks?: WatchCallbacks): Promise<WatchResult> {\n const entityDirs = findEntityDirectories(process.cwd(), options.dir);\n\n if (entityDirs.length === 0) {\n throw new Error('No entity directories found');\n }\n\n callbacks?.onLog?.(`Watching ${entityDirs.length} entity ${entityDirs.length === 1 ? 'directory' : 'directories'} for changes`);\n\n // Setup SQL logging session\n await this.setupSqlLogging(callbacks);\n\n // Set up watchers\n const watchers: chokidar.FSWatcher[] = [];\n\n for (const entityDir of entityDirs) {\n const entityConfig = await loadEntityConfig(entityDir);\n if (!entityConfig) {\n callbacks?.onWarn?.(`Skipping ${entityDir} - no valid entity configuration`);\n continue;\n }\n\n callbacks?.onLog?.(`Watching ${entityConfig.entity} in ${entityDir}`);\n\n // Watch for JSON files and external files\n const patterns = [\n path.join(entityDir, entityConfig.filePattern || '**/*.json'),\n path.join(entityDir, '**/*.md'),\n path.join(entityDir, '**/*.txt'),\n path.join(entityDir, '**/*.html'),\n path.join(entityDir, '**/*.liquid'),\n path.join(entityDir, '**/*.sql'),\n ];\n\n const ignored = [\n '**/node_modules/**',\n '**/.git/**',\n '**/.mj-sync.json',\n '**/.mj-folder.json',\n '**/*.backup',\n ...(options.ignorePatterns || []),\n ];\n\n const watcher = chokidar.watch(patterns, {\n ignored,\n persistent: true,\n ignoreInitial: true,\n });\n\n watcher\n .on('add', (filePath) => {\n callbacks?.onFileAdd?.(filePath, entityDir, entityConfig);\n this.handleFileChange(filePath, 'added', entityDir, entityConfig, options, callbacks);\n })\n .on('change', (filePath) => {\n callbacks?.onFileChange?.(filePath, entityDir, entityConfig);\n this.handleFileChange(filePath, 'changed', entityDir, entityConfig, options, callbacks);\n })\n .on('unlink', (filePath) => {\n callbacks?.onFileDelete?.(filePath, entityDir, entityConfig);\n this.handleFileChange(filePath, 'deleted', entityDir, entityConfig, options, callbacks);\n });\n\n watchers.push(watcher);\n }\n\n return {\n watchers,\n stop: async () => {\n // Clear all debounce timers\n for (const timer of this.debounceTimers.values()) {\n clearTimeout(timer);\n }\n this.debounceTimers.clear();\n\n // Close all watchers\n await Promise.all(watchers.map((w) => w.close()));\n\n // Dispose SQL logging session\n if (this.sqlLoggingSession) {\n try {\n callbacks?.onLog?.(`📝 SQL log written to: ${this.sqlLoggingSession.filePath}`);\n await this.sqlLoggingSession.dispose();\n this.sqlLoggingSession = null;\n } catch (error) {\n callbacks?.onWarn?.(`Failed to close SQL logging session: ${error}`);\n }\n }\n },\n };\n }\n\n private handleFileChange(\n filePath: string,\n event: string,\n entityDir: string,\n entityConfig: any,\n options: WatchOptions,\n callbacks?: WatchCallbacks\n ): void {\n // Clear existing debounce timer\n const existingTimer = this.debounceTimers.get(filePath);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Set new debounce timer\n const debounceMs = options.debounceMs || 1000;\n const timer = setTimeout(async () => {\n this.debounceTimers.delete(filePath);\n\n try {\n const relativePath = path.relative(entityDir, filePath);\n callbacks?.onLog?.(`File ${event}: ${relativePath}`);\n\n if (event === 'deleted') {\n // Handle deletion\n callbacks?.onLog?.('File deletion detected - manual database cleanup may be required');\n } else if (filePath.endsWith('.json')) {\n // Handle JSON file change\n await this.syncJsonFile(filePath, entityDir, entityConfig, callbacks);\n } else {\n // Handle external file change\n await this.syncExternalFile(filePath, entityDir, entityConfig, callbacks);\n }\n } catch (error) {\n const errorMessage = `Failed to sync ${filePath}: ${(error as any).message || error}`;\n callbacks?.onWarn?.(errorMessage);\n if (error instanceof Error) {\n callbacks?.onError?.(error);\n }\n }\n }, debounceMs);\n\n this.debounceTimers.set(filePath, timer);\n }\n\n private async syncJsonFile(filePath: string, entityDir: string, entityConfig: any, callbacks?: WatchCallbacks): Promise<void> {\n const recordData: RecordData = await fs.readJson(filePath);\n\n // Keep original fields for file writing\n const originalFields = { ...recordData.fields };\n\n // Build defaults\n const defaults = await this.syncEngine.buildDefaults(filePath, entityConfig);\n\n // Load or create entity\n let entity: BaseEntity | null = null;\n let isNew = false;\n\n if (recordData.primaryKey) {\n entity = await this.syncEngine.loadEntity(entityConfig.entity, recordData.primaryKey);\n }\n\n if (!entity) {\n // New record\n entity = await this.syncEngine.createEntityObject(entityConfig.entity);\n entity.NewRecord();\n isNew = true;\n\n // UUID generation now happens automatically in BaseEntity.NewRecord()\n }\n\n // Apply defaults first\n for (const [field, value] of Object.entries(defaults)) {\n if (field in entity) {\n (entity as any)[field] = value;\n }\n }\n\n // Apply record fields with processed values for database operations\n for (const [field, value] of Object.entries(recordData.fields)) {\n if (field in entity) {\n const processedValue = await this.syncEngine.processFieldValue(value, path.dirname(filePath));\n (entity as any)[field] = processedValue;\n }\n }\n\n // Check if the record is dirty before saving\n let wasActuallyUpdated = false;\n let changes: any = null;\n\n if (!isNew && entity.Dirty) {\n // Record is dirty, get the changes\n changes = entity.GetChangesSinceLastSave();\n const changeKeys = Object.keys(changes);\n if (changeKeys.length > 0) {\n wasActuallyUpdated = true;\n\n // Get primary key info for display\n const entityInfo = this.syncEngine.getEntityInfo(entityConfig.entity);\n const primaryKeyDisplay: string[] = [];\n if (entityInfo) {\n for (const pk of entityInfo.PrimaryKeys) {\n primaryKeyDisplay.push(`${pk.Name}: ${entity.Get(pk.Name)}`);\n }\n }\n\n callbacks?.onLog?.(`📝 Updating ${entityConfig.entity} record:`);\n if (primaryKeyDisplay.length > 0) {\n callbacks?.onLog?.(` Primary Key: ${primaryKeyDisplay.join(', ')}`);\n }\n callbacks?.onLog?.(` Changes:`);\n for (const fieldName of changeKeys) {\n const field = entity.GetFieldByName(fieldName);\n const oldValue = field ? field.OldValue : undefined;\n const newValue = (changes as any)[fieldName];\n callbacks?.onLog?.(` ${fieldName}: ${oldValue} → ${newValue}`);\n }\n\n callbacks?.onRecordUpdated?.(entity, changes, entityConfig);\n }\n } else if (isNew) {\n wasActuallyUpdated = true;\n callbacks?.onRecordCreated?.(entity, entityConfig);\n }\n\n // Save the record\n const saved = await entity.Save();\n if (!saved) {\n const message = entity.LatestResult?.Message;\n if (message) {\n throw new Error(`Failed to save record: ${message}`);\n }\n\n const errors =\n entity.LatestResult?.Errors?.map((err) => (typeof err === 'string' ? err : err?.message || JSON.stringify(err)))?.join(', ') ||\n 'Unknown error';\n throw new Error(`Failed to save record: ${errors}`);\n }\n\n if (wasActuallyUpdated) {\n callbacks?.onLog?.(`Successfully ${isNew ? 'created' : 'updated'} ${entityConfig.entity} record`);\n callbacks?.onRecordSaved?.(entity, isNew, entityConfig);\n } else {\n callbacks?.onLog?.(`No changes detected for ${entityConfig.entity} record - skipped update`);\n }\n\n // Update the local file with primary key and sync metadata\n if (wasActuallyUpdated) {\n const entityInfo = this.syncEngine.getEntityInfo(entityConfig.entity);\n if (entityInfo) {\n // Update primary key for new records\n if (isNew) {\n const newPrimaryKey: Record<string, any> = {};\n for (const pk of entityInfo.PrimaryKeys) {\n newPrimaryKey[pk.Name] = entity.Get(pk.Name);\n }\n recordData.primaryKey = newPrimaryKey;\n }\n\n // Always update sync metadata when the record was updated - use original fields for checksum\n recordData.sync = {\n lastModified: new Date().toISOString(),\n checksum: await this.syncEngine.calculateChecksumWithFileContent(originalFields, path.dirname(filePath)),\n };\n\n // Restore original field values to preserve @ references\n recordData.fields = originalFields;\n\n // Write back to file\n await JsonWriteHelper.writeOrderedRecordData(filePath, recordData);\n }\n }\n }\n\n private async syncExternalFile(filePath: string, entityDir: string, entityConfig: any, callbacks?: WatchCallbacks): Promise<void> {\n // Find the corresponding JSON file\n const fileName = path.basename(filePath);\n const parts = fileName.split('.');\n\n if (parts.length >= 3) {\n // Format: uuid.fieldname.ext\n const jsonFileName = `${parts[0]}.json`;\n const fieldName = parts[1];\n const jsonFilePath = path.join(path.dirname(filePath), jsonFileName);\n\n if (await fs.pathExists(jsonFilePath)) {\n // Update the JSON file's sync metadata to trigger a sync\n const recordData: RecordData = await fs.readJson(jsonFilePath);\n recordData.sync = {\n lastModified: new Date().toISOString(),\n checksum: recordData.sync?.checksum || '',\n };\n await JsonWriteHelper.writeOrderedRecordData(jsonFilePath, recordData);\n\n callbacks?.onLog?.(`Updated sync metadata for ${jsonFileName} due to external file change`);\n }\n }\n }\n\n private async setupSqlLogging(callbacks?: WatchCallbacks): Promise<void> {\n try {\n // Load sync config for SQL logging settings\n const syncConfig = await loadSyncConfig(configManager.getOriginalCwd());\n\n if (syncConfig?.sqlLogging?.enabled) {\n const provider = Metadata.Provider as any; // SQLServerDataProvider\n\n if (provider && typeof provider.CreateSqlLogger === 'function') {\n // Generate filename with timestamp\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = syncConfig.sqlLogging?.formatAsMigration ? `MetadataSync_Watch_${timestamp}.sql` : `watch_${timestamp}.sql`;\n\n // Use .sql-log-watch directory in the working directory\n const outputDir = path.join(configManager.getOriginalCwd(), '.sql-log-watch');\n const filepath = path.join(outputDir, filename);\n\n // Ensure the directory exists\n await fs.ensureDir(outputDir);\n\n // Create the SQL logging session\n this.sqlLoggingSession = await provider.CreateSqlLogger(filepath, {\n formatAsMigration: syncConfig.sqlLogging?.formatAsMigration || false,\n description: 'MetadataSync watch operation',\n logRecordChangeMetadata: true,\n });\n\n callbacks?.onLog?.(`📝 SQL logging enabled: ${filepath}`);\n }\n }\n } catch (error) {\n callbacks?.onWarn?.(`Failed to setup SQL logging: ${error}`);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"WatchService.js","sourceRoot":"","sources":["../../src/services/WatchService.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs-extra';\nimport path from 'path';\nimport chokidar from 'chokidar';\nimport { BaseEntity, Metadata } from '@memberjunction/core';\nimport { SyncEngine, RecordData } from '../lib/sync-engine';\nimport { loadEntityConfig, loadSyncConfig } from '../config';\nimport { findEntityDirectories } from '../lib/provider-utils';\nimport { configManager } from '../lib/config-manager';\nimport { JsonWriteHelper } from '../lib/json-write-helper';\nimport type { SqlLoggingSession } from '@memberjunction/sqlserver-dataprovider';\n\nexport interface WatchOptions {\n dir?: string;\n debounceMs?: number;\n ignorePatterns?: string[];\n}\n\nexport interface WatchCallbacks {\n onFileAdd?: (filePath: string, entityDir: string, entityConfig: any) => void;\n onFileChange?: (filePath: string, entityDir: string, entityConfig: any) => void;\n onFileDelete?: (filePath: string, entityDir: string, entityConfig: any) => void;\n onLog?: (message: string) => void;\n onWarn?: (message: string) => void;\n onError?: (error: Error) => void;\n onRecordCreated?: (entity: BaseEntity, entityConfig: any) => void;\n onRecordUpdated?: (entity: BaseEntity, changes: any, entityConfig: any) => void;\n onRecordSaved?: (entity: BaseEntity, isNew: boolean, entityConfig: any) => void;\n}\n\nexport interface WatchResult {\n watchers: chokidar.FSWatcher[];\n stop: () => Promise<void>;\n}\n\nexport class WatchService {\n private syncEngine: SyncEngine;\n private debounceTimers: Map<string, NodeJS.Timeout> = new Map();\n private sqlLoggingSession: SqlLoggingSession | null = null;\n \n constructor(syncEngine: SyncEngine) {\n this.syncEngine = syncEngine;\n }\n \n async watch(options: WatchOptions = {}, callbacks?: WatchCallbacks): Promise<WatchResult> {\n const entityDirs = findEntityDirectories(process.cwd(), options.dir);\n \n if (entityDirs.length === 0) {\n throw new Error('No entity directories found');\n }\n \n callbacks?.onLog?.(`Watching ${entityDirs.length} entity ${entityDirs.length === 1 ? 'directory' : 'directories'} for changes`);\n \n // Setup SQL logging session\n await this.setupSqlLogging(callbacks);\n \n // Set up watchers\n const watchers: chokidar.FSWatcher[] = [];\n \n for (const entityDir of entityDirs) {\n const entityConfig = await loadEntityConfig(entityDir);\n if (!entityConfig) {\n callbacks?.onWarn?.(`Skipping ${entityDir} - no valid entity configuration`);\n continue;\n }\n \n callbacks?.onLog?.(`Watching ${entityConfig.entity} in ${entityDir}`);\n \n // Watch for JSON files and external files\n const patterns = [\n path.join(entityDir, entityConfig.filePattern || '**/*.json'),\n path.join(entityDir, '**/*.md'),\n path.join(entityDir, '**/*.txt'),\n path.join(entityDir, '**/*.html'),\n path.join(entityDir, '**/*.liquid'),\n path.join(entityDir, '**/*.sql')\n ];\n \n const ignored = [\n '**/node_modules/**',\n '**/.git/**',\n '**/.mj-sync.json',\n '**/.mj-folder.json',\n '**/*.backup',\n ...(options.ignorePatterns || [])\n ];\n \n const watcher = chokidar.watch(patterns, {\n ignored,\n persistent: true,\n ignoreInitial: true\n });\n \n watcher\n .on('add', (filePath) => {\n callbacks?.onFileAdd?.(filePath, entityDir, entityConfig);\n this.handleFileChange(filePath, 'added', entityDir, entityConfig, options, callbacks);\n })\n .on('change', (filePath) => {\n callbacks?.onFileChange?.(filePath, entityDir, entityConfig);\n this.handleFileChange(filePath, 'changed', entityDir, entityConfig, options, callbacks);\n })\n .on('unlink', (filePath) => {\n callbacks?.onFileDelete?.(filePath, entityDir, entityConfig);\n this.handleFileChange(filePath, 'deleted', entityDir, entityConfig, options, callbacks);\n });\n \n watchers.push(watcher);\n }\n \n return {\n watchers,\n stop: async () => {\n // Clear all debounce timers\n for (const timer of this.debounceTimers.values()) {\n clearTimeout(timer);\n }\n this.debounceTimers.clear();\n \n // Close all watchers\n await Promise.all(watchers.map(w => w.close()));\n \n // Dispose SQL logging session\n if (this.sqlLoggingSession) {\n try {\n callbacks?.onLog?.(`📝 SQL log written to: ${this.sqlLoggingSession.filePath}`);\n await this.sqlLoggingSession.dispose();\n this.sqlLoggingSession = null;\n } catch (error) {\n callbacks?.onWarn?.(`Failed to close SQL logging session: ${error}`);\n }\n }\n }\n };\n }\n \n private handleFileChange(\n filePath: string,\n event: string,\n entityDir: string,\n entityConfig: any,\n options: WatchOptions,\n callbacks?: WatchCallbacks\n ): void {\n // Clear existing debounce timer\n const existingTimer = this.debounceTimers.get(filePath);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n \n // Set new debounce timer\n const debounceMs = options.debounceMs || 1000;\n const timer = setTimeout(async () => {\n this.debounceTimers.delete(filePath);\n \n try {\n const relativePath = path.relative(entityDir, filePath);\n callbacks?.onLog?.(`File ${event}: ${relativePath}`);\n \n if (event === 'deleted') {\n // Handle deletion\n callbacks?.onLog?.('File deletion detected - manual database cleanup may be required');\n } else if (filePath.endsWith('.json')) {\n // Handle JSON file change\n await this.syncJsonFile(filePath, entityDir, entityConfig, callbacks);\n } else {\n // Handle external file change\n await this.syncExternalFile(filePath, entityDir, entityConfig, callbacks);\n }\n } catch (error) {\n const errorMessage = `Failed to sync ${filePath}: ${(error as any).message || error}`;\n callbacks?.onWarn?.(errorMessage);\n if (error instanceof Error) {\n callbacks?.onError?.(error);\n }\n }\n }, debounceMs);\n \n this.debounceTimers.set(filePath, timer);\n }\n \n private async syncJsonFile(\n filePath: string,\n entityDir: string,\n entityConfig: any,\n callbacks?: WatchCallbacks\n ): Promise<void> {\n const recordData: RecordData = await fs.readJson(filePath);\n \n // Keep original fields for file writing\n const originalFields = { ...recordData.fields };\n \n // Build defaults\n const defaults = await this.syncEngine.buildDefaults(filePath, entityConfig);\n \n // Load or create entity\n let entity: BaseEntity | null = null;\n let isNew = false;\n \n if (recordData.primaryKey) {\n entity = await this.syncEngine.loadEntity(entityConfig.entity, recordData.primaryKey);\n }\n \n if (!entity) {\n // New record\n entity = await this.syncEngine.createEntityObject(entityConfig.entity);\n entity.NewRecord();\n isNew = true;\n \n // UUID generation now happens automatically in BaseEntity.NewRecord()\n }\n \n // Apply defaults first\n for (const [field, value] of Object.entries(defaults)) {\n if (field in entity) {\n (entity as any)[field] = value;\n }\n }\n \n // Apply record fields with processed values for database operations\n for (const [field, value] of Object.entries(recordData.fields)) {\n if (field in entity) {\n const processedValue = await this.syncEngine.processFieldValue(value, path.dirname(filePath));\n (entity as any)[field] = processedValue;\n }\n }\n \n // Check if the record is dirty before saving\n let wasActuallyUpdated = false;\n let changes: any = null;\n \n if (!isNew && entity.Dirty) {\n // Record is dirty, get the changes\n changes = entity.GetChangesSinceLastSave();\n const changeKeys = Object.keys(changes);\n if (changeKeys.length > 0) {\n wasActuallyUpdated = true;\n \n // Get primary key info for display\n const entityInfo = this.syncEngine.getEntityInfo(entityConfig.entity);\n const primaryKeyDisplay: string[] = [];\n if (entityInfo) {\n for (const pk of entityInfo.PrimaryKeys) {\n primaryKeyDisplay.push(`${pk.Name}: ${entity.Get(pk.Name)}`);\n }\n }\n \n callbacks?.onLog?.(`📝 Updating ${entityConfig.entity} record:`);\n if (primaryKeyDisplay.length > 0) {\n callbacks?.onLog?.(` Primary Key: ${primaryKeyDisplay.join(', ')}`);\n }\n callbacks?.onLog?.(` Changes:`);\n for (const fieldName of changeKeys) {\n const field = entity.GetFieldByName(fieldName);\n const oldValue = field ? field.OldValue : undefined;\n const newValue = (changes as any)[fieldName];\n callbacks?.onLog?.(` ${fieldName}: ${oldValue} → ${newValue}`);\n }\n \n callbacks?.onRecordUpdated?.(entity, changes, entityConfig);\n }\n } else if (isNew) {\n wasActuallyUpdated = true;\n callbacks?.onRecordCreated?.(entity, entityConfig);\n }\n \n // Save the record\n const saved = await entity.Save();\n if (!saved) {\n const message = entity.LatestResult?.Message;\n if (message) {\n throw new Error(`Failed to save record: ${message}`);\n }\n \n const errors = entity.LatestResult?.Errors?.map(err => \n typeof err === 'string' ? err : (err?.message || JSON.stringify(err))\n )?.join(', ') || 'Unknown error';\n throw new Error(`Failed to save record: ${errors}`);\n }\n \n if (wasActuallyUpdated) {\n callbacks?.onLog?.(`Successfully ${isNew ? 'created' : 'updated'} ${entityConfig.entity} record`);\n callbacks?.onRecordSaved?.(entity, isNew, entityConfig);\n } else {\n callbacks?.onLog?.(`No changes detected for ${entityConfig.entity} record - skipped update`);\n }\n \n // Update the local file with primary key and sync metadata\n if (wasActuallyUpdated) {\n const entityInfo = this.syncEngine.getEntityInfo(entityConfig.entity);\n if (entityInfo) {\n // Update primary key for new records\n if (isNew) {\n const newPrimaryKey: Record<string, any> = {};\n for (const pk of entityInfo.PrimaryKeys) {\n newPrimaryKey[pk.Name] = entity.Get(pk.Name);\n }\n recordData.primaryKey = newPrimaryKey;\n }\n \n // Always update sync metadata when the record was updated - use original fields for checksum\n recordData.sync = {\n lastModified: new Date().toISOString(),\n checksum: await this.syncEngine.calculateChecksumWithFileContent(originalFields, path.dirname(filePath))\n };\n \n // Restore original field values to preserve @ references\n recordData.fields = originalFields;\n \n // Write back to file\n await JsonWriteHelper.writeOrderedRecordData(filePath, recordData);\n }\n }\n }\n \n private async syncExternalFile(\n filePath: string,\n entityDir: string,\n entityConfig: any,\n callbacks?: WatchCallbacks\n ): Promise<void> {\n // Find the corresponding JSON file\n const fileName = path.basename(filePath);\n const parts = fileName.split('.');\n \n if (parts.length >= 3) {\n // Format: uuid.fieldname.ext\n const jsonFileName = `${parts[0]}.json`;\n const fieldName = parts[1];\n const jsonFilePath = path.join(path.dirname(filePath), jsonFileName);\n \n if (await fs.pathExists(jsonFilePath)) {\n // Update the JSON file's sync metadata to trigger a sync\n const recordData: RecordData = await fs.readJson(jsonFilePath);\n recordData.sync = {\n lastModified: new Date().toISOString(),\n checksum: recordData.sync?.checksum || ''\n };\n await JsonWriteHelper.writeOrderedRecordData(jsonFilePath, recordData);\n \n callbacks?.onLog?.(`Updated sync metadata for ${jsonFileName} due to external file change`);\n }\n }\n }\n \n private async setupSqlLogging(callbacks?: WatchCallbacks): Promise<void> {\n try {\n // Load sync config for SQL logging settings\n const syncConfig = await loadSyncConfig(configManager.getOriginalCwd());\n \n if (syncConfig?.sqlLogging?.enabled) {\n const provider = Metadata.Provider as any; // SQLServerDataProvider\n \n if (provider && typeof provider.CreateSqlLogger === 'function') {\n // Generate filename with timestamp\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = syncConfig.sqlLogging?.formatAsMigration \n ? `MetadataSync_Watch_${timestamp}.sql`\n : `watch_${timestamp}.sql`;\n \n // Use .sql-log-watch directory in the working directory\n const outputDir = path.join(configManager.getOriginalCwd(), '.sql-log-watch');\n const filepath = path.join(outputDir, filename);\n \n // Ensure the directory exists\n await fs.ensureDir(outputDir);\n \n // Create the SQL logging session\n this.sqlLoggingSession = await provider.CreateSqlLogger(filepath, {\n formatAsMigration: syncConfig.sqlLogging?.formatAsMigration || false,\n description: 'MetadataSync watch operation',\n logRecordChangeMetadata: true\n });\n \n callbacks?.onLog?.(`📝 SQL logging enabled: ${filepath}`);\n }\n }\n } catch (error) {\n callbacks?.onWarn?.(`Failed to setup SQL logging: ${error}`);\n }\n }\n}"]}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Validation types and interfaces for MetadataSync
3
3
  */
4
+ import type { MetadataKeyword } from '../constants/metadata-keywords';
4
5
  export interface ValidationResult {
5
6
  isValid: boolean;
6
7
  errors: ValidationError[];
@@ -87,7 +88,11 @@ export interface ValidationOptions {
87
88
  maxNestingDepth: number;
88
89
  checkBestPractices: boolean;
89
90
  }
90
- export type ReferenceType = '@file:' | '@lookup:' | '@template:' | '@parent:' | '@root:' | '@env:';
91
+ /**
92
+ * Reference type representing metadata keywords.
93
+ * This type is now sourced from the centralized metadata-keywords constants.
94
+ */
95
+ export type ReferenceType = MetadataKeyword;
91
96
  export interface ParsedReference {
92
97
  type: ReferenceType;
93
98
  value: string;
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/types/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validation types and interfaces for MetadataSync\n */\n\nexport interface ValidationResult {\n isValid: boolean;\n errors: ValidationError[];\n warnings: ValidationWarning[];\n summary: ValidationSummary;\n}\n\nexport interface ValidationError {\n type: 'entity' | 'field' | 'value' | 'reference' | 'dependency' | 'circular' | 'validation';\n severity: 'error';\n entity?: string;\n field?: string;\n file: string;\n message: string;\n suggestion?: string;\n details?: any;\n}\n\nexport interface ValidationWarning {\n type: 'nesting' | 'naming' | 'bestpractice' | 'performance' | 'validation';\n severity: 'warning';\n entity?: string;\n field?: string;\n file: string;\n message: string;\n suggestion?: string;\n details?: any;\n}\n\nexport interface ValidationSummary {\n totalFiles: number;\n totalEntities: number;\n totalErrors: number;\n totalWarnings: number;\n fileResults: Map<string, FileValidationResult>;\n}\n\n/**\n * Custom error class for validation errors\n */\nexport class ValidationErrorClass extends Error {\n public readonly type: ValidationError['type'];\n public readonly severity: ValidationError['severity'];\n public readonly file: string;\n public readonly entity?: string;\n public readonly field?: string;\n public readonly suggestion?: string;\n public readonly line?: number;\n public readonly column?: number;\n \n constructor(error: ValidationError) {\n super(error.message);\n this.name = 'ValidationError';\n this.type = error.type;\n this.severity = error.severity;\n this.file = error.file;\n this.entity = error.entity;\n this.field = error.field;\n this.suggestion = error.suggestion;\n \n // Try to extract line/column from error message if present\n const lineMatch = error.message.match(/line (\\d+)/i);\n const colMatch = error.message.match(/column (\\d+)/i);\n this.line = lineMatch ? parseInt(lineMatch[1]) : undefined;\n this.column = colMatch ? parseInt(colMatch[1]) : undefined;\n \n // Ensure proper prototype chain\n Object.setPrototypeOf(this, ValidationErrorClass.prototype);\n }\n \n /**\n * Get formatted error message with location info\n */\n getFormattedMessage(): string {\n let msg = this.message;\n if (this.line) {\n msg += ` (line ${this.line}`;\n if (this.column) {\n msg += `, column ${this.column}`;\n }\n msg += ')';\n }\n return msg;\n }\n}\n\n/**\n * Custom warning class for validation warnings\n */\nexport class ValidationWarningClass extends Error {\n public readonly type: ValidationWarning['type'];\n public readonly severity: ValidationWarning['severity'];\n public readonly file: string;\n public readonly entity?: string;\n public readonly field?: string;\n public readonly suggestion?: string;\n public readonly line?: number;\n public readonly column?: number;\n \n constructor(warning: ValidationWarning) {\n super(warning.message);\n this.name = 'ValidationWarning';\n this.type = warning.type;\n this.severity = warning.severity;\n this.file = warning.file;\n this.entity = warning.entity;\n this.field = warning.field;\n this.suggestion = warning.suggestion;\n \n // Try to extract line/column from warning message if present\n const lineMatch = warning.message.match(/line (\\d+)/i);\n const colMatch = warning.message.match(/column (\\d+)/i);\n this.line = lineMatch ? parseInt(lineMatch[1]) : undefined;\n this.column = colMatch ? parseInt(colMatch[1]) : undefined;\n \n // Ensure proper prototype chain\n Object.setPrototypeOf(this, ValidationWarningClass.prototype);\n }\n \n /**\n * Get formatted warning message with location info\n */\n getFormattedMessage(): string {\n let msg = this.message;\n if (this.line) {\n msg += ` (line ${this.line}`;\n if (this.column) {\n msg += `, column ${this.column}`;\n }\n msg += ')';\n }\n return msg;\n }\n}\n\nexport interface FileValidationResult {\n file: string;\n entityCount: number;\n errors: ValidationError[];\n warnings: ValidationWarning[];\n}\n\nexport interface EntityDependency {\n entityName: string;\n dependsOn: Set<string>;\n file: string;\n}\n\nexport interface ValidationOptions {\n verbose: boolean;\n outputFormat: 'human' | 'json';\n maxNestingDepth: number;\n checkBestPractices: boolean;\n}\n\nexport type ReferenceType = '@file:' | '@lookup:' | '@template:' | '@parent:' | '@root:' | '@env:';\n\nexport interface ParsedReference {\n type: ReferenceType;\n value: string;\n entity?: string;\n field?: string;\n fields?: Array<{field: string, value: string}>; // For multi-field lookups\n createIfMissing?: boolean;\n additionalFields?: Record<string, any>;\n}"]}
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/types/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validation types and interfaces for MetadataSync\n */\n\nimport type { MetadataKeyword } from '../constants/metadata-keywords';\n\nexport interface ValidationResult {\n isValid: boolean;\n errors: ValidationError[];\n warnings: ValidationWarning[];\n summary: ValidationSummary;\n}\n\nexport interface ValidationError {\n type: 'entity' | 'field' | 'value' | 'reference' | 'dependency' | 'circular' | 'validation';\n severity: 'error';\n entity?: string;\n field?: string;\n file: string;\n message: string;\n suggestion?: string;\n details?: any;\n}\n\nexport interface ValidationWarning {\n type: 'nesting' | 'naming' | 'bestpractice' | 'performance' | 'validation';\n severity: 'warning';\n entity?: string;\n field?: string;\n file: string;\n message: string;\n suggestion?: string;\n details?: any;\n}\n\nexport interface ValidationSummary {\n totalFiles: number;\n totalEntities: number;\n totalErrors: number;\n totalWarnings: number;\n fileResults: Map<string, FileValidationResult>;\n}\n\n/**\n * Custom error class for validation errors\n */\nexport class ValidationErrorClass extends Error {\n public readonly type: ValidationError['type'];\n public readonly severity: ValidationError['severity'];\n public readonly file: string;\n public readonly entity?: string;\n public readonly field?: string;\n public readonly suggestion?: string;\n public readonly line?: number;\n public readonly column?: number;\n \n constructor(error: ValidationError) {\n super(error.message);\n this.name = 'ValidationError';\n this.type = error.type;\n this.severity = error.severity;\n this.file = error.file;\n this.entity = error.entity;\n this.field = error.field;\n this.suggestion = error.suggestion;\n \n // Try to extract line/column from error message if present\n const lineMatch = error.message.match(/line (\\d+)/i);\n const colMatch = error.message.match(/column (\\d+)/i);\n this.line = lineMatch ? parseInt(lineMatch[1]) : undefined;\n this.column = colMatch ? parseInt(colMatch[1]) : undefined;\n \n // Ensure proper prototype chain\n Object.setPrototypeOf(this, ValidationErrorClass.prototype);\n }\n \n /**\n * Get formatted error message with location info\n */\n getFormattedMessage(): string {\n let msg = this.message;\n if (this.line) {\n msg += ` (line ${this.line}`;\n if (this.column) {\n msg += `, column ${this.column}`;\n }\n msg += ')';\n }\n return msg;\n }\n}\n\n/**\n * Custom warning class for validation warnings\n */\nexport class ValidationWarningClass extends Error {\n public readonly type: ValidationWarning['type'];\n public readonly severity: ValidationWarning['severity'];\n public readonly file: string;\n public readonly entity?: string;\n public readonly field?: string;\n public readonly suggestion?: string;\n public readonly line?: number;\n public readonly column?: number;\n \n constructor(warning: ValidationWarning) {\n super(warning.message);\n this.name = 'ValidationWarning';\n this.type = warning.type;\n this.severity = warning.severity;\n this.file = warning.file;\n this.entity = warning.entity;\n this.field = warning.field;\n this.suggestion = warning.suggestion;\n \n // Try to extract line/column from warning message if present\n const lineMatch = warning.message.match(/line (\\d+)/i);\n const colMatch = warning.message.match(/column (\\d+)/i);\n this.line = lineMatch ? parseInt(lineMatch[1]) : undefined;\n this.column = colMatch ? parseInt(colMatch[1]) : undefined;\n \n // Ensure proper prototype chain\n Object.setPrototypeOf(this, ValidationWarningClass.prototype);\n }\n \n /**\n * Get formatted warning message with location info\n */\n getFormattedMessage(): string {\n let msg = this.message;\n if (this.line) {\n msg += ` (line ${this.line}`;\n if (this.column) {\n msg += `, column ${this.column}`;\n }\n msg += ')';\n }\n return msg;\n }\n}\n\nexport interface FileValidationResult {\n file: string;\n entityCount: number;\n errors: ValidationError[];\n warnings: ValidationWarning[];\n}\n\nexport interface EntityDependency {\n entityName: string;\n dependsOn: Set<string>;\n file: string;\n}\n\nexport interface ValidationOptions {\n verbose: boolean;\n outputFormat: 'human' | 'json';\n maxNestingDepth: number;\n checkBestPractices: boolean;\n}\n\n/**\n * Reference type representing metadata keywords.\n * This type is now sourced from the centralized metadata-keywords constants.\n */\nexport type ReferenceType = MetadataKeyword;\n\nexport interface ParsedReference {\n type: ReferenceType;\n value: string;\n entity?: string;\n field?: string;\n fields?: Array<{field: string, value: string}>; // For multi-field lookups\n createIfMissing?: boolean;\n additionalFields?: Record<string, any>;\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/metadata-sync",
3
- "version": "2.112.0",
3
+ "version": "2.113.0",
4
4
  "description": "MemberJunction metadata synchronization CLI tool",
5
5
  "keywords": [
6
6
  "metadata",
@@ -26,11 +26,12 @@
26
26
  "build": "tsc -b"
27
27
  },
28
28
  "dependencies": {
29
- "@memberjunction/core-entities": "2.112.0",
30
- "@memberjunction/core-entities-server": "2.112.0",
31
- "@memberjunction/global": "2.112.0",
32
- "@memberjunction/sqlserver-dataprovider": "2.112.0",
33
- "@memberjunction/graphql-dataprovider": "2.112.0",
29
+ "@memberjunction/core": "2.113.0",
30
+ "@memberjunction/core-entities": "2.113.0",
31
+ "@memberjunction/core-entities-server": "2.113.0",
32
+ "@memberjunction/global": "2.113.0",
33
+ "@memberjunction/sqlserver-dataprovider": "2.113.0",
34
+ "@memberjunction/graphql-dataprovider": "2.113.0",
34
35
  "chokidar": "^3.6.0",
35
36
  "cosmiconfig": "9.0.0",
36
37
  "dotenv": "16.4.5",