@memberjunction/metadata-sync 2.91.0 ā 2.92.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.
package/dist/lib/sync-engine.js
CHANGED
|
@@ -91,11 +91,13 @@ class SyncEngine {
|
|
|
91
91
|
if (depth > MAX_RECURSION_DEPTH) {
|
|
92
92
|
throw new Error(`Maximum recursion depth (${MAX_RECURSION_DEPTH}) exceeded while processing field value: ${value}`);
|
|
93
93
|
}
|
|
94
|
-
// Handle arrays and objects
|
|
94
|
+
// Handle arrays and objects that are directly defined in metadata files
|
|
95
|
+
// Note: Objects loaded from @file references are returned as-is to preserve proper escaping
|
|
95
96
|
if (value !== null && typeof value === 'object') {
|
|
96
97
|
// Check if it's an array or a plain object (not a Date, etc.)
|
|
97
98
|
if (Array.isArray(value) || value.constructor === Object) {
|
|
98
|
-
// Convert to pretty-printed JSON string
|
|
99
|
+
// Convert to pretty-printed JSON string for inline metadata objects
|
|
100
|
+
// Objects from @file references will be handled by BaseEntity during save
|
|
99
101
|
return JSON.stringify(value, null, 2);
|
|
100
102
|
}
|
|
101
103
|
}
|
|
@@ -153,8 +155,10 @@ class SyncEngine {
|
|
|
153
155
|
// Now recursively process any @file references within the JSON
|
|
154
156
|
const fileDir = path_1.default.dirname(fullPath);
|
|
155
157
|
processedJson = await this.processJsonFieldValues(processedJson, fileDir, parentRecord, rootRecord, depth + 1, batchContext);
|
|
156
|
-
// Return
|
|
157
|
-
|
|
158
|
+
// Return the processed JSON object directly without stringifying
|
|
159
|
+
// Let BaseEntity handle serialization when saving to database
|
|
160
|
+
// This ensures proper escaping of embedded code/scripts
|
|
161
|
+
return processedJson;
|
|
158
162
|
}
|
|
159
163
|
catch (jsonError) {
|
|
160
164
|
// Not valid JSON or error processing, fall back to text file handling
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-engine.js","sourceRoot":"","sources":["../../src/lib/sync-engine.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Core synchronization engine for MemberJunction metadata\n * @module sync-engine\n * \n * This module provides the core functionality for synchronizing metadata between\n * the MemberJunction database and local file system representations. It handles\n * special reference types (@file, @url, @lookup, @env, @parent, @root, @template),\n * manages entity operations, and provides utilities for data transformation.\n */\n\nimport path from 'path';\nimport fs from 'fs-extra';\nimport crypto from 'crypto';\nimport axios from 'axios';\nimport { EntityInfo, Metadata, RunView, BaseEntity, CompositeKey, UserInfo } from '@memberjunction/core';\nimport { EntityConfig, FolderConfig } from '../config';\nimport { JsonPreprocessor } from './json-preprocessor';\n\n/**\n * Represents the structure of a metadata record with optional sync tracking\n */\nexport interface RecordData {\n /** Primary key field(s) and their values */\n primaryKey?: Record<string, any>;\n /** Entity field names and their values */\n fields: Record<string, any>;\n /** Related entities organized by entity name */\n relatedEntities?: Record<string, RecordData[]>;\n /** Synchronization metadata for change tracking */\n sync?: {\n /** ISO timestamp of last modification */\n lastModified: string;\n /** SHA256 checksum of the fields object */\n checksum: string;\n };\n}\n\n/**\n * Core engine for synchronizing MemberJunction metadata between database and files\n * \n * @class SyncEngine\n * @example\n * ```typescript\n * const syncEngine = new SyncEngine(systemUser);\n * \n * // Process a field value with special references\n * const value = await syncEngine.processFieldValue('@lookup:Users.Email=admin@example.com', '/path/to/base');\n * ```\n */\nexport class SyncEngine {\n private metadata: Metadata;\n private contextUser: UserInfo;\n\n /**\n * Creates a new SyncEngine instance\n * @param contextUser - The user context for database operations\n */\n constructor(contextUser: UserInfo) {\n this.metadata = new Metadata();\n this.contextUser = contextUser;\n }\n \n /**\n * Initializes the sync engine by refreshing metadata cache\n * @returns Promise that resolves when initialization is complete\n */\n async initialize(): Promise<void> {\n // Currently no initialization needed as metadata is managed globally\n // Keeping this method for backward compatibility and future use\n }\n \n /**\n * Process special references in field values and handle complex objects\n * \n * Automatically handles:\n * - Arrays and objects are converted to JSON strings\n * - Scalars (strings, numbers, booleans, null) pass through unchanged\n * \n * Handles the following reference types for string values:\n * - `@parent:fieldName` - References a field from the parent record\n * - `@root:fieldName` - References a field from the root record\n * - `@file:path` - Reads content from an external file\n * - `@url:address` - Fetches content from a URL\n * - `@lookup:Entity.Field=Value` - Looks up an entity ID by field value\n * - `@env:VARIABLE` - Reads an environment variable\n * \n * @param value - The field value to process\n * @param baseDir - Base directory for resolving relative file paths\n * @param parentRecord - Optional parent entity for @parent references\n * @param rootRecord - Optional root entity for @root references\n * @returns The processed value with all references resolved\n * @throws Error if a reference cannot be resolved\n * \n * @example\n * ```typescript\n * // File reference\n * const content = await processFieldValue('@file:template.md', '/path/to/dir');\n * \n * // Lookup with auto-create\n * const userId = await processFieldValue('@lookup:Users.Email=john@example.com?create', '/path');\n * \n * // Complex object - automatically stringified\n * const jsonStr = await processFieldValue({items: [{id: 1}, {id: 2}]}, '/path');\n * // Returns: '{\\n \"items\": [\\n {\\n \"id\": 1\\n },\\n {\\n \"id\": 2\\n }\\n ]\\n}'\n * ```\n */\n async processFieldValue(value: any, baseDir: string, parentRecord?: BaseEntity | null, rootRecord?: BaseEntity | null, depth: number = 0, batchContext?: Map<string, BaseEntity>): Promise<any> {\n // Check recursion depth limit\n const MAX_RECURSION_DEPTH = 50;\n if (depth > MAX_RECURSION_DEPTH) {\n throw new Error(`Maximum recursion depth (${MAX_RECURSION_DEPTH}) exceeded while processing field value: ${value}`);\n }\n // Handle arrays and objects by converting them to JSON strings\n if (value !== null && typeof value === 'object') {\n // Check if it's an array or a plain object (not a Date, etc.)\n if (Array.isArray(value) || value.constructor === Object) {\n // Convert to pretty-printed JSON string\n return JSON.stringify(value, null, 2);\n }\n }\n \n // If not a string, return as-is (numbers, booleans, null, etc.)\n if (typeof value !== 'string') {\n return value;\n }\n \n // If string starts with @ but isn't one of our known reference types, return as-is\n // This handles cases like npm package names (@mui/material, @angular/core, etc.)\n if (value.startsWith('@')) {\n const knownPrefixes = ['@parent:', '@root:', '@file:', '@lookup:', '@env:', '@template:', '@include'];\n const isKnownReference = knownPrefixes.some(prefix => value.startsWith(prefix));\n if (!isKnownReference) {\n return value; // Not a MetadataSync reference, just a string that happens to start with @\n }\n }\n \n // Check for @parent: reference\n if (value.startsWith('@parent:')) {\n if (!parentRecord) {\n throw new Error(`@parent reference used but no parent record available: ${value}`);\n }\n const fieldName = value.substring(8);\n return parentRecord.Get(fieldName);\n }\n \n // Check for @root: reference\n if (value.startsWith('@root:')) {\n if (!rootRecord) {\n throw new Error(`@root reference used but no root record available: ${value}`);\n }\n const fieldName = value.substring(6);\n return rootRecord.Get(fieldName);\n }\n \n // Check for @file: reference\n if (value.startsWith('@file:')) {\n const filePath = value.substring(6);\n const fullPath = path.resolve(baseDir, filePath);\n \n if (await fs.pathExists(fullPath)) {\n // Check if this is a JSON file that might contain @include directives\n if (fullPath.endsWith('.json')) {\n try {\n // Parse as JSON and check for @include directives\n const jsonContent = await fs.readJson(fullPath);\n \n // Check if the JSON contains any @include directives\n const jsonString = JSON.stringify(jsonContent);\n const hasIncludes = jsonString.includes('\"@include') || jsonString.includes('\"@include.');\n \n let processedJson: any;\n if (hasIncludes) {\n // Process @include directives with a fresh preprocessor instance\n const preprocessor = new JsonPreprocessor();\n processedJson = await preprocessor.processFile(fullPath);\n } else {\n processedJson = jsonContent;\n }\n \n // Now recursively process any @file references within the JSON\n const fileDir = path.dirname(fullPath);\n processedJson = await this.processJsonFieldValues(processedJson, fileDir, parentRecord, rootRecord, depth + 1, batchContext);\n \n // Return as JSON string since @file references typically expect string content\n return JSON.stringify(processedJson, null, 2);\n } catch (jsonError) {\n // Not valid JSON or error processing, fall back to text file handling\n const fileContent = await fs.readFile(fullPath, 'utf-8');\n // Process the file content for {@include} references in text files\n return await this.processFileContentWithIncludes(fileContent, fullPath);\n }\n } else {\n // Not a JSON file, process as text with {@include} support\n const fileContent = await fs.readFile(fullPath, 'utf-8');\n // Process the file content for {@include} references\n return await this.processFileContentWithIncludes(fileContent, fullPath);\n }\n } else {\n throw new Error(`File not found: ${fullPath}`);\n }\n }\n \n // Check for @url: reference\n if (value.startsWith('@url:')) {\n const url = value.substring(5);\n \n try {\n const response = await axios.get(url);\n return response.data;\n } catch (error) {\n throw new Error(`Failed to fetch URL: ${url} - ${error}`);\n }\n }\n \n // Check for @lookup: reference\n if (value.startsWith('@lookup:')) {\n const lookupStr = value.substring(8);\n \n // Parse lookup with optional create syntax\n // Format: EntityName.Field1=Value1&Field2=Value2?create&OtherField=Value\n const entityMatch = lookupStr.match(/^([^.]+)\\./);\n if (!entityMatch) {\n throw new Error(`Invalid lookup format: ${value}`);\n }\n \n const entityName = entityMatch[1];\n const remaining = lookupStr.substring(entityName.length + 1);\n \n // Check if this has ?create syntax\n const hasCreate = remaining.includes('?create');\n const lookupPart = hasCreate ? remaining.split('?')[0] : remaining;\n \n // Parse all lookup fields (can be multiple with &)\n const lookupFields: Array<{fieldName: string, fieldValue: string}> = [];\n const lookupPairs = lookupPart.split('&');\n \n for (const pair of lookupPairs) {\n const fieldMatch = pair.match(/^(.+?)=(.+)$/);\n if (!fieldMatch) {\n throw new Error(`Invalid lookup field format: ${pair} in ${value}`);\n }\n const [, fieldName, fieldValue] = fieldMatch;\n \n // Recursively process the field value to resolve any nested @ commands\n const processedValue = await this.processFieldValue(\n fieldValue.trim(), \n baseDir, \n parentRecord, \n rootRecord,\n depth + 1,\n batchContext\n );\n \n lookupFields.push({ fieldName: fieldName.trim(), fieldValue: processedValue });\n }\n \n if (lookupFields.length === 0) {\n throw new Error(`No lookup fields specified: ${value}`);\n }\n \n // Parse additional fields for creation if ?create is present\n let createFields: Record<string, any> = {};\n if (hasCreate && remaining.includes('?create&')) {\n const createPart = remaining.split('?create&')[1];\n const pairs = createPart.split('&');\n for (const pair of pairs) {\n const [key, val] = pair.split('=');\n if (key && val) {\n const decodedVal = decodeURIComponent(val);\n // Recursively process the field value to resolve any nested @ commands\n createFields[key] = await this.processFieldValue(\n decodedVal, \n baseDir, \n parentRecord, \n rootRecord,\n depth + 1,\n batchContext\n );\n }\n }\n }\n \n return await this.resolveLookup(entityName, lookupFields, hasCreate, createFields, batchContext);\n }\n \n // Check for @env: reference\n if (value.startsWith('@env:')) {\n const envVar = value.substring(5);\n const envValue = process.env[envVar];\n \n if (envValue === undefined) {\n throw new Error(`Environment variable not found: ${envVar}`);\n }\n \n return envValue;\n }\n \n return value;\n }\n \n /**\n * Resolve a lookup reference to an ID, optionally creating the record if it doesn't exist\n * \n * @param entityName - Name of the entity to search in\n * @param fieldName - Field to match against\n * @param fieldValue - Value to search for\n * @param autoCreate - Whether to create the record if not found\n * @param createFields - Additional fields to set when creating\n * @returns The ID of the found or created record\n * @throws Error if lookup fails and autoCreate is false\n * \n * @example\n * ```typescript\n * // Simple lookup\n * const categoryId = await resolveLookup('Categories', 'Name', 'Technology');\n * \n * // Lookup with auto-create\n * const tagId = await resolveLookup('Tags', 'Name', 'New Tag', true, {\n * Description: 'Auto-created tag',\n * Status: 'Active'\n * });\n * ```\n */\n async resolveLookup(\n entityName: string, \n lookupFields: Array<{fieldName: string, fieldValue: string}>,\n autoCreate: boolean = false,\n createFields: Record<string, any> = {},\n batchContext?: Map<string, BaseEntity>\n ): Promise<string> {\n // First check batch context for in-memory entities\n if (batchContext) {\n // Try to find the entity in batch context\n for (const [, entity] of batchContext) {\n // Check if this is the right entity type\n if (entity.EntityInfo?.Name === entityName) {\n // Check if all lookup fields match\n let allMatch = true;\n for (const {fieldName, fieldValue} of lookupFields) {\n const entityValue = entity.Get(fieldName);\n const normalizedEntityValue = entityValue?.toString() || '';\n const normalizedLookupValue = fieldValue?.toString() || '';\n \n if (normalizedEntityValue !== normalizedLookupValue) {\n allMatch = false;\n break;\n }\n }\n \n if (allMatch) {\n // Found in batch context, return primary key\n const entityInfo = this.metadata.EntityByName(entityName);\n if (entityInfo && entityInfo.PrimaryKeys.length > 0) {\n const pkeyField = entityInfo.PrimaryKeys[0].Name;\n return entity.Get(pkeyField);\n }\n }\n }\n }\n }\n \n // Not found in batch context, check database\n const rv = new RunView();\n const entityInfo = this.metadata.EntityByName(entityName);\n if (!entityInfo) {\n throw new Error(`Entity not found: ${entityName}`);\n }\n \n // Build compound filter for all lookup fields\n const filterParts: string[] = [];\n for (const {fieldName, fieldValue} of lookupFields) {\n const field = entityInfo.Fields.find(f => f.Name.trim().toLowerCase() === fieldName.trim().toLowerCase());\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in entity '${entityName}'`);\n }\n \n // Handle null values properly\n if (fieldValue.trim().toLowerCase() === 'null') {\n filterParts.push(`${fieldName} IS NULL`);\n } else {\n const quotes = field.NeedsQuotes ? \"'\" : '';\n filterParts.push(`${fieldName} = ${quotes}${fieldValue.replace(/'/g, \"''\")}${quotes}`);\n }\n }\n \n const extraFilter = filterParts.join(' AND ');\n const result = await rv.RunView({\n EntityName: entityName,\n ExtraFilter: extraFilter,\n MaxRows: 1\n }, this.contextUser);\n \n if (result.Success && result.Results.length > 0) {\n if (entityInfo.PrimaryKeys.length > 0) {\n const pkeyField = entityInfo.PrimaryKeys[0].Name;\n const id = result.Results[0][pkeyField];\n return id;\n }\n }\n \n // If not found and auto-create is enabled, create the record\n if (autoCreate) {\n \n const newEntity = await this.metadata.GetEntityObject(entityName, this.contextUser);\n if (!newEntity) {\n throw new Error(`Failed to create entity object for: ${entityName}`);\n }\n \n newEntity.NewRecord();\n \n // UUID generation now happens automatically in BaseEntity.NewRecord()\n \n // Set all lookup fields\n for (const {fieldName, fieldValue} of lookupFields) {\n if (fieldName in newEntity) {\n // Handle null values properly\n if (fieldValue.toLowerCase() === 'null') {\n (newEntity as any)[fieldName] = null;\n } else {\n (newEntity as any)[fieldName] = fieldValue;\n }\n }\n }\n \n // Set any additional fields provided\n for (const [key, value] of Object.entries(createFields)) {\n if (key in newEntity) {\n (newEntity as any)[key] = value;\n }\n }\n \n // Save the new record (new records are always dirty)\n const filterDesc = lookupFields.map(({fieldName, fieldValue}) => `${fieldName}='${fieldValue}'`).join(' AND ');\n console.log(`š Auto-creating ${entityName} record where ${filterDesc}`);\n const saved = await newEntity.Save();\n if (!saved) {\n const message = newEntity.LatestResult?.Message;\n if (message) {\n throw new Error(`Failed to auto-create ${entityName}: ${message}`);\n }\n \n const errors = newEntity.LatestResult?.Errors?.map(err => \n typeof err === 'string' ? err : (err?.message || JSON.stringify(err))\n )?.join(', ') || 'Unknown error';\n throw new Error(`Failed to auto-create ${entityName}: ${errors}`);\n }\n \n // Return the new ID\n if (entityInfo.PrimaryKeys.length > 0) {\n const pkeyField = entityInfo.PrimaryKeys[0].Name;\n const newId = newEntity.Get(pkeyField);\n return newId;\n }\n }\n \n const filterDesc = lookupFields.map(({fieldName, fieldValue}) => `${fieldName}='${fieldValue}'`).join(' AND ');\n throw new Error(`Lookup failed: No record found in '${entityName}' where ${filterDesc}`);\n }\n \n /**\n * Build cascading defaults for a file path and process field values\n * \n * Walks up the directory tree from the file location, collecting defaults from\n * entity config and folder configs, with deeper folders overriding parent values.\n * All default values are processed for special references.\n * \n * @param filePath - Path to the file being processed\n * @param entityConfig - Entity configuration containing base defaults\n * @returns Processed defaults with all references resolved\n * @throws Error if any default value processing fails\n */\n async buildDefaults(filePath: string, entityConfig: EntityConfig): Promise<Record<string, any>> {\n const parts = path.dirname(filePath).split(path.sep);\n let defaults: Record<string, any> = { ...entityConfig.defaults };\n \n // Walk up the directory tree building defaults\n let currentPath = '';\n for (const part of parts) {\n currentPath = path.join(currentPath, part);\n const folderConfig = await this.loadFolderConfig(currentPath);\n \n if (folderConfig?.defaults) {\n defaults = { ...defaults, ...folderConfig.defaults };\n }\n }\n \n // Process all default values (lookups, file references, etc.)\n const processedDefaults: Record<string, any> = {};\n const baseDir = path.dirname(filePath);\n \n for (const [field, value] of Object.entries(defaults)) {\n try {\n processedDefaults[field] = await this.processFieldValue(value, baseDir, null, null, 0);\n } catch (error) {\n throw new Error(`Failed to process default for field '${field}': ${error}`);\n }\n }\n \n return processedDefaults;\n }\n \n /**\n * Load folder configuration from .mj-folder.json file\n * \n * @param dir - Directory to check for configuration\n * @returns Folder configuration or null if not found/invalid\n * @private\n */\n private async loadFolderConfig(dir: string): Promise<FolderConfig | null> {\n const configPath = path.join(dir, '.mj-folder.json');\n \n if (await fs.pathExists(configPath)) {\n try {\n return await fs.readJson(configPath);\n } catch (error) {\n console.error(`Error loading folder config at ${configPath}:`, error);\n return null;\n }\n }\n \n return null;\n }\n \n /**\n * Calculate SHA256 checksum for data\n * \n * Generates a deterministic hash of the provided data by converting it to\n * formatted JSON and calculating a SHA256 digest. Used for change detection\n * in sync operations.\n * \n * @param data - Any data structure to calculate checksum for\n * @returns Hexadecimal string representation of the SHA256 hash\n * \n * @example\n * ```typescript\n * const checksum = syncEngine.calculateChecksum({\n * name: 'Test Record',\n * value: 42,\n * tags: ['a', 'b']\n * });\n * // Returns consistent hash for same data structure\n * ```\n */\n calculateChecksum(data: any): string {\n const hash = crypto.createHash('sha256');\n hash.update(JSON.stringify(data, null, 2));\n return hash.digest('hex');\n }\n\n /**\n * Calculate checksum including resolved file content\n * \n * Enhanced checksum calculation that resolves @file references and includes\n * the actual file content (with @include directives processed) in the checksum.\n * This ensures that changes to referenced files are detected.\n * \n * @param data - Fields object that may contain @file references\n * @param entityDir - Directory for resolving relative file paths\n * @returns Promise resolving to checksum string\n */\n async calculateChecksumWithFileContent(data: any, entityDir: string): Promise<string> {\n const processedData = await this.resolveFileReferencesForChecksum(data, entityDir);\n return this.calculateChecksum(processedData);\n }\n\n /**\n * Resolve @file references for checksum calculation\n * \n * Recursively processes an object and replaces @file references with their\n * actual content (including resolved @include directives). This ensures the\n * checksum reflects the actual content, not just the reference.\n * \n * @param obj - Object to process\n * @param entityDir - Directory for resolving relative paths\n * @returns Promise resolving to processed object\n * @private\n */\n private async resolveFileReferencesForChecksum(obj: any, entityDir: string): Promise<any> {\n if (!obj || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return Promise.all(obj.map(item => this.resolveFileReferencesForChecksum(item, entityDir)));\n }\n\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n if (typeof value === 'string' && value.startsWith('@file:')) {\n // Process @file reference and include actual content\n try {\n const filePath = value.substring(6);\n const fullPath = path.isAbsolute(filePath) ? filePath : path.join(entityDir, filePath);\n \n if (await fs.pathExists(fullPath)) {\n let processedContent: string;\n \n // Check if this is a JSON file that might contain @include directives\n if (fullPath.endsWith('.json')) {\n try {\n const jsonContent = await fs.readJson(fullPath);\n const jsonString = JSON.stringify(jsonContent);\n const hasIncludes = jsonString.includes('\"@include') || jsonString.includes('\"@include.');\n \n if (hasIncludes) {\n // Process @include directives\n const preprocessor = new JsonPreprocessor();\n const processedJson = await preprocessor.processFile(fullPath);\n processedContent = JSON.stringify(processedJson, null, 2);\n } else {\n processedContent = JSON.stringify(jsonContent, null, 2);\n }\n } catch {\n // Not valid JSON, process as text\n const content = await fs.readFile(fullPath, 'utf-8');\n processedContent = await this.processFileContentWithIncludes(content, fullPath);\n }\n } else {\n // Text file - process {@include} references\n const content = await fs.readFile(fullPath, 'utf-8');\n processedContent = await this.processFileContentWithIncludes(content, fullPath);\n }\n \n result[key] = {\n _checksumType: 'file',\n _reference: value,\n _content: processedContent\n };\n } else {\n // File doesn't exist, keep the reference\n result[key] = value;\n }\n } catch (error) {\n // Error reading file, keep the reference\n result[key] = value;\n }\n } else if (typeof value === 'object') {\n result[key] = await this.resolveFileReferencesForChecksum(value, entityDir);\n } else {\n result[key] = value;\n }\n }\n return result;\n }\n \n /**\n * Get entity metadata information by name\n * \n * Retrieves the EntityInfo object containing schema metadata for the specified entity.\n * Returns null if the entity is not found in the metadata cache.\n * \n * @param entityName - Name of the entity to look up\n * @returns EntityInfo object with schema details or null if not found\n * \n * @example\n * ```typescript\n * const entityInfo = syncEngine.getEntityInfo('AI Prompts');\n * if (entityInfo) {\n * console.log(`Primary keys: ${entityInfo.PrimaryKeys.map(pk => pk.Name).join(', ')}`);\n * }\n * ```\n */\n getEntityInfo(entityName: string): EntityInfo | null {\n return this.metadata.EntityByName(entityName);\n }\n \n /**\n * Create a new entity object instance\n * \n * Uses the MemberJunction metadata system to properly instantiate an entity object.\n * This ensures correct class registration and respects any custom entity subclasses.\n * \n * @param entityName - Name of the entity to create\n * @returns Promise resolving to the new BaseEntity instance\n * @throws Error if entity creation fails\n * \n * @example\n * ```typescript\n * const entity = await syncEngine.createEntityObject('AI Prompts');\n * entity.NewRecord();\n * entity.Set('Name', 'My Prompt');\n * await entity.Save();\n * ```\n */\n async createEntityObject(entityName: string): Promise<BaseEntity> {\n const entity = await this.metadata.GetEntityObject(entityName, this.contextUser);\n if (!entity) {\n throw new Error(`Failed to create entity object for: ${entityName}`);\n }\n return entity;\n }\n \n /**\n * Load an entity record by primary key\n * \n * Retrieves an existing entity record from the database using its primary key values.\n * Supports both single and composite primary keys. Returns null if the record is not found.\n * \n * @param entityName - Name of the entity to load\n * @param primaryKey - Object containing primary key field names and values\n * @returns Promise resolving to the loaded entity or null if not found\n * @throws Error if entity metadata is not found\n * \n * @example\n * ```typescript\n * // Single primary key\n * const entity = await syncEngine.loadEntity('Users', { ID: '123-456' });\n * \n * // Composite primary key\n * const entity = await syncEngine.loadEntity('UserRoles', { \n * UserID: '123-456',\n * RoleID: '789-012'\n * });\n * ```\n */\n async loadEntity(entityName: string, primaryKey: Record<string, any>): Promise<BaseEntity | null> {\n const entityInfo = this.getEntityInfo(entityName);\n \n if (!entityInfo) {\n throw new Error(`Entity not found: ${entityName}`);\n }\n \n // First, check if the record exists using RunView to avoid \"Error in BaseEntity.Load\" messages\n // when records don't exist (which is a normal scenario during sync operations)\n const rv = new RunView();\n \n // Build filter for primary key(s)\n const filters: string[] = [];\n for (const pk of entityInfo.PrimaryKeys) {\n const value = primaryKey[pk.Name];\n if (value === undefined || value === null) {\n throw new Error(`Missing primary key value for ${pk.Name} in entity ${entityName}`);\n }\n \n // Check if field needs quotes\n const field = entityInfo.Fields.find(f => f.Name === pk.Name);\n const quotes = field?.NeedsQuotes ? \"'\" : '';\n const escapedValue = field?.NeedsQuotes && typeof value === 'string' ? value.replace(/'/g, \"''\") : value;\n filters.push(`${pk.Name} = ${quotes}${escapedValue}${quotes}`);\n }\n \n const result = await rv.RunView({\n EntityName: entityName,\n ExtraFilter: filters.join(' AND '),\n MaxRows: 1\n }, this.contextUser);\n \n // If no record found, return null without attempting to load\n if (!result.Success || result.Results.length === 0) {\n return null;\n }\n \n // Record exists, now load it properly through the entity\n const entity = await this.createEntityObject(entityName);\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromSimpleObject(primaryKey);\n const loaded = await entity.InnerLoad(compositeKey);\n \n return loaded ? entity : null;\n }\n \n /**\n * Process file content with {@include} references\n * \n * Recursively processes a file's content to resolve `{@include path}` references.\n * Include references use JSDoc-style syntax and support:\n * - Relative paths resolved from the containing file's directory\n * - Recursive includes (includes within included files)\n * - Circular reference detection to prevent infinite loops\n * - Seamless content substitution maintaining surrounding text\n * \n * @param content - The file content to process\n * @param filePath - Path to the file being processed\n * @param visitedPaths - Set of already visited file paths for circular reference detection\n * @returns Promise resolving to the content with all includes resolved\n * @throws Error if circular reference detected or included file not found\n * \n * @example\n * ```typescript\n * // Content with include reference\n * const content = 'This is a {@include ./shared/header.md} example';\n * \n * // Resolves to:\n * const result = await processFileContentWithIncludes('/path/to/file.md', content);\n * // 'This is a [contents of header.md] example'\n * ```\n */\n private async processFileContentWithIncludes(\n content: string,\n filePath: string, \n visitedPaths: Set<string> = new Set()\n ): Promise<string> {\n // Add current file to visited set\n const absolutePath = path.resolve(filePath);\n if (visitedPaths.has(absolutePath)) {\n throw new Error(`Circular reference detected: ${absolutePath} is already being processed`);\n }\n visitedPaths.add(absolutePath);\n \n // Pattern to match {@include path} references\n // Supports whitespace around the path for flexibility\n const includePattern = /\\{@include\\s+([^\\}]+)\\s*\\}/g;\n \n let processedContent = content;\n let match: RegExpExecArray | null;\n \n // Process all {@include} references\n while ((match = includePattern.exec(content)) !== null) {\n const [fullMatch, includePath] = match;\n const trimmedPath = includePath.trim();\n \n // Resolve the include path relative to the current file's directory\n const currentDir = path.dirname(filePath);\n const resolvedPath = path.resolve(currentDir, trimmedPath);\n \n try {\n // Check if the included file exists\n if (!await fs.pathExists(resolvedPath)) {\n throw new Error(`Included file not found: ${resolvedPath}`);\n }\n \n // Read the included file\n const includedContent = await fs.readFile(resolvedPath, 'utf-8');\n \n // Recursively process the included content for nested includes\n const processedInclude = await this.processFileContentWithIncludes(\n includedContent,\n resolvedPath, \n new Set(visitedPaths) // Pass a copy to allow the same file in different branches\n );\n \n // Replace the {@include} reference with the processed content\n processedContent = processedContent.replace(fullMatch, processedInclude);\n } catch (error) {\n // Enhance error message with context\n throw new Error(`Failed to process {@include ${trimmedPath}} in ${filePath}: ${error}`);\n }\n }\n \n return processedContent;\n }\n\n /**\n * Recursively process field values in a JSON object\n * \n * Processes all string values in a JSON object through processFieldValue,\n * which handles @file, @lookup, @parent, @root references. This ensures\n * that nested @file references within JSON files are properly resolved.\n * \n * @param obj - JSON object to process\n * @param baseDir - Base directory for resolving relative file paths\n * @param parentRecord - Parent entity record for @parent references\n * @param rootRecord - Root entity record for @root references\n * @param depth - Current recursion depth\n * @param batchContext - Batch processing context\n * @returns Promise resolving to processed JSON object\n * @private\n */\n private async processJsonFieldValues(\n obj: any,\n baseDir: string,\n parentRecord?: BaseEntity | null,\n rootRecord?: BaseEntity | null,\n depth: number = 0,\n batchContext?: Map<string, BaseEntity>\n ): Promise<any> {\n // Handle null and undefined\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n // Handle arrays\n if (Array.isArray(obj)) {\n return Promise.all(\n obj.map(item => \n this.processJsonFieldValues(item, baseDir, parentRecord, rootRecord, depth, batchContext)\n )\n );\n }\n\n // Handle objects\n if (typeof obj === 'object') {\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n // Process string values that might contain references\n if (typeof value === 'string') {\n // Check if this looks like a reference that needs processing\n // Only process known reference types, ignore other @ strings (like npm packages)\n if (value.startsWith('@file:') || value.startsWith('@lookup:') || \n value.startsWith('@parent:') || value.startsWith('@root:') ||\n value.startsWith('@env:') || value.startsWith('@template:') ||\n value.startsWith('@include')) {\n result[key] = await this.processFieldValue(value, baseDir, parentRecord, rootRecord, depth, batchContext);\n } else {\n result[key] = value;\n }\n } else if (typeof value === 'object') {\n // Recursively process nested objects\n result[key] = await this.processJsonFieldValues(value, baseDir, parentRecord, rootRecord, depth, batchContext);\n } else {\n // Keep primitive values as-is\n result[key] = value;\n }\n }\n return result;\n }\n\n // Return primitive values as-is\n return obj;\n }\n \n}"]}
|
|
1
|
+
{"version":3,"file":"sync-engine.js","sourceRoot":"","sources":["../../src/lib/sync-engine.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Core synchronization engine for MemberJunction metadata\n * @module sync-engine\n * \n * This module provides the core functionality for synchronizing metadata between\n * the MemberJunction database and local file system representations. It handles\n * special reference types (@file, @url, @lookup, @env, @parent, @root, @template),\n * manages entity operations, and provides utilities for data transformation.\n */\n\nimport path from 'path';\nimport fs from 'fs-extra';\nimport crypto from 'crypto';\nimport axios from 'axios';\nimport { EntityInfo, Metadata, RunView, BaseEntity, CompositeKey, UserInfo } from '@memberjunction/core';\nimport { EntityConfig, FolderConfig } from '../config';\nimport { JsonPreprocessor } from './json-preprocessor';\n\n/**\n * Represents the structure of a metadata record with optional sync tracking\n */\nexport interface RecordData {\n /** Primary key field(s) and their values */\n primaryKey?: Record<string, any>;\n /** Entity field names and their values */\n fields: Record<string, any>;\n /** Related entities organized by entity name */\n relatedEntities?: Record<string, RecordData[]>;\n /** Synchronization metadata for change tracking */\n sync?: {\n /** ISO timestamp of last modification */\n lastModified: string;\n /** SHA256 checksum of the fields object */\n checksum: string;\n };\n}\n\n/**\n * Core engine for synchronizing MemberJunction metadata between database and files\n * \n * @class SyncEngine\n * @example\n * ```typescript\n * const syncEngine = new SyncEngine(systemUser);\n * \n * // Process a field value with special references\n * const value = await syncEngine.processFieldValue('@lookup:Users.Email=admin@example.com', '/path/to/base');\n * ```\n */\nexport class SyncEngine {\n private metadata: Metadata;\n private contextUser: UserInfo;\n\n /**\n * Creates a new SyncEngine instance\n * @param contextUser - The user context for database operations\n */\n constructor(contextUser: UserInfo) {\n this.metadata = new Metadata();\n this.contextUser = contextUser;\n }\n \n /**\n * Initializes the sync engine by refreshing metadata cache\n * @returns Promise that resolves when initialization is complete\n */\n async initialize(): Promise<void> {\n // Currently no initialization needed as metadata is managed globally\n // Keeping this method for backward compatibility and future use\n }\n \n /**\n * Process special references in field values and handle complex objects\n * \n * Automatically handles:\n * - Arrays and objects are converted to JSON strings\n * - Scalars (strings, numbers, booleans, null) pass through unchanged\n * \n * Handles the following reference types for string values:\n * - `@parent:fieldName` - References a field from the parent record\n * - `@root:fieldName` - References a field from the root record\n * - `@file:path` - Reads content from an external file\n * - `@url:address` - Fetches content from a URL\n * - `@lookup:Entity.Field=Value` - Looks up an entity ID by field value\n * - `@env:VARIABLE` - Reads an environment variable\n * \n * @param value - The field value to process\n * @param baseDir - Base directory for resolving relative file paths\n * @param parentRecord - Optional parent entity for @parent references\n * @param rootRecord - Optional root entity for @root references\n * @returns The processed value with all references resolved\n * @throws Error if a reference cannot be resolved\n * \n * @example\n * ```typescript\n * // File reference\n * const content = await processFieldValue('@file:template.md', '/path/to/dir');\n * \n * // Lookup with auto-create\n * const userId = await processFieldValue('@lookup:Users.Email=john@example.com?create', '/path');\n * \n * // Complex object - automatically stringified\n * const jsonStr = await processFieldValue({items: [{id: 1}, {id: 2}]}, '/path');\n * // Returns: '{\\n \"items\": [\\n {\\n \"id\": 1\\n },\\n {\\n \"id\": 2\\n }\\n ]\\n}'\n * ```\n */\n async processFieldValue(value: any, baseDir: string, parentRecord?: BaseEntity | null, rootRecord?: BaseEntity | null, depth: number = 0, batchContext?: Map<string, BaseEntity>): Promise<any> {\n // Check recursion depth limit\n const MAX_RECURSION_DEPTH = 50;\n if (depth > MAX_RECURSION_DEPTH) {\n throw new Error(`Maximum recursion depth (${MAX_RECURSION_DEPTH}) exceeded while processing field value: ${value}`);\n }\n // Handle arrays and objects that are directly defined in metadata files\n // Note: Objects loaded from @file references are returned as-is to preserve proper escaping\n if (value !== null && typeof value === 'object') {\n // Check if it's an array or a plain object (not a Date, etc.)\n if (Array.isArray(value) || value.constructor === Object) {\n // Convert to pretty-printed JSON string for inline metadata objects\n // Objects from @file references will be handled by BaseEntity during save\n return JSON.stringify(value, null, 2);\n }\n }\n \n // If not a string, return as-is (numbers, booleans, null, etc.)\n if (typeof value !== 'string') {\n return value;\n }\n \n // If string starts with @ but isn't one of our known reference types, return as-is\n // This handles cases like npm package names (@mui/material, @angular/core, etc.)\n if (value.startsWith('@')) {\n const knownPrefixes = ['@parent:', '@root:', '@file:', '@lookup:', '@env:', '@template:', '@include'];\n const isKnownReference = knownPrefixes.some(prefix => value.startsWith(prefix));\n if (!isKnownReference) {\n return value; // Not a MetadataSync reference, just a string that happens to start with @\n }\n }\n \n // Check for @parent: reference\n if (value.startsWith('@parent:')) {\n if (!parentRecord) {\n throw new Error(`@parent reference used but no parent record available: ${value}`);\n }\n const fieldName = value.substring(8);\n return parentRecord.Get(fieldName);\n }\n \n // Check for @root: reference\n if (value.startsWith('@root:')) {\n if (!rootRecord) {\n throw new Error(`@root reference used but no root record available: ${value}`);\n }\n const fieldName = value.substring(6);\n return rootRecord.Get(fieldName);\n }\n \n // Check for @file: reference\n if (value.startsWith('@file:')) {\n const filePath = value.substring(6);\n const fullPath = path.resolve(baseDir, filePath);\n \n if (await fs.pathExists(fullPath)) {\n // Check if this is a JSON file that might contain @include directives\n if (fullPath.endsWith('.json')) {\n try {\n // Parse as JSON and check for @include directives\n const jsonContent = await fs.readJson(fullPath);\n \n // Check if the JSON contains any @include directives\n const jsonString = JSON.stringify(jsonContent);\n const hasIncludes = jsonString.includes('\"@include') || jsonString.includes('\"@include.');\n \n let processedJson: any;\n if (hasIncludes) {\n // Process @include directives with a fresh preprocessor instance\n const preprocessor = new JsonPreprocessor();\n processedJson = await preprocessor.processFile(fullPath);\n } else {\n processedJson = jsonContent;\n }\n \n // Now recursively process any @file references within the JSON\n const fileDir = path.dirname(fullPath);\n processedJson = await this.processJsonFieldValues(processedJson, fileDir, parentRecord, rootRecord, depth + 1, batchContext);\n \n // Return the processed JSON object directly without stringifying\n // Let BaseEntity handle serialization when saving to database\n // This ensures proper escaping of embedded code/scripts\n return processedJson;\n } catch (jsonError) {\n // Not valid JSON or error processing, fall back to text file handling\n const fileContent = await fs.readFile(fullPath, 'utf-8');\n // Process the file content for {@include} references in text files\n return await this.processFileContentWithIncludes(fileContent, fullPath);\n }\n } else {\n // Not a JSON file, process as text with {@include} support\n const fileContent = await fs.readFile(fullPath, 'utf-8');\n // Process the file content for {@include} references\n return await this.processFileContentWithIncludes(fileContent, fullPath);\n }\n } else {\n throw new Error(`File not found: ${fullPath}`);\n }\n }\n \n // Check for @url: reference\n if (value.startsWith('@url:')) {\n const url = value.substring(5);\n \n try {\n const response = await axios.get(url);\n return response.data;\n } catch (error) {\n throw new Error(`Failed to fetch URL: ${url} - ${error}`);\n }\n }\n \n // Check for @lookup: reference\n if (value.startsWith('@lookup:')) {\n const lookupStr = value.substring(8);\n \n // Parse lookup with optional create syntax\n // Format: EntityName.Field1=Value1&Field2=Value2?create&OtherField=Value\n const entityMatch = lookupStr.match(/^([^.]+)\\./);\n if (!entityMatch) {\n throw new Error(`Invalid lookup format: ${value}`);\n }\n \n const entityName = entityMatch[1];\n const remaining = lookupStr.substring(entityName.length + 1);\n \n // Check if this has ?create syntax\n const hasCreate = remaining.includes('?create');\n const lookupPart = hasCreate ? remaining.split('?')[0] : remaining;\n \n // Parse all lookup fields (can be multiple with &)\n const lookupFields: Array<{fieldName: string, fieldValue: string}> = [];\n const lookupPairs = lookupPart.split('&');\n \n for (const pair of lookupPairs) {\n const fieldMatch = pair.match(/^(.+?)=(.+)$/);\n if (!fieldMatch) {\n throw new Error(`Invalid lookup field format: ${pair} in ${value}`);\n }\n const [, fieldName, fieldValue] = fieldMatch;\n \n // Recursively process the field value to resolve any nested @ commands\n const processedValue = await this.processFieldValue(\n fieldValue.trim(), \n baseDir, \n parentRecord, \n rootRecord,\n depth + 1,\n batchContext\n );\n \n lookupFields.push({ fieldName: fieldName.trim(), fieldValue: processedValue });\n }\n \n if (lookupFields.length === 0) {\n throw new Error(`No lookup fields specified: ${value}`);\n }\n \n // Parse additional fields for creation if ?create is present\n let createFields: Record<string, any> = {};\n if (hasCreate && remaining.includes('?create&')) {\n const createPart = remaining.split('?create&')[1];\n const pairs = createPart.split('&');\n for (const pair of pairs) {\n const [key, val] = pair.split('=');\n if (key && val) {\n const decodedVal = decodeURIComponent(val);\n // Recursively process the field value to resolve any nested @ commands\n createFields[key] = await this.processFieldValue(\n decodedVal, \n baseDir, \n parentRecord, \n rootRecord,\n depth + 1,\n batchContext\n );\n }\n }\n }\n \n return await this.resolveLookup(entityName, lookupFields, hasCreate, createFields, batchContext);\n }\n \n // Check for @env: reference\n if (value.startsWith('@env:')) {\n const envVar = value.substring(5);\n const envValue = process.env[envVar];\n \n if (envValue === undefined) {\n throw new Error(`Environment variable not found: ${envVar}`);\n }\n \n return envValue;\n }\n \n return value;\n }\n \n /**\n * Resolve a lookup reference to an ID, optionally creating the record if it doesn't exist\n * \n * @param entityName - Name of the entity to search in\n * @param fieldName - Field to match against\n * @param fieldValue - Value to search for\n * @param autoCreate - Whether to create the record if not found\n * @param createFields - Additional fields to set when creating\n * @returns The ID of the found or created record\n * @throws Error if lookup fails and autoCreate is false\n * \n * @example\n * ```typescript\n * // Simple lookup\n * const categoryId = await resolveLookup('Categories', 'Name', 'Technology');\n * \n * // Lookup with auto-create\n * const tagId = await resolveLookup('Tags', 'Name', 'New Tag', true, {\n * Description: 'Auto-created tag',\n * Status: 'Active'\n * });\n * ```\n */\n async resolveLookup(\n entityName: string, \n lookupFields: Array<{fieldName: string, fieldValue: string}>,\n autoCreate: boolean = false,\n createFields: Record<string, any> = {},\n batchContext?: Map<string, BaseEntity>\n ): Promise<string> {\n // First check batch context for in-memory entities\n if (batchContext) {\n // Try to find the entity in batch context\n for (const [, entity] of batchContext) {\n // Check if this is the right entity type\n if (entity.EntityInfo?.Name === entityName) {\n // Check if all lookup fields match\n let allMatch = true;\n for (const {fieldName, fieldValue} of lookupFields) {\n const entityValue = entity.Get(fieldName);\n const normalizedEntityValue = entityValue?.toString() || '';\n const normalizedLookupValue = fieldValue?.toString() || '';\n \n if (normalizedEntityValue !== normalizedLookupValue) {\n allMatch = false;\n break;\n }\n }\n \n if (allMatch) {\n // Found in batch context, return primary key\n const entityInfo = this.metadata.EntityByName(entityName);\n if (entityInfo && entityInfo.PrimaryKeys.length > 0) {\n const pkeyField = entityInfo.PrimaryKeys[0].Name;\n return entity.Get(pkeyField);\n }\n }\n }\n }\n }\n \n // Not found in batch context, check database\n const rv = new RunView();\n const entityInfo = this.metadata.EntityByName(entityName);\n if (!entityInfo) {\n throw new Error(`Entity not found: ${entityName}`);\n }\n \n // Build compound filter for all lookup fields\n const filterParts: string[] = [];\n for (const {fieldName, fieldValue} of lookupFields) {\n const field = entityInfo.Fields.find(f => f.Name.trim().toLowerCase() === fieldName.trim().toLowerCase());\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in entity '${entityName}'`);\n }\n \n // Handle null values properly\n if (fieldValue.trim().toLowerCase() === 'null') {\n filterParts.push(`${fieldName} IS NULL`);\n } else {\n const quotes = field.NeedsQuotes ? \"'\" : '';\n filterParts.push(`${fieldName} = ${quotes}${fieldValue.replace(/'/g, \"''\")}${quotes}`);\n }\n }\n \n const extraFilter = filterParts.join(' AND ');\n const result = await rv.RunView({\n EntityName: entityName,\n ExtraFilter: extraFilter,\n MaxRows: 1\n }, this.contextUser);\n \n if (result.Success && result.Results.length > 0) {\n if (entityInfo.PrimaryKeys.length > 0) {\n const pkeyField = entityInfo.PrimaryKeys[0].Name;\n const id = result.Results[0][pkeyField];\n return id;\n }\n }\n \n // If not found and auto-create is enabled, create the record\n if (autoCreate) {\n \n const newEntity = await this.metadata.GetEntityObject(entityName, this.contextUser);\n if (!newEntity) {\n throw new Error(`Failed to create entity object for: ${entityName}`);\n }\n \n newEntity.NewRecord();\n \n // UUID generation now happens automatically in BaseEntity.NewRecord()\n \n // Set all lookup fields\n for (const {fieldName, fieldValue} of lookupFields) {\n if (fieldName in newEntity) {\n // Handle null values properly\n if (fieldValue.toLowerCase() === 'null') {\n (newEntity as any)[fieldName] = null;\n } else {\n (newEntity as any)[fieldName] = fieldValue;\n }\n }\n }\n \n // Set any additional fields provided\n for (const [key, value] of Object.entries(createFields)) {\n if (key in newEntity) {\n (newEntity as any)[key] = value;\n }\n }\n \n // Save the new record (new records are always dirty)\n const filterDesc = lookupFields.map(({fieldName, fieldValue}) => `${fieldName}='${fieldValue}'`).join(' AND ');\n console.log(`š Auto-creating ${entityName} record where ${filterDesc}`);\n const saved = await newEntity.Save();\n if (!saved) {\n const message = newEntity.LatestResult?.Message;\n if (message) {\n throw new Error(`Failed to auto-create ${entityName}: ${message}`);\n }\n \n const errors = newEntity.LatestResult?.Errors?.map(err => \n typeof err === 'string' ? err : (err?.message || JSON.stringify(err))\n )?.join(', ') || 'Unknown error';\n throw new Error(`Failed to auto-create ${entityName}: ${errors}`);\n }\n \n // Return the new ID\n if (entityInfo.PrimaryKeys.length > 0) {\n const pkeyField = entityInfo.PrimaryKeys[0].Name;\n const newId = newEntity.Get(pkeyField);\n return newId;\n }\n }\n \n const filterDesc = lookupFields.map(({fieldName, fieldValue}) => `${fieldName}='${fieldValue}'`).join(' AND ');\n throw new Error(`Lookup failed: No record found in '${entityName}' where ${filterDesc}`);\n }\n \n /**\n * Build cascading defaults for a file path and process field values\n * \n * Walks up the directory tree from the file location, collecting defaults from\n * entity config and folder configs, with deeper folders overriding parent values.\n * All default values are processed for special references.\n * \n * @param filePath - Path to the file being processed\n * @param entityConfig - Entity configuration containing base defaults\n * @returns Processed defaults with all references resolved\n * @throws Error if any default value processing fails\n */\n async buildDefaults(filePath: string, entityConfig: EntityConfig): Promise<Record<string, any>> {\n const parts = path.dirname(filePath).split(path.sep);\n let defaults: Record<string, any> = { ...entityConfig.defaults };\n \n // Walk up the directory tree building defaults\n let currentPath = '';\n for (const part of parts) {\n currentPath = path.join(currentPath, part);\n const folderConfig = await this.loadFolderConfig(currentPath);\n \n if (folderConfig?.defaults) {\n defaults = { ...defaults, ...folderConfig.defaults };\n }\n }\n \n // Process all default values (lookups, file references, etc.)\n const processedDefaults: Record<string, any> = {};\n const baseDir = path.dirname(filePath);\n \n for (const [field, value] of Object.entries(defaults)) {\n try {\n processedDefaults[field] = await this.processFieldValue(value, baseDir, null, null, 0);\n } catch (error) {\n throw new Error(`Failed to process default for field '${field}': ${error}`);\n }\n }\n \n return processedDefaults;\n }\n \n /**\n * Load folder configuration from .mj-folder.json file\n * \n * @param dir - Directory to check for configuration\n * @returns Folder configuration or null if not found/invalid\n * @private\n */\n private async loadFolderConfig(dir: string): Promise<FolderConfig | null> {\n const configPath = path.join(dir, '.mj-folder.json');\n \n if (await fs.pathExists(configPath)) {\n try {\n return await fs.readJson(configPath);\n } catch (error) {\n console.error(`Error loading folder config at ${configPath}:`, error);\n return null;\n }\n }\n \n return null;\n }\n \n /**\n * Calculate SHA256 checksum for data\n * \n * Generates a deterministic hash of the provided data by converting it to\n * formatted JSON and calculating a SHA256 digest. Used for change detection\n * in sync operations.\n * \n * @param data - Any data structure to calculate checksum for\n * @returns Hexadecimal string representation of the SHA256 hash\n * \n * @example\n * ```typescript\n * const checksum = syncEngine.calculateChecksum({\n * name: 'Test Record',\n * value: 42,\n * tags: ['a', 'b']\n * });\n * // Returns consistent hash for same data structure\n * ```\n */\n calculateChecksum(data: any): string {\n const hash = crypto.createHash('sha256');\n hash.update(JSON.stringify(data, null, 2));\n return hash.digest('hex');\n }\n\n /**\n * Calculate checksum including resolved file content\n * \n * Enhanced checksum calculation that resolves @file references and includes\n * the actual file content (with @include directives processed) in the checksum.\n * This ensures that changes to referenced files are detected.\n * \n * @param data - Fields object that may contain @file references\n * @param entityDir - Directory for resolving relative file paths\n * @returns Promise resolving to checksum string\n */\n async calculateChecksumWithFileContent(data: any, entityDir: string): Promise<string> {\n const processedData = await this.resolveFileReferencesForChecksum(data, entityDir);\n return this.calculateChecksum(processedData);\n }\n\n /**\n * Resolve @file references for checksum calculation\n * \n * Recursively processes an object and replaces @file references with their\n * actual content (including resolved @include directives). This ensures the\n * checksum reflects the actual content, not just the reference.\n * \n * @param obj - Object to process\n * @param entityDir - Directory for resolving relative paths\n * @returns Promise resolving to processed object\n * @private\n */\n private async resolveFileReferencesForChecksum(obj: any, entityDir: string): Promise<any> {\n if (!obj || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return Promise.all(obj.map(item => this.resolveFileReferencesForChecksum(item, entityDir)));\n }\n\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n if (typeof value === 'string' && value.startsWith('@file:')) {\n // Process @file reference and include actual content\n try {\n const filePath = value.substring(6);\n const fullPath = path.isAbsolute(filePath) ? filePath : path.join(entityDir, filePath);\n \n if (await fs.pathExists(fullPath)) {\n let processedContent: string;\n \n // Check if this is a JSON file that might contain @include directives\n if (fullPath.endsWith('.json')) {\n try {\n const jsonContent = await fs.readJson(fullPath);\n const jsonString = JSON.stringify(jsonContent);\n const hasIncludes = jsonString.includes('\"@include') || jsonString.includes('\"@include.');\n \n if (hasIncludes) {\n // Process @include directives\n const preprocessor = new JsonPreprocessor();\n const processedJson = await preprocessor.processFile(fullPath);\n processedContent = JSON.stringify(processedJson, null, 2);\n } else {\n processedContent = JSON.stringify(jsonContent, null, 2);\n }\n } catch {\n // Not valid JSON, process as text\n const content = await fs.readFile(fullPath, 'utf-8');\n processedContent = await this.processFileContentWithIncludes(content, fullPath);\n }\n } else {\n // Text file - process {@include} references\n const content = await fs.readFile(fullPath, 'utf-8');\n processedContent = await this.processFileContentWithIncludes(content, fullPath);\n }\n \n result[key] = {\n _checksumType: 'file',\n _reference: value,\n _content: processedContent\n };\n } else {\n // File doesn't exist, keep the reference\n result[key] = value;\n }\n } catch (error) {\n // Error reading file, keep the reference\n result[key] = value;\n }\n } else if (typeof value === 'object') {\n result[key] = await this.resolveFileReferencesForChecksum(value, entityDir);\n } else {\n result[key] = value;\n }\n }\n return result;\n }\n \n /**\n * Get entity metadata information by name\n * \n * Retrieves the EntityInfo object containing schema metadata for the specified entity.\n * Returns null if the entity is not found in the metadata cache.\n * \n * @param entityName - Name of the entity to look up\n * @returns EntityInfo object with schema details or null if not found\n * \n * @example\n * ```typescript\n * const entityInfo = syncEngine.getEntityInfo('AI Prompts');\n * if (entityInfo) {\n * console.log(`Primary keys: ${entityInfo.PrimaryKeys.map(pk => pk.Name).join(', ')}`);\n * }\n * ```\n */\n getEntityInfo(entityName: string): EntityInfo | null {\n return this.metadata.EntityByName(entityName);\n }\n \n /**\n * Create a new entity object instance\n * \n * Uses the MemberJunction metadata system to properly instantiate an entity object.\n * This ensures correct class registration and respects any custom entity subclasses.\n * \n * @param entityName - Name of the entity to create\n * @returns Promise resolving to the new BaseEntity instance\n * @throws Error if entity creation fails\n * \n * @example\n * ```typescript\n * const entity = await syncEngine.createEntityObject('AI Prompts');\n * entity.NewRecord();\n * entity.Set('Name', 'My Prompt');\n * await entity.Save();\n * ```\n */\n async createEntityObject(entityName: string): Promise<BaseEntity> {\n const entity = await this.metadata.GetEntityObject(entityName, this.contextUser);\n if (!entity) {\n throw new Error(`Failed to create entity object for: ${entityName}`);\n }\n return entity;\n }\n \n /**\n * Load an entity record by primary key\n * \n * Retrieves an existing entity record from the database using its primary key values.\n * Supports both single and composite primary keys. Returns null if the record is not found.\n * \n * @param entityName - Name of the entity to load\n * @param primaryKey - Object containing primary key field names and values\n * @returns Promise resolving to the loaded entity or null if not found\n * @throws Error if entity metadata is not found\n * \n * @example\n * ```typescript\n * // Single primary key\n * const entity = await syncEngine.loadEntity('Users', { ID: '123-456' });\n * \n * // Composite primary key\n * const entity = await syncEngine.loadEntity('UserRoles', { \n * UserID: '123-456',\n * RoleID: '789-012'\n * });\n * ```\n */\n async loadEntity(entityName: string, primaryKey: Record<string, any>): Promise<BaseEntity | null> {\n const entityInfo = this.getEntityInfo(entityName);\n \n if (!entityInfo) {\n throw new Error(`Entity not found: ${entityName}`);\n }\n \n // First, check if the record exists using RunView to avoid \"Error in BaseEntity.Load\" messages\n // when records don't exist (which is a normal scenario during sync operations)\n const rv = new RunView();\n \n // Build filter for primary key(s)\n const filters: string[] = [];\n for (const pk of entityInfo.PrimaryKeys) {\n const value = primaryKey[pk.Name];\n if (value === undefined || value === null) {\n throw new Error(`Missing primary key value for ${pk.Name} in entity ${entityName}`);\n }\n \n // Check if field needs quotes\n const field = entityInfo.Fields.find(f => f.Name === pk.Name);\n const quotes = field?.NeedsQuotes ? \"'\" : '';\n const escapedValue = field?.NeedsQuotes && typeof value === 'string' ? value.replace(/'/g, \"''\") : value;\n filters.push(`${pk.Name} = ${quotes}${escapedValue}${quotes}`);\n }\n \n const result = await rv.RunView({\n EntityName: entityName,\n ExtraFilter: filters.join(' AND '),\n MaxRows: 1\n }, this.contextUser);\n \n // If no record found, return null without attempting to load\n if (!result.Success || result.Results.length === 0) {\n return null;\n }\n \n // Record exists, now load it properly through the entity\n const entity = await this.createEntityObject(entityName);\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromSimpleObject(primaryKey);\n const loaded = await entity.InnerLoad(compositeKey);\n \n return loaded ? entity : null;\n }\n \n /**\n * Process file content with {@include} references\n * \n * Recursively processes a file's content to resolve `{@include path}` references.\n * Include references use JSDoc-style syntax and support:\n * - Relative paths resolved from the containing file's directory\n * - Recursive includes (includes within included files)\n * - Circular reference detection to prevent infinite loops\n * - Seamless content substitution maintaining surrounding text\n * \n * @param content - The file content to process\n * @param filePath - Path to the file being processed\n * @param visitedPaths - Set of already visited file paths for circular reference detection\n * @returns Promise resolving to the content with all includes resolved\n * @throws Error if circular reference detected or included file not found\n * \n * @example\n * ```typescript\n * // Content with include reference\n * const content = 'This is a {@include ./shared/header.md} example';\n * \n * // Resolves to:\n * const result = await processFileContentWithIncludes('/path/to/file.md', content);\n * // 'This is a [contents of header.md] example'\n * ```\n */\n private async processFileContentWithIncludes(\n content: string,\n filePath: string, \n visitedPaths: Set<string> = new Set()\n ): Promise<string> {\n // Add current file to visited set\n const absolutePath = path.resolve(filePath);\n if (visitedPaths.has(absolutePath)) {\n throw new Error(`Circular reference detected: ${absolutePath} is already being processed`);\n }\n visitedPaths.add(absolutePath);\n \n // Pattern to match {@include path} references\n // Supports whitespace around the path for flexibility\n const includePattern = /\\{@include\\s+([^\\}]+)\\s*\\}/g;\n \n let processedContent = content;\n let match: RegExpExecArray | null;\n \n // Process all {@include} references\n while ((match = includePattern.exec(content)) !== null) {\n const [fullMatch, includePath] = match;\n const trimmedPath = includePath.trim();\n \n // Resolve the include path relative to the current file's directory\n const currentDir = path.dirname(filePath);\n const resolvedPath = path.resolve(currentDir, trimmedPath);\n \n try {\n // Check if the included file exists\n if (!await fs.pathExists(resolvedPath)) {\n throw new Error(`Included file not found: ${resolvedPath}`);\n }\n \n // Read the included file\n const includedContent = await fs.readFile(resolvedPath, 'utf-8');\n \n // Recursively process the included content for nested includes\n const processedInclude = await this.processFileContentWithIncludes(\n includedContent,\n resolvedPath, \n new Set(visitedPaths) // Pass a copy to allow the same file in different branches\n );\n \n // Replace the {@include} reference with the processed content\n processedContent = processedContent.replace(fullMatch, processedInclude);\n } catch (error) {\n // Enhance error message with context\n throw new Error(`Failed to process {@include ${trimmedPath}} in ${filePath}: ${error}`);\n }\n }\n \n return processedContent;\n }\n\n /**\n * Recursively process field values in a JSON object\n * \n * Processes all string values in a JSON object through processFieldValue,\n * which handles @file, @lookup, @parent, @root references. This ensures\n * that nested @file references within JSON files are properly resolved.\n * \n * @param obj - JSON object to process\n * @param baseDir - Base directory for resolving relative file paths\n * @param parentRecord - Parent entity record for @parent references\n * @param rootRecord - Root entity record for @root references\n * @param depth - Current recursion depth\n * @param batchContext - Batch processing context\n * @returns Promise resolving to processed JSON object\n * @private\n */\n private async processJsonFieldValues(\n obj: any,\n baseDir: string,\n parentRecord?: BaseEntity | null,\n rootRecord?: BaseEntity | null,\n depth: number = 0,\n batchContext?: Map<string, BaseEntity>\n ): Promise<any> {\n // Handle null and undefined\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n // Handle arrays\n if (Array.isArray(obj)) {\n return Promise.all(\n obj.map(item => \n this.processJsonFieldValues(item, baseDir, parentRecord, rootRecord, depth, batchContext)\n )\n );\n }\n\n // Handle objects\n if (typeof obj === 'object') {\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n // Process string values that might contain references\n if (typeof value === 'string') {\n // Check if this looks like a reference that needs processing\n // Only process known reference types, ignore other @ strings (like npm packages)\n if (value.startsWith('@file:') || value.startsWith('@lookup:') || \n value.startsWith('@parent:') || value.startsWith('@root:') ||\n value.startsWith('@env:') || value.startsWith('@template:') ||\n value.startsWith('@include')) {\n result[key] = await this.processFieldValue(value, baseDir, parentRecord, rootRecord, depth, batchContext);\n } else {\n result[key] = value;\n }\n } else if (typeof value === 'object') {\n // Recursively process nested objects\n result[key] = await this.processJsonFieldValues(value, baseDir, parentRecord, rootRecord, depth, batchContext);\n } else {\n // Keep primitive values as-is\n result[key] = value;\n }\n }\n return result;\n }\n\n // Return primitive values as-is\n return obj;\n }\n \n}"]}
|
|
@@ -17,7 +17,7 @@ const json_write_helper_1 = require("../lib/json-write-helper");
|
|
|
17
17
|
const record_dependency_analyzer_1 = require("../lib/record-dependency-analyzer");
|
|
18
18
|
const json_preprocessor_1 = require("../lib/json-preprocessor");
|
|
19
19
|
// Configuration for parallel processing
|
|
20
|
-
const PARALLEL_BATCH_SIZE =
|
|
20
|
+
const PARALLEL_BATCH_SIZE = 1; // Number of records to process in parallel at each dependency level
|
|
21
21
|
class PushService {
|
|
22
22
|
syncEngine;
|
|
23
23
|
contextUser;
|
|
@@ -597,7 +597,8 @@ class PushService {
|
|
|
597
597
|
return `"${value}"`;
|
|
598
598
|
}
|
|
599
599
|
if (typeof value === 'object') {
|
|
600
|
-
|
|
600
|
+
const str = JSON.stringify(value);
|
|
601
|
+
return str.length > 50 ? `"${str.substring(0, 47)}..."` : `"${str}"`;
|
|
601
602
|
}
|
|
602
603
|
return String(value);
|
|
603
604
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PushService.js","sourceRoot":"","sources":["../../src/services/PushService.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs-extra';\nimport path from 'path';\nimport fastGlob from 'fast-glob';\nimport { BaseEntity, Metadata, UserInfo } from '@memberjunction/core';\nimport { SyncEngine, RecordData } from '../lib/sync-engine';\nimport { loadEntityConfig, loadSyncConfig } from '../config';\nimport { FileBackupManager } from '../lib/file-backup-manager';\nimport { configManager } from '../lib/config-manager';\nimport { SQLLogger } from '../lib/sql-logger';\nimport { TransactionManager } from '../lib/transaction-manager';\nimport { JsonWriteHelper } from '../lib/json-write-helper';\nimport { RecordDependencyAnalyzer, FlattenedRecord } from '../lib/record-dependency-analyzer';\nimport { JsonPreprocessor } from '../lib/json-preprocessor';\nimport type { SqlLoggingSession, SQLServerDataProvider } from '@memberjunction/sqlserver-dataprovider';\n\n// Configuration for parallel processing\nconst PARALLEL_BATCH_SIZE = 10; // Number of records to process in parallel at each dependency level\n\nexport interface PushOptions {\n dir?: string;\n dryRun?: boolean;\n verbose?: boolean;\n noValidate?: boolean;\n parallelBatchSize?: number; // Number of records to process in parallel (default: 10)\n}\n\nexport interface PushCallbacks {\n onProgress?: (message: string) => void;\n onSuccess?: (message: string) => void;\n onError?: (message: string) => void;\n onWarn?: (message: string) => void;\n onLog?: (message: string) => void;\n onConfirm?: (message: string) => Promise<boolean>;\n}\n\nexport interface PushResult {\n created: number;\n updated: number;\n unchanged: number;\n errors: number;\n warnings: string[];\n sqlLogPath?: string;\n}\n\nexport interface EntityPushResult {\n created: number;\n updated: number;\n unchanged: number;\n errors: number;\n}\n\nexport class PushService {\n private syncEngine: SyncEngine;\n private contextUser: UserInfo;\n private warnings: string[] = [];\n private syncConfig: any;\n \n constructor(syncEngine: SyncEngine, contextUser: UserInfo) {\n this.syncEngine = syncEngine;\n this.contextUser = contextUser;\n }\n \n async push(options: PushOptions, callbacks?: PushCallbacks): Promise<PushResult> {\n this.warnings = [];\n \n const fileBackupManager = new FileBackupManager();\n \n // Load sync config for SQL logging settings and autoCreateMissingRecords flag\n // If dir option is specified, load from that directory, otherwise use original CWD\n const configDir = options.dir ? path.resolve(configManager.getOriginalCwd(), options.dir) : configManager.getOriginalCwd();\n this.syncConfig = await loadSyncConfig(configDir);\n \n if (options.verbose) {\n callbacks?.onLog?.(`Original working directory: ${configManager.getOriginalCwd()}`);\n callbacks?.onLog?.(`Config directory (with dir option): ${configDir}`);\n callbacks?.onLog?.(`Config file path: ${path.join(configDir, '.mj-sync.json')}`);\n callbacks?.onLog?.(`Full sync config loaded: ${JSON.stringify(this.syncConfig, null, 2)}`);\n callbacks?.onLog?.(`SQL logging config: ${JSON.stringify(this.syncConfig?.sqlLogging)}`);\n }\n \n const sqlLogger = new SQLLogger(this.syncConfig);\n const transactionManager = new TransactionManager(sqlLogger);\n \n if (options.verbose) {\n callbacks?.onLog?.(`SQLLogger enabled status: ${sqlLogger.enabled}`);\n }\n \n // Setup SQL logging session with the provider if enabled\n let sqlLoggingSession: SqlLoggingSession | null = null;\n \n try {\n // Initialize SQL logger if enabled and not dry-run\n if (sqlLogger.enabled && !options.dryRun) {\n const provider = Metadata.Provider as SQLServerDataProvider;\n \n if (options.verbose) {\n callbacks?.onLog?.(`SQL logging enabled: ${sqlLogger.enabled}`);\n callbacks?.onLog?.(`Provider type: ${provider?.constructor?.name || 'Unknown'}`);\n callbacks?.onLog?.(`Has CreateSqlLogger: ${typeof provider?.CreateSqlLogger === 'function'}`);\n }\n \n if (provider && typeof provider.CreateSqlLogger === 'function') {\n // Generate filename with timestamp\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = this.syncConfig.sqlLogging?.formatAsMigration \n ? `MetadataSync_Push_${timestamp}.sql`\n : `push_${timestamp}.sql`;\n \n // Use .sql-log-push directory in the config directory (where sync was initiated)\n const outputDir = path.join(configDir, this.syncConfig?.sqlLogging?.outputDirectory || './sql-log-push');\n const filepath = path.join(outputDir, filename);\n \n // Ensure the directory exists\n await fs.ensureDir(path.dirname(filepath));\n \n // Create the SQL logging session\n sqlLoggingSession = await provider.CreateSqlLogger(filepath, {\n formatAsMigration: this.syncConfig.sqlLogging?.formatAsMigration || false,\n description: 'MetadataSync push operation',\n statementTypes: \"mutations\",\n prettyPrint: true,\n filterPatterns: this.syncConfig.sqlLogging?.filterPatterns,\n filterType: this.syncConfig.sqlLogging?.filterType,\n });\n \n if (options.verbose) {\n callbacks?.onLog?.(`š SQL logging enabled: ${filepath}`);\n }\n } else {\n if (options.verbose) {\n callbacks?.onWarn?.('SQL logging requested but provider does not support it');\n }\n }\n }\n \n // Find entity directories to process\n // Note: If options.dir is specified, configDir already points to that directory\n // So we don't need to pass it as specificDir\n const entityDirs = this.findEntityDirectories(configDir, undefined, this.syncConfig?.directoryOrder);\n \n if (entityDirs.length === 0) {\n throw new Error('No entity directories found');\n }\n \n if (options.verbose) {\n callbacks?.onLog?.(`Found ${entityDirs.length} entity ${entityDirs.length === 1 ? 'directory' : 'directories'} to process`);\n }\n \n // Initialize file backup manager (unless in dry-run mode)\n if (!options.dryRun) {\n await fileBackupManager.initialize();\n if (options.verbose) {\n callbacks?.onLog?.('š File backup manager initialized');\n }\n }\n \n // Process each entity directory\n let totalCreated = 0;\n let totalUpdated = 0;\n let totalUnchanged = 0;\n let totalErrors = 0;\n \n // Begin transaction if not in dry-run mode\n if (!options.dryRun) {\n await transactionManager.beginTransaction();\n }\n \n try {\n for (const entityDir of entityDirs) {\n const entityConfig = await loadEntityConfig(entityDir);\n if (!entityConfig) {\n const warning = `Skipping ${entityDir} - no valid entity configuration`;\n this.warnings.push(warning);\n callbacks?.onWarn?.(warning);\n continue;\n }\n \n // Show folder with spinner at start\n const dirName = path.relative(process.cwd(), entityDir) || '.';\n callbacks?.onLog?.(`\\nš ${dirName}:`);\n \n // Use onProgress for animated spinner if available\n if (callbacks?.onProgress) {\n callbacks.onProgress(`Processing ${dirName}...`);\n } else {\n callbacks?.onLog?.(` ā³ Processing...`);\n }\n \n if (options.verbose && callbacks?.onLog) {\n callbacks.onLog(`Processing ${entityConfig.entity} in ${entityDir}`);\n }\n \n const result = await this.processEntityDirectory(\n entityDir,\n entityConfig,\n options,\n fileBackupManager,\n callbacks\n );\n \n // Stop the spinner if we were using onProgress\n if (callbacks?.onProgress && callbacks?.onSuccess) {\n callbacks.onSuccess(`Processed ${dirName}`);\n }\n \n // Show per-directory summary\n const dirTotal = result.created + result.updated + result.unchanged;\n if (dirTotal > 0 || result.errors > 0) {\n callbacks?.onLog?.(` Total processed: ${dirTotal} unique records`);\n if (result.created > 0) {\n callbacks?.onLog?.(` ā Created: ${result.created}`);\n }\n if (result.updated > 0) {\n callbacks?.onLog?.(` ā Updated: ${result.updated}`);\n }\n if (result.unchanged > 0) {\n callbacks?.onLog?.(` - Unchanged: ${result.unchanged}`);\n }\n if (result.errors > 0) {\n callbacks?.onLog?.(` ā Errors: ${result.errors}`);\n }\n }\n \n totalCreated += result.created;\n totalUpdated += result.updated;\n totalUnchanged += result.unchanged;\n totalErrors += result.errors;\n }\n \n // Commit transaction if successful\n if (!options.dryRun && totalErrors === 0) {\n await transactionManager.commitTransaction();\n }\n } catch (error) {\n // Rollback transaction on error\n if (!options.dryRun) {\n callbacks?.onError?.('\\nā ļø Rolling back database transaction due to error...');\n await transactionManager.rollbackTransaction();\n callbacks?.onError?.('ā Database transaction rolled back successfully');\n }\n throw error;\n }\n \n // Commit file backups if successful and not in dry-run mode\n if (!options.dryRun && totalErrors === 0) {\n await fileBackupManager.cleanup();\n if (options.verbose) {\n callbacks?.onLog?.('ā
File backups committed');\n }\n }\n \n // Close SQL logging session if it was created\n let sqlLogPath: string | undefined;\n if (sqlLoggingSession) {\n sqlLogPath = sqlLoggingSession.filePath;\n await sqlLoggingSession.dispose();\n if (options.verbose) {\n callbacks?.onLog?.(`š SQL log written to: ${sqlLogPath}`);\n }\n }\n \n return {\n created: totalCreated,\n updated: totalUpdated,\n unchanged: totalUnchanged,\n errors: totalErrors,\n warnings: this.warnings,\n sqlLogPath\n };\n \n } catch (error) {\n // Rollback file backups on error\n if (!options.dryRun) {\n try {\n await fileBackupManager.rollback();\n callbacks?.onWarn?.('File backups rolled back due to error');\n } catch (rollbackError) {\n callbacks?.onWarn?.(`Failed to rollback file backups: ${rollbackError}`);\n }\n }\n \n // Close SQL logging session on error\n if (sqlLoggingSession) {\n try {\n await sqlLoggingSession.dispose();\n } catch (disposeError) {\n callbacks?.onWarn?.(`Failed to close SQL logging session: ${disposeError}`);\n }\n }\n \n throw error;\n }\n }\n \n private async processEntityDirectory(\n entityDir: string,\n entityConfig: any,\n options: PushOptions,\n fileBackupManager: FileBackupManager,\n callbacks?: PushCallbacks\n ): Promise<EntityPushResult> {\n let created = 0;\n let updated = 0;\n let unchanged = 0;\n let errors = 0;\n \n // Find all JSON files in the directory\n const pattern = entityConfig.filePattern || '*.json';\n const files = await fastGlob(pattern, {\n cwd: entityDir,\n absolute: true,\n onlyFiles: true,\n dot: true,\n ignore: ['**/node_modules/**', '**/.mj-*.json']\n });\n \n if (options.verbose) {\n callbacks?.onLog?.(`Found ${files.length} files to process`);\n }\n \n // Process each file\n for (const filePath of files) {\n try {\n // Backup the file before any modifications (unless dry-run)\n if (!options.dryRun) {\n await fileBackupManager.backupFile(filePath);\n }\n \n // Read the raw file data first\n const rawFileData = await fs.readJson(filePath);\n \n // Only preprocess if there are @include directives\n let fileData = rawFileData;\n const jsonString = JSON.stringify(rawFileData);\n const hasIncludes = jsonString.includes('\"@include\"') || jsonString.includes('\"@include.');\n \n if (hasIncludes) {\n // Preprocess the JSON file to handle @include directives\n // Create a new preprocessor instance for each file to ensure clean state\n const jsonPreprocessor = new JsonPreprocessor();\n fileData = await jsonPreprocessor.processFile(filePath);\n }\n \n const records = Array.isArray(fileData) ? fileData : [fileData];\n const isArray = Array.isArray(fileData);\n \n // Analyze dependencies and get sorted records\n const analyzer = new RecordDependencyAnalyzer();\n const analysisResult = await analyzer.analyzeFileRecords(records, entityConfig.entity);\n \n if (analysisResult.circularDependencies.length > 0) {\n callbacks?.onWarn?.(`ā ļø Circular dependencies detected in ${filePath}`);\n for (const cycle of analysisResult.circularDependencies) {\n callbacks?.onWarn?.(` Cycle: ${cycle.join(' ā ')}`);\n }\n }\n \n if (options.verbose) {\n callbacks?.onLog?.(` Analyzed ${analysisResult.sortedRecords.length} records (including nested)`);\n }\n \n // Create batch context for in-memory entity resolution\n // Note: While JavaScript is single-threaded, async operations can interleave.\n // Map operations themselves are atomic, but we ensure records are added to\n // the context AFTER successful save to maintain consistency.\n const batchContext = new Map<string, BaseEntity>();\n \n // Process records using dependency levels for parallel processing\n if (analysisResult.dependencyLevels && analysisResult.dependencyLevels.length > 0) {\n // Use parallel processing with dependency levels\n for (let levelIndex = 0; levelIndex < analysisResult.dependencyLevels.length; levelIndex++) {\n const level = analysisResult.dependencyLevels[levelIndex];\n \n if (options.verbose && level.length > 1) {\n callbacks?.onLog?.(` Processing dependency level ${levelIndex} with ${level.length} records in parallel...`);\n }\n \n // Process records in this level in parallel batches\n const batchSize = options.parallelBatchSize || PARALLEL_BATCH_SIZE;\n for (let i = 0; i < level.length; i += batchSize) {\n const batch = level.slice(i, Math.min(i + batchSize, level.length));\n \n // Process batch in parallel\n const batchResults = await Promise.all(\n batch.map(async (flattenedRecord) => {\n try {\n const result = await this.processFlattenedRecord(\n flattenedRecord,\n entityDir,\n options,\n batchContext,\n callbacks\n );\n return { success: true, result };\n } catch (error) {\n // Return error instead of throwing to handle after Promise.all\n return { success: false, error, record: flattenedRecord };\n }\n })\n );\n \n // Process results and check for errors\n for (const batchResult of batchResults) {\n if (!batchResult.success) {\n // Fail fast on first error with detailed logging\n const err = batchResult.error as Error;\n const rec = batchResult.record as FlattenedRecord;\n \n callbacks?.onError?.(`\\nā BATCH PROCESSING FAILED`);\n callbacks?.onError?.(` Processing halted at dependency level ${levelIndex}`);\n callbacks?.onError?.(` Failed record: ${rec.entityName} at ${rec.path}`);\n callbacks?.onError?.(` Error: ${err.message}`);\n callbacks?.onError?.(` Records in this batch: ${batch.length}`);\n callbacks?.onError?.(` Records successfully processed before failure: ${batchResults.filter(r => r.success).length}`);\n \n // The error has already been logged in detail by processFlattenedRecord\n // Now throw to trigger rollback\n throw new Error(`Batch processing failed: ${err.message}`);\n }\n \n // Update stats for successful results\n const result = batchResult.result!;\n if (!result.isDuplicate) {\n if (result.status === 'created') created++;\n else if (result.status === 'updated') updated++;\n else if (result.status === 'unchanged') unchanged++;\n }\n }\n }\n }\n } else {\n // Fallback to sequential processing if no dependency levels available\n for (const flattenedRecord of analysisResult.sortedRecords) {\n try {\n const result = await this.processFlattenedRecord(\n flattenedRecord,\n entityDir,\n options,\n batchContext,\n callbacks\n );\n \n // Update stats\n if (!result.isDuplicate) {\n if (result.status === 'created') created++;\n else if (result.status === 'updated') updated++;\n else if (result.status === 'unchanged') unchanged++;\n }\n } catch (recordError) {\n const errorMsg = `Error processing ${flattenedRecord.entityName} record at ${flattenedRecord.path}: ${recordError}`;\n callbacks?.onError?.(errorMsg);\n errors++;\n }\n }\n }\n \n // Write back to file (handles both single records and arrays)\n if (!options.dryRun) {\n if (isArray) {\n await JsonWriteHelper.writeOrderedRecordData(filePath, records);\n } else {\n // For single record files, write back the single record\n await JsonWriteHelper.writeOrderedRecordData(filePath, records[0]);\n }\n }\n } catch (fileError) {\n const errorMsg = `Error reading file ${filePath}: ${fileError}`;\n callbacks?.onError?.(errorMsg);\n errors++;\n }\n }\n \n return { created, updated, unchanged, errors };\n }\n \n private async processFlattenedRecord(\n flattenedRecord: FlattenedRecord,\n entityDir: string,\n options: PushOptions,\n batchContext: Map<string, BaseEntity>,\n callbacks?: PushCallbacks\n ): Promise<{ status: 'created' | 'updated' | 'unchanged' | 'error'; isDuplicate?: boolean }> {\n const metadata = new Metadata();\n const { record, entityName, parentContext, id: recordId } = flattenedRecord;\n \n // Use the unique record ID from the flattened record for batch context\n // This ensures we can properly find parent entities even when they're new\n const lookupKey = recordId;\n \n // Check if already in batch context\n let entity = batchContext.get(lookupKey);\n if (entity) {\n // Already processed\n return { status: 'unchanged', isDuplicate: true };\n }\n \n // Get or create entity instance\n entity = await metadata.GetEntityObject(entityName, this.contextUser);\n if (!entity) {\n throw new Error(`Failed to create entity object for ${entityName}`);\n }\n \n // Check if record exists\n const primaryKey = record.primaryKey;\n let exists = false;\n let isNew = false;\n \n if (primaryKey && Object.keys(primaryKey).length > 0) {\n // First check if the record exists using the sync engine's loadEntity method\n // This avoids the \"Error in BaseEntity.Load\" message for missing records\n const existingEntity = await this.syncEngine.loadEntity(entityName, primaryKey);\n \n if (existingEntity) {\n // Record exists, use the loaded entity\n entity = existingEntity;\n exists = true;\n } else {\n // Record doesn't exist in database\n const autoCreate = this.syncConfig?.push?.autoCreateMissingRecords ?? false;\n const pkDisplay = Object.entries(primaryKey)\n .map(([key, value]) => `${key}=${value}`)\n .join(', ');\n \n if (!autoCreate) {\n const warning = `Record not found: ${entityName} with primaryKey {${pkDisplay}}. To auto-create missing records, set push.autoCreateMissingRecords=true in .mj-sync.json`;\n this.warnings.push(warning);\n callbacks?.onWarn?.(warning);\n return { status: 'error' };\n } else {\n // Log that we're creating the missing record\n if (options.verbose) {\n callbacks?.onLog?.(`š Creating missing ${entityName} record with primaryKey {${pkDisplay}}`);\n }\n }\n }\n }\n \n if (!exists) {\n entity.NewRecord();\n isNew = true;\n \n // Set primary key values for new records if provided\n if (primaryKey) {\n for (const [pkField, pkValue] of Object.entries(primaryKey)) {\n entity.Set(pkField, pkValue);\n }\n }\n }\n \n // Store original field values to preserve @ references\n const originalFields = { ...record.fields };\n \n // Get parent entity from context if available\n let parentEntity: BaseEntity | null = null;\n if (parentContext) {\n // Find the parent's flattened record ID\n // The parent record was flattened before this child, so it should have a lower ID number\n const parentRecordId = flattenedRecord.dependencies.values().next().value;\n if (parentRecordId) {\n parentEntity = batchContext.get(parentRecordId) || null;\n }\n \n if (!parentEntity) {\n // Parent should have been processed before child due to dependency ordering\n throw new Error(`Parent entity not found in batch context for ${entityName}. Parent dependencies: ${Array.from(flattenedRecord.dependencies).join(', ')}`);\n }\n }\n \n // Process field values with parent context and batch context\n for (const [fieldName, fieldValue] of Object.entries(record.fields)) {\n const processedValue = await this.syncEngine.processFieldValue(\n fieldValue,\n entityDir,\n parentEntity,\n null, // rootRecord\n 0,\n batchContext // Pass batch context for lookups\n );\n entity.Set(fieldName, processedValue);\n }\n \n // Check if the record is actually dirty before considering it changed\n let isDirty = entity.Dirty;\n \n // Also check if file content has changed (for @file references)\n if (!isDirty && !isNew && record.sync) {\n const currentChecksum = await this.syncEngine.calculateChecksumWithFileContent(originalFields, entityDir);\n if (currentChecksum !== record.sync.checksum) {\n isDirty = true;\n if (options.verbose) {\n callbacks?.onLog?.(`š File content changed for ${entityName} record (checksum mismatch)`);\n }\n }\n }\n \n if (options.dryRun) {\n if (exists) {\n callbacks?.onLog?.(`[DRY RUN] Would update ${entityName} record`);\n return { status: 'updated' };\n } else {\n callbacks?.onLog?.(`[DRY RUN] Would create ${entityName} record`);\n return { status: 'created' };\n }\n }\n \n // If updating an existing record that's dirty, show what changed\n if (!isNew && isDirty) {\n const changes = entity.GetChangesSinceLastSave();\n const changeKeys = Object.keys(changes);\n if (changeKeys.length > 0) {\n // Get primary key info for display\n const entityInfo = this.syncEngine.getEntityInfo(entityName);\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 ${entityName} 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}: ${this.formatFieldValue(oldValue)} ā ${this.formatFieldValue(newValue)}`);\n }\n }\n }\n \n // Save the record with detailed error logging\n const saveResult = await entity.Save();\n if (!saveResult) {\n // Build detailed error information\n const entityInfo = this.syncEngine.getEntityInfo(entityName);\n const primaryKeyInfo: string[] = [];\n const fieldInfo: string[] = [];\n \n // Collect primary key information\n if (entityInfo) {\n for (const pk of entityInfo.PrimaryKeys) {\n const pkValue = entity.Get(pk.Name);\n primaryKeyInfo.push(`${pk.Name}=${this.formatFieldValue(pkValue)}`);\n }\n }\n \n // Collect field values that were being saved\n for (const [fieldName, fieldValue] of Object.entries(record.fields)) {\n const processedValue = entity.Get(fieldName);\n fieldInfo.push(`${fieldName}=${this.formatFieldValue(processedValue)}`);\n }\n \n // Get the actual error details from the entity\n const errorMessage = entity.LatestResult?.Message || 'Unknown error';\n const errorDetails = entity.LatestResult?.Errors?.map(err => \n typeof err === 'string' ? err : (err?.message || JSON.stringify(err))\n )?.join(', ') || '';\n \n // Log detailed error information\n callbacks?.onError?.(`\\nā FATAL ERROR: Failed to save ${entityName} record`);\n callbacks?.onError?.(` Entity: ${entityName}`);\n if (primaryKeyInfo.length > 0) {\n callbacks?.onError?.(` Primary Key: {${primaryKeyInfo.join(', ')}}`);\n }\n callbacks?.onError?.(` Record Path: ${flattenedRecord.path}`);\n callbacks?.onError?.(` Is New Record: ${isNew}`);\n callbacks?.onError?.(` Field Values Being Saved:`);\n for (const field of fieldInfo) {\n callbacks?.onError?.(` - ${field}`);\n }\n callbacks?.onError?.(` SQL Error: ${errorMessage}`);\n if (errorDetails) {\n callbacks?.onError?.(` Additional Details: ${errorDetails}`);\n }\n \n // Check for common issues\n if (errorMessage.includes('conversion failed') || errorMessage.includes('GUID')) {\n callbacks?.onError?.(` ā ļø This appears to be a GUID/UUID format error. Check that all ID fields contain valid GUIDs.`);\n }\n if (errorMessage.includes('transaction')) {\n callbacks?.onError?.(` ā ļø Transaction error detected. The database transaction may be corrupted.`);\n }\n \n // Throw error to trigger rollback and stop processing\n throw new Error(`Failed to save ${entityName} record at ${flattenedRecord.path}: ${errorMessage}`);\n }\n \n // Add to batch context AFTER save so it has an ID for child @parent:ID references\n // Use the recordId (lookupKey) as the key so child records can find this parent\n batchContext.set(lookupKey, entity);\n \n // Update primaryKey for new records\n if (isNew) {\n const entityInfo = this.syncEngine.getEntityInfo(entityName);\n if (entityInfo) {\n const newPrimaryKey: Record<string, any> = {};\n for (const pk of entityInfo.PrimaryKeys) {\n newPrimaryKey[pk.Name] = entity.Get(pk.Name);\n }\n record.primaryKey = newPrimaryKey;\n }\n }\n \n // Only update sync metadata if the record was actually dirty (changed)\n if (isNew || isDirty) {\n record.sync = {\n lastModified: new Date().toISOString(),\n checksum: await this.syncEngine.calculateChecksumWithFileContent(originalFields, entityDir)\n };\n if (options.verbose) {\n callbacks?.onLog?.(` ā Updated sync metadata (record was ${isNew ? 'new' : 'changed'})`);\n }\n } else if (options.verbose) {\n callbacks?.onLog?.(` - Skipped sync metadata update (no changes detected)`);\n }\n \n // Restore original field values to preserve @ references\n record.fields = originalFields;\n \n return { \n status: isNew ? 'created' : (isDirty ? 'updated' : 'unchanged'),\n isDuplicate: false\n };\n }\n \n private formatFieldValue(value: any): string {\n if (value === null || value === undefined) return 'null';\n if (typeof value === 'string') {\n // Truncate long strings and show quotes\n if (value.length > 50) {\n return `\"${value.substring(0, 47)}...\"`;\n }\n return `\"${value}\"`;\n }\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n return String(value);\n }\n \n private buildBatchContextKey(entityName: string, record: RecordData): string {\n // Build a unique key for the batch context based on entity name and identifying fields\n const keyParts = [entityName];\n \n // Use primary key if available\n if (record.primaryKey) {\n for (const [field, value] of Object.entries(record.primaryKey)) {\n keyParts.push(`${field}=${value}`);\n }\n } else {\n // Use a combination of important fields as fallback\n const identifyingFields = ['Name', 'ID', 'Code', 'Email'];\n for (const field of identifyingFields) {\n if (record.fields[field]) {\n keyParts.push(`${field}=${record.fields[field]}`);\n }\n }\n }\n \n return keyParts.join('|');\n }\n \n private findEntityDirectories(baseDir: string, specificDir?: string, directoryOrder?: string[]): string[] {\n const dirs: string[] = [];\n \n if (specificDir) {\n // Process specific directory\n const fullPath = path.resolve(baseDir, specificDir);\n if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {\n // Check if this directory has an entity configuration\n const configPath = path.join(fullPath, '.mj-sync.json');\n if (fs.existsSync(configPath)) {\n try {\n const config = fs.readJsonSync(configPath);\n if (config.entity) {\n // It's an entity directory, add it\n dirs.push(fullPath);\n } else {\n // It's a container directory, search its subdirectories\n this.findEntityDirectoriesRecursive(fullPath, dirs);\n }\n } catch {\n // Invalid config, skip\n }\n }\n }\n } else {\n // Find all entity directories\n this.findEntityDirectoriesRecursive(baseDir, dirs);\n }\n \n // Apply directory ordering if specified\n if (directoryOrder && directoryOrder.length > 0 && !specificDir) {\n // Create a map of directory name to order index\n const orderMap = new Map<string, number>();\n directoryOrder.forEach((dir, index) => {\n orderMap.set(dir, index);\n });\n \n // Sort directories based on the order map\n dirs.sort((a, b) => {\n const nameA = path.basename(a);\n const nameB = path.basename(b);\n const orderA = orderMap.get(nameA) ?? Number.MAX_SAFE_INTEGER;\n const orderB = orderMap.get(nameB) ?? Number.MAX_SAFE_INTEGER;\n \n // If both have specified orders, use them\n if (orderA !== Number.MAX_SAFE_INTEGER || orderB !== Number.MAX_SAFE_INTEGER) {\n return orderA - orderB;\n }\n \n // Otherwise, maintain original order (stable sort)\n return 0;\n });\n }\n \n return dirs;\n }\n\n private findEntityDirectoriesRecursive(dir: string, dirs: string[]): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n \n for (const entry of entries) {\n if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {\n const fullPath = path.join(dir, entry.name);\n const configPath = path.join(fullPath, '.mj-sync.json');\n \n if (fs.existsSync(configPath)) {\n try {\n const config = fs.readJsonSync(configPath);\n if (config.entity) {\n dirs.push(fullPath);\n }\n } catch {\n // Skip invalid config files\n }\n } else {\n // Recurse into subdirectories\n this.findEntityDirectoriesRecursive(fullPath, dirs);\n }\n }\n }\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"PushService.js","sourceRoot":"","sources":["../../src/services/PushService.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs-extra';\nimport path from 'path';\nimport fastGlob from 'fast-glob';\nimport { BaseEntity, Metadata, UserInfo } from '@memberjunction/core';\nimport { SyncEngine, RecordData } from '../lib/sync-engine';\nimport { loadEntityConfig, loadSyncConfig } from '../config';\nimport { FileBackupManager } from '../lib/file-backup-manager';\nimport { configManager } from '../lib/config-manager';\nimport { SQLLogger } from '../lib/sql-logger';\nimport { TransactionManager } from '../lib/transaction-manager';\nimport { JsonWriteHelper } from '../lib/json-write-helper';\nimport { RecordDependencyAnalyzer, FlattenedRecord } from '../lib/record-dependency-analyzer';\nimport { JsonPreprocessor } from '../lib/json-preprocessor';\nimport type { SqlLoggingSession, SQLServerDataProvider } from '@memberjunction/sqlserver-dataprovider';\n\n// Configuration for parallel processing\nconst PARALLEL_BATCH_SIZE = 1; // Number of records to process in parallel at each dependency level\n/// TEMPORARILY DISABLED PARALLEL BY SETTING TO 1 as we were having some issues\n\nexport interface PushOptions {\n dir?: string;\n dryRun?: boolean;\n verbose?: boolean;\n noValidate?: boolean;\n parallelBatchSize?: number; // Number of records to process in parallel (default: 10)\n}\n\nexport interface PushCallbacks {\n onProgress?: (message: string) => void;\n onSuccess?: (message: string) => void;\n onError?: (message: string) => void;\n onWarn?: (message: string) => void;\n onLog?: (message: string) => void;\n onConfirm?: (message: string) => Promise<boolean>;\n}\n\nexport interface PushResult {\n created: number;\n updated: number;\n unchanged: number;\n errors: number;\n warnings: string[];\n sqlLogPath?: string;\n}\n\nexport interface EntityPushResult {\n created: number;\n updated: number;\n unchanged: number;\n errors: number;\n}\n\nexport class PushService {\n private syncEngine: SyncEngine;\n private contextUser: UserInfo;\n private warnings: string[] = [];\n private syncConfig: any;\n \n constructor(syncEngine: SyncEngine, contextUser: UserInfo) {\n this.syncEngine = syncEngine;\n this.contextUser = contextUser;\n }\n \n async push(options: PushOptions, callbacks?: PushCallbacks): Promise<PushResult> {\n this.warnings = [];\n \n const fileBackupManager = new FileBackupManager();\n \n // Load sync config for SQL logging settings and autoCreateMissingRecords flag\n // If dir option is specified, load from that directory, otherwise use original CWD\n const configDir = options.dir ? path.resolve(configManager.getOriginalCwd(), options.dir) : configManager.getOriginalCwd();\n this.syncConfig = await loadSyncConfig(configDir);\n \n if (options.verbose) {\n callbacks?.onLog?.(`Original working directory: ${configManager.getOriginalCwd()}`);\n callbacks?.onLog?.(`Config directory (with dir option): ${configDir}`);\n callbacks?.onLog?.(`Config file path: ${path.join(configDir, '.mj-sync.json')}`);\n callbacks?.onLog?.(`Full sync config loaded: ${JSON.stringify(this.syncConfig, null, 2)}`);\n callbacks?.onLog?.(`SQL logging config: ${JSON.stringify(this.syncConfig?.sqlLogging)}`);\n }\n \n const sqlLogger = new SQLLogger(this.syncConfig);\n const transactionManager = new TransactionManager(sqlLogger);\n \n if (options.verbose) {\n callbacks?.onLog?.(`SQLLogger enabled status: ${sqlLogger.enabled}`);\n }\n \n // Setup SQL logging session with the provider if enabled\n let sqlLoggingSession: SqlLoggingSession | null = null;\n \n try {\n // Initialize SQL logger if enabled and not dry-run\n if (sqlLogger.enabled && !options.dryRun) {\n const provider = Metadata.Provider as SQLServerDataProvider;\n \n if (options.verbose) {\n callbacks?.onLog?.(`SQL logging enabled: ${sqlLogger.enabled}`);\n callbacks?.onLog?.(`Provider type: ${provider?.constructor?.name || 'Unknown'}`);\n callbacks?.onLog?.(`Has CreateSqlLogger: ${typeof provider?.CreateSqlLogger === 'function'}`);\n }\n \n if (provider && typeof provider.CreateSqlLogger === 'function') {\n // Generate filename with timestamp\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = this.syncConfig.sqlLogging?.formatAsMigration \n ? `MetadataSync_Push_${timestamp}.sql`\n : `push_${timestamp}.sql`;\n \n // Use .sql-log-push directory in the config directory (where sync was initiated)\n const outputDir = path.join(configDir, this.syncConfig?.sqlLogging?.outputDirectory || './sql-log-push');\n const filepath = path.join(outputDir, filename);\n \n // Ensure the directory exists\n await fs.ensureDir(path.dirname(filepath));\n \n // Create the SQL logging session\n sqlLoggingSession = await provider.CreateSqlLogger(filepath, {\n formatAsMigration: this.syncConfig.sqlLogging?.formatAsMigration || false,\n description: 'MetadataSync push operation',\n statementTypes: \"mutations\",\n prettyPrint: true,\n filterPatterns: this.syncConfig.sqlLogging?.filterPatterns,\n filterType: this.syncConfig.sqlLogging?.filterType,\n });\n \n if (options.verbose) {\n callbacks?.onLog?.(`š SQL logging enabled: ${filepath}`);\n }\n } else {\n if (options.verbose) {\n callbacks?.onWarn?.('SQL logging requested but provider does not support it');\n }\n }\n }\n \n // Find entity directories to process\n // Note: If options.dir is specified, configDir already points to that directory\n // So we don't need to pass it as specificDir\n const entityDirs = this.findEntityDirectories(configDir, undefined, this.syncConfig?.directoryOrder);\n \n if (entityDirs.length === 0) {\n throw new Error('No entity directories found');\n }\n \n if (options.verbose) {\n callbacks?.onLog?.(`Found ${entityDirs.length} entity ${entityDirs.length === 1 ? 'directory' : 'directories'} to process`);\n }\n \n // Initialize file backup manager (unless in dry-run mode)\n if (!options.dryRun) {\n await fileBackupManager.initialize();\n if (options.verbose) {\n callbacks?.onLog?.('š File backup manager initialized');\n }\n }\n \n // Process each entity directory\n let totalCreated = 0;\n let totalUpdated = 0;\n let totalUnchanged = 0;\n let totalErrors = 0;\n \n // Begin transaction if not in dry-run mode\n if (!options.dryRun) {\n await transactionManager.beginTransaction();\n }\n \n try {\n for (const entityDir of entityDirs) {\n const entityConfig = await loadEntityConfig(entityDir);\n if (!entityConfig) {\n const warning = `Skipping ${entityDir} - no valid entity configuration`;\n this.warnings.push(warning);\n callbacks?.onWarn?.(warning);\n continue;\n }\n \n // Show folder with spinner at start\n const dirName = path.relative(process.cwd(), entityDir) || '.';\n callbacks?.onLog?.(`\\nš ${dirName}:`);\n \n // Use onProgress for animated spinner if available\n if (callbacks?.onProgress) {\n callbacks.onProgress(`Processing ${dirName}...`);\n } else {\n callbacks?.onLog?.(` ā³ Processing...`);\n }\n \n if (options.verbose && callbacks?.onLog) {\n callbacks.onLog(`Processing ${entityConfig.entity} in ${entityDir}`);\n }\n \n const result = await this.processEntityDirectory(\n entityDir,\n entityConfig,\n options,\n fileBackupManager,\n callbacks\n );\n \n // Stop the spinner if we were using onProgress\n if (callbacks?.onProgress && callbacks?.onSuccess) {\n callbacks.onSuccess(`Processed ${dirName}`);\n }\n \n // Show per-directory summary\n const dirTotal = result.created + result.updated + result.unchanged;\n if (dirTotal > 0 || result.errors > 0) {\n callbacks?.onLog?.(` Total processed: ${dirTotal} unique records`);\n if (result.created > 0) {\n callbacks?.onLog?.(` ā Created: ${result.created}`);\n }\n if (result.updated > 0) {\n callbacks?.onLog?.(` ā Updated: ${result.updated}`);\n }\n if (result.unchanged > 0) {\n callbacks?.onLog?.(` - Unchanged: ${result.unchanged}`);\n }\n if (result.errors > 0) {\n callbacks?.onLog?.(` ā Errors: ${result.errors}`);\n }\n }\n \n totalCreated += result.created;\n totalUpdated += result.updated;\n totalUnchanged += result.unchanged;\n totalErrors += result.errors;\n }\n \n // Commit transaction if successful\n if (!options.dryRun && totalErrors === 0) {\n await transactionManager.commitTransaction();\n }\n } catch (error) {\n // Rollback transaction on error\n if (!options.dryRun) {\n callbacks?.onError?.('\\nā ļø Rolling back database transaction due to error...');\n await transactionManager.rollbackTransaction();\n callbacks?.onError?.('ā Database transaction rolled back successfully');\n }\n throw error;\n }\n \n // Commit file backups if successful and not in dry-run mode\n if (!options.dryRun && totalErrors === 0) {\n await fileBackupManager.cleanup();\n if (options.verbose) {\n callbacks?.onLog?.('ā
File backups committed');\n }\n }\n \n // Close SQL logging session if it was created\n let sqlLogPath: string | undefined;\n if (sqlLoggingSession) {\n sqlLogPath = sqlLoggingSession.filePath;\n await sqlLoggingSession.dispose();\n if (options.verbose) {\n callbacks?.onLog?.(`š SQL log written to: ${sqlLogPath}`);\n }\n }\n \n return {\n created: totalCreated,\n updated: totalUpdated,\n unchanged: totalUnchanged,\n errors: totalErrors,\n warnings: this.warnings,\n sqlLogPath\n };\n \n } catch (error) {\n // Rollback file backups on error\n if (!options.dryRun) {\n try {\n await fileBackupManager.rollback();\n callbacks?.onWarn?.('File backups rolled back due to error');\n } catch (rollbackError) {\n callbacks?.onWarn?.(`Failed to rollback file backups: ${rollbackError}`);\n }\n }\n \n // Close SQL logging session on error\n if (sqlLoggingSession) {\n try {\n await sqlLoggingSession.dispose();\n } catch (disposeError) {\n callbacks?.onWarn?.(`Failed to close SQL logging session: ${disposeError}`);\n }\n }\n \n throw error;\n }\n }\n \n private async processEntityDirectory(\n entityDir: string,\n entityConfig: any,\n options: PushOptions,\n fileBackupManager: FileBackupManager,\n callbacks?: PushCallbacks\n ): Promise<EntityPushResult> {\n let created = 0;\n let updated = 0;\n let unchanged = 0;\n let errors = 0;\n \n // Find all JSON files in the directory\n const pattern = entityConfig.filePattern || '*.json';\n const files = await fastGlob(pattern, {\n cwd: entityDir,\n absolute: true,\n onlyFiles: true,\n dot: true,\n ignore: ['**/node_modules/**', '**/.mj-*.json']\n });\n \n if (options.verbose) {\n callbacks?.onLog?.(`Found ${files.length} files to process`);\n }\n \n // Process each file\n for (const filePath of files) {\n try {\n // Backup the file before any modifications (unless dry-run)\n if (!options.dryRun) {\n await fileBackupManager.backupFile(filePath);\n }\n \n // Read the raw file data first\n const rawFileData = await fs.readJson(filePath);\n \n // Only preprocess if there are @include directives\n let fileData = rawFileData;\n const jsonString = JSON.stringify(rawFileData);\n const hasIncludes = jsonString.includes('\"@include\"') || jsonString.includes('\"@include.');\n \n if (hasIncludes) {\n // Preprocess the JSON file to handle @include directives\n // Create a new preprocessor instance for each file to ensure clean state\n const jsonPreprocessor = new JsonPreprocessor();\n fileData = await jsonPreprocessor.processFile(filePath);\n }\n \n const records = Array.isArray(fileData) ? fileData : [fileData];\n const isArray = Array.isArray(fileData);\n \n // Analyze dependencies and get sorted records\n const analyzer = new RecordDependencyAnalyzer();\n const analysisResult = await analyzer.analyzeFileRecords(records, entityConfig.entity);\n \n if (analysisResult.circularDependencies.length > 0) {\n callbacks?.onWarn?.(`ā ļø Circular dependencies detected in ${filePath}`);\n for (const cycle of analysisResult.circularDependencies) {\n callbacks?.onWarn?.(` Cycle: ${cycle.join(' ā ')}`);\n }\n }\n \n if (options.verbose) {\n callbacks?.onLog?.(` Analyzed ${analysisResult.sortedRecords.length} records (including nested)`);\n }\n \n // Create batch context for in-memory entity resolution\n // Note: While JavaScript is single-threaded, async operations can interleave.\n // Map operations themselves are atomic, but we ensure records are added to\n // the context AFTER successful save to maintain consistency.\n const batchContext = new Map<string, BaseEntity>();\n \n // Process records using dependency levels for parallel processing\n if (analysisResult.dependencyLevels && analysisResult.dependencyLevels.length > 0) {\n // Use parallel processing with dependency levels\n for (let levelIndex = 0; levelIndex < analysisResult.dependencyLevels.length; levelIndex++) {\n const level = analysisResult.dependencyLevels[levelIndex];\n \n if (options.verbose && level.length > 1) {\n callbacks?.onLog?.(` Processing dependency level ${levelIndex} with ${level.length} records in parallel...`);\n }\n \n // Process records in this level in parallel batches\n const batchSize = options.parallelBatchSize || PARALLEL_BATCH_SIZE;\n for (let i = 0; i < level.length; i += batchSize) {\n const batch = level.slice(i, Math.min(i + batchSize, level.length));\n \n // Process batch in parallel\n const batchResults = await Promise.all(\n batch.map(async (flattenedRecord) => {\n try {\n const result = await this.processFlattenedRecord(\n flattenedRecord,\n entityDir,\n options,\n batchContext,\n callbacks\n );\n return { success: true, result };\n } catch (error) {\n // Return error instead of throwing to handle after Promise.all\n return { success: false, error, record: flattenedRecord };\n }\n })\n );\n \n // Process results and check for errors\n for (const batchResult of batchResults) {\n if (!batchResult.success) {\n // Fail fast on first error with detailed logging\n const err = batchResult.error as Error;\n const rec = batchResult.record as FlattenedRecord;\n \n callbacks?.onError?.(`\\nā BATCH PROCESSING FAILED`);\n callbacks?.onError?.(` Processing halted at dependency level ${levelIndex}`);\n callbacks?.onError?.(` Failed record: ${rec.entityName} at ${rec.path}`);\n callbacks?.onError?.(` Error: ${err.message}`);\n callbacks?.onError?.(` Records in this batch: ${batch.length}`);\n callbacks?.onError?.(` Records successfully processed before failure: ${batchResults.filter(r => r.success).length}`);\n \n // The error has already been logged in detail by processFlattenedRecord\n // Now throw to trigger rollback\n throw new Error(`Batch processing failed: ${err.message}`);\n }\n \n // Update stats for successful results\n const result = batchResult.result!;\n if (!result.isDuplicate) {\n if (result.status === 'created') created++;\n else if (result.status === 'updated') updated++;\n else if (result.status === 'unchanged') unchanged++;\n }\n }\n }\n }\n } else {\n // Fallback to sequential processing if no dependency levels available\n for (const flattenedRecord of analysisResult.sortedRecords) {\n try {\n const result = await this.processFlattenedRecord(\n flattenedRecord,\n entityDir,\n options,\n batchContext,\n callbacks\n );\n \n // Update stats\n if (!result.isDuplicate) {\n if (result.status === 'created') created++;\n else if (result.status === 'updated') updated++;\n else if (result.status === 'unchanged') unchanged++;\n }\n } catch (recordError) {\n const errorMsg = `Error processing ${flattenedRecord.entityName} record at ${flattenedRecord.path}: ${recordError}`;\n callbacks?.onError?.(errorMsg);\n errors++;\n }\n }\n }\n \n // Write back to file (handles both single records and arrays)\n if (!options.dryRun) {\n if (isArray) {\n await JsonWriteHelper.writeOrderedRecordData(filePath, records);\n } else {\n // For single record files, write back the single record\n await JsonWriteHelper.writeOrderedRecordData(filePath, records[0]);\n }\n }\n } catch (fileError) {\n const errorMsg = `Error reading file ${filePath}: ${fileError}`;\n callbacks?.onError?.(errorMsg);\n errors++;\n }\n }\n \n return { created, updated, unchanged, errors };\n }\n \n private async processFlattenedRecord(\n flattenedRecord: FlattenedRecord,\n entityDir: string,\n options: PushOptions,\n batchContext: Map<string, BaseEntity>,\n callbacks?: PushCallbacks\n ): Promise<{ status: 'created' | 'updated' | 'unchanged' | 'error'; isDuplicate?: boolean }> {\n const metadata = new Metadata();\n const { record, entityName, parentContext, id: recordId } = flattenedRecord;\n \n // Use the unique record ID from the flattened record for batch context\n // This ensures we can properly find parent entities even when they're new\n const lookupKey = recordId;\n \n // Check if already in batch context\n let entity = batchContext.get(lookupKey);\n if (entity) {\n // Already processed\n return { status: 'unchanged', isDuplicate: true };\n }\n \n // Get or create entity instance\n entity = await metadata.GetEntityObject(entityName, this.contextUser);\n if (!entity) {\n throw new Error(`Failed to create entity object for ${entityName}`);\n }\n \n // Check if record exists\n const primaryKey = record.primaryKey;\n let exists = false;\n let isNew = false;\n \n if (primaryKey && Object.keys(primaryKey).length > 0) {\n // First check if the record exists using the sync engine's loadEntity method\n // This avoids the \"Error in BaseEntity.Load\" message for missing records\n const existingEntity = await this.syncEngine.loadEntity(entityName, primaryKey);\n \n if (existingEntity) {\n // Record exists, use the loaded entity\n entity = existingEntity;\n exists = true;\n } else {\n // Record doesn't exist in database\n const autoCreate = this.syncConfig?.push?.autoCreateMissingRecords ?? false;\n const pkDisplay = Object.entries(primaryKey)\n .map(([key, value]) => `${key}=${value}`)\n .join(', ');\n \n if (!autoCreate) {\n const warning = `Record not found: ${entityName} with primaryKey {${pkDisplay}}. To auto-create missing records, set push.autoCreateMissingRecords=true in .mj-sync.json`;\n this.warnings.push(warning);\n callbacks?.onWarn?.(warning);\n return { status: 'error' };\n } else {\n // Log that we're creating the missing record\n if (options.verbose) {\n callbacks?.onLog?.(`š Creating missing ${entityName} record with primaryKey {${pkDisplay}}`);\n }\n }\n }\n }\n \n if (!exists) {\n entity.NewRecord();\n isNew = true;\n \n // Set primary key values for new records if provided\n if (primaryKey) {\n for (const [pkField, pkValue] of Object.entries(primaryKey)) {\n entity.Set(pkField, pkValue);\n }\n }\n }\n \n // Store original field values to preserve @ references\n const originalFields = { ...record.fields };\n \n // Get parent entity from context if available\n let parentEntity: BaseEntity | null = null;\n if (parentContext) {\n // Find the parent's flattened record ID\n // The parent record was flattened before this child, so it should have a lower ID number\n const parentRecordId = flattenedRecord.dependencies.values().next().value;\n if (parentRecordId) {\n parentEntity = batchContext.get(parentRecordId) || null;\n }\n \n if (!parentEntity) {\n // Parent should have been processed before child due to dependency ordering\n throw new Error(`Parent entity not found in batch context for ${entityName}. Parent dependencies: ${Array.from(flattenedRecord.dependencies).join(', ')}`);\n }\n }\n \n // Process field values with parent context and batch context\n for (const [fieldName, fieldValue] of Object.entries(record.fields)) {\n const processedValue = await this.syncEngine.processFieldValue(\n fieldValue,\n entityDir,\n parentEntity,\n null, // rootRecord\n 0,\n batchContext // Pass batch context for lookups\n );\n entity.Set(fieldName, processedValue);\n }\n \n // Check if the record is actually dirty before considering it changed\n let isDirty = entity.Dirty;\n \n // Also check if file content has changed (for @file references)\n if (!isDirty && !isNew && record.sync) {\n const currentChecksum = await this.syncEngine.calculateChecksumWithFileContent(originalFields, entityDir);\n if (currentChecksum !== record.sync.checksum) {\n isDirty = true;\n if (options.verbose) {\n callbacks?.onLog?.(`š File content changed for ${entityName} record (checksum mismatch)`);\n }\n }\n }\n \n if (options.dryRun) {\n if (exists) {\n callbacks?.onLog?.(`[DRY RUN] Would update ${entityName} record`);\n return { status: 'updated' };\n } else {\n callbacks?.onLog?.(`[DRY RUN] Would create ${entityName} record`);\n return { status: 'created' };\n }\n }\n \n // If updating an existing record that's dirty, show what changed\n if (!isNew && isDirty) {\n const changes = entity.GetChangesSinceLastSave();\n const changeKeys = Object.keys(changes);\n if (changeKeys.length > 0) {\n // Get primary key info for display\n const entityInfo = this.syncEngine.getEntityInfo(entityName);\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 ${entityName} 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}: ${this.formatFieldValue(oldValue)} ā ${this.formatFieldValue(newValue)}`);\n }\n }\n }\n \n // Save the record with detailed error logging\n const saveResult = await entity.Save();\n if (!saveResult) {\n // Build detailed error information\n const entityInfo = this.syncEngine.getEntityInfo(entityName);\n const primaryKeyInfo: string[] = [];\n const fieldInfo: string[] = [];\n \n // Collect primary key information\n if (entityInfo) {\n for (const pk of entityInfo.PrimaryKeys) {\n const pkValue = entity.Get(pk.Name);\n primaryKeyInfo.push(`${pk.Name}=${this.formatFieldValue(pkValue)}`);\n }\n }\n \n // Collect field values that were being saved\n for (const [fieldName, fieldValue] of Object.entries(record.fields)) {\n const processedValue = entity.Get(fieldName);\n fieldInfo.push(`${fieldName}=${this.formatFieldValue(processedValue)}`);\n }\n \n // Get the actual error details from the entity\n const errorMessage = entity.LatestResult?.Message || 'Unknown error';\n const errorDetails = entity.LatestResult?.Errors?.map(err => \n typeof err === 'string' ? err : (err?.message || JSON.stringify(err))\n )?.join(', ') || '';\n \n // Log detailed error information\n callbacks?.onError?.(`\\nā FATAL ERROR: Failed to save ${entityName} record`);\n callbacks?.onError?.(` Entity: ${entityName}`);\n if (primaryKeyInfo.length > 0) {\n callbacks?.onError?.(` Primary Key: {${primaryKeyInfo.join(', ')}}`);\n }\n callbacks?.onError?.(` Record Path: ${flattenedRecord.path}`);\n callbacks?.onError?.(` Is New Record: ${isNew}`);\n callbacks?.onError?.(` Field Values Being Saved:`);\n for (const field of fieldInfo) {\n callbacks?.onError?.(` - ${field}`);\n }\n callbacks?.onError?.(` SQL Error: ${errorMessage}`);\n if (errorDetails) {\n callbacks?.onError?.(` Additional Details: ${errorDetails}`);\n }\n \n // Check for common issues\n if (errorMessage.includes('conversion failed') || errorMessage.includes('GUID')) {\n callbacks?.onError?.(` ā ļø This appears to be a GUID/UUID format error. Check that all ID fields contain valid GUIDs.`);\n }\n if (errorMessage.includes('transaction')) {\n callbacks?.onError?.(` ā ļø Transaction error detected. The database transaction may be corrupted.`);\n }\n \n // Throw error to trigger rollback and stop processing\n throw new Error(`Failed to save ${entityName} record at ${flattenedRecord.path}: ${errorMessage}`);\n }\n \n // Add to batch context AFTER save so it has an ID for child @parent:ID references\n // Use the recordId (lookupKey) as the key so child records can find this parent\n batchContext.set(lookupKey, entity);\n \n // Update primaryKey for new records\n if (isNew) {\n const entityInfo = this.syncEngine.getEntityInfo(entityName);\n if (entityInfo) {\n const newPrimaryKey: Record<string, any> = {};\n for (const pk of entityInfo.PrimaryKeys) {\n newPrimaryKey[pk.Name] = entity.Get(pk.Name);\n }\n record.primaryKey = newPrimaryKey;\n }\n }\n \n // Only update sync metadata if the record was actually dirty (changed)\n if (isNew || isDirty) {\n record.sync = {\n lastModified: new Date().toISOString(),\n checksum: await this.syncEngine.calculateChecksumWithFileContent(originalFields, entityDir)\n };\n if (options.verbose) {\n callbacks?.onLog?.(` ā Updated sync metadata (record was ${isNew ? 'new' : 'changed'})`);\n }\n } else if (options.verbose) {\n callbacks?.onLog?.(` - Skipped sync metadata update (no changes detected)`);\n }\n \n // Restore original field values to preserve @ references\n record.fields = originalFields;\n \n return { \n status: isNew ? 'created' : (isDirty ? 'updated' : 'unchanged'),\n isDuplicate: false\n };\n }\n \n private formatFieldValue(value: any): string {\n if (value === null || value === undefined) return 'null';\n if (typeof value === 'string') {\n // Truncate long strings and show quotes\n if (value.length > 50) {\n return `\"${value.substring(0, 47)}...\"`;\n }\n return `\"${value}\"`;\n }\n if (typeof value === 'object') {\n const str = JSON.stringify(value);\n return str.length > 50 ? `\"${str.substring(0, 47)}...\"` : `\"${str}\"`;\n }\n return String(value);\n }\n \n private buildBatchContextKey(entityName: string, record: RecordData): string {\n // Build a unique key for the batch context based on entity name and identifying fields\n const keyParts = [entityName];\n \n // Use primary key if available\n if (record.primaryKey) {\n for (const [field, value] of Object.entries(record.primaryKey)) {\n keyParts.push(`${field}=${value}`);\n }\n } else {\n // Use a combination of important fields as fallback\n const identifyingFields = ['Name', 'ID', 'Code', 'Email'];\n for (const field of identifyingFields) {\n if (record.fields[field]) {\n keyParts.push(`${field}=${record.fields[field]}`);\n }\n }\n }\n \n return keyParts.join('|');\n }\n \n private findEntityDirectories(baseDir: string, specificDir?: string, directoryOrder?: string[]): string[] {\n const dirs: string[] = [];\n \n if (specificDir) {\n // Process specific directory\n const fullPath = path.resolve(baseDir, specificDir);\n if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {\n // Check if this directory has an entity configuration\n const configPath = path.join(fullPath, '.mj-sync.json');\n if (fs.existsSync(configPath)) {\n try {\n const config = fs.readJsonSync(configPath);\n if (config.entity) {\n // It's an entity directory, add it\n dirs.push(fullPath);\n } else {\n // It's a container directory, search its subdirectories\n this.findEntityDirectoriesRecursive(fullPath, dirs);\n }\n } catch {\n // Invalid config, skip\n }\n }\n }\n } else {\n // Find all entity directories\n this.findEntityDirectoriesRecursive(baseDir, dirs);\n }\n \n // Apply directory ordering if specified\n if (directoryOrder && directoryOrder.length > 0 && !specificDir) {\n // Create a map of directory name to order index\n const orderMap = new Map<string, number>();\n directoryOrder.forEach((dir, index) => {\n orderMap.set(dir, index);\n });\n \n // Sort directories based on the order map\n dirs.sort((a, b) => {\n const nameA = path.basename(a);\n const nameB = path.basename(b);\n const orderA = orderMap.get(nameA) ?? Number.MAX_SAFE_INTEGER;\n const orderB = orderMap.get(nameB) ?? Number.MAX_SAFE_INTEGER;\n \n // If both have specified orders, use them\n if (orderA !== Number.MAX_SAFE_INTEGER || orderB !== Number.MAX_SAFE_INTEGER) {\n return orderA - orderB;\n }\n \n // Otherwise, maintain original order (stable sort)\n return 0;\n });\n }\n \n return dirs;\n }\n\n private findEntityDirectoriesRecursive(dir: string, dirs: string[]): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n \n for (const entry of entries) {\n if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {\n const fullPath = path.join(dir, entry.name);\n const configPath = path.join(fullPath, '.mj-sync.json');\n \n if (fs.existsSync(configPath)) {\n try {\n const config = fs.readJsonSync(configPath);\n if (config.entity) {\n dirs.push(fullPath);\n }\n } catch {\n // Skip invalid config files\n }\n } else {\n // Recurse into subdirectories\n this.findEntityDirectoriesRecursive(fullPath, dirs);\n }\n }\n }\n }\n}"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/metadata-sync",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.92.0",
|
|
4
4
|
"description": "MemberJunction metadata synchronization CLI tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"metadata",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"build": "tsc -b"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@memberjunction/core": "2.
|
|
30
|
-
"@memberjunction/core-entities": "2.
|
|
31
|
-
"@memberjunction/core-entities-server": "2.
|
|
32
|
-
"@memberjunction/global": "2.
|
|
33
|
-
"@memberjunction/sqlserver-dataprovider": "2.
|
|
34
|
-
"@memberjunction/graphql-dataprovider": "2.
|
|
29
|
+
"@memberjunction/core": "2.92.0",
|
|
30
|
+
"@memberjunction/core-entities": "2.92.0",
|
|
31
|
+
"@memberjunction/core-entities-server": "2.92.0",
|
|
32
|
+
"@memberjunction/global": "2.92.0",
|
|
33
|
+
"@memberjunction/sqlserver-dataprovider": "2.92.0",
|
|
34
|
+
"@memberjunction/graphql-dataprovider": "2.92.0",
|
|
35
35
|
"chokidar": "^3.6.0",
|
|
36
36
|
"cosmiconfig": "9.0.0",
|
|
37
37
|
"dotenv": "16.4.5",
|