@memberjunction/metadata-sync 3.4.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +907 -2200
  2. package/dist/config.d.ts +1 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +17 -27
  5. package/dist/config.js.map +1 -1
  6. package/dist/constants/metadata-keywords.d.ts +1 -0
  7. package/dist/constants/metadata-keywords.d.ts.map +1 -0
  8. package/dist/constants/metadata-keywords.js +31 -42
  9. package/dist/constants/metadata-keywords.js.map +1 -1
  10. package/dist/index.d.ts +39 -37
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +26 -62
  13. package/dist/index.js.map +1 -1
  14. package/dist/lib/EntityPropertyExtractor.d.ts +1 -0
  15. package/dist/lib/EntityPropertyExtractor.d.ts.map +1 -0
  16. package/dist/lib/EntityPropertyExtractor.js +1 -5
  17. package/dist/lib/EntityPropertyExtractor.js.map +1 -1
  18. package/dist/lib/FieldExternalizer.d.ts +1 -0
  19. package/dist/lib/FieldExternalizer.d.ts.map +1 -0
  20. package/dist/lib/FieldExternalizer.js +14 -21
  21. package/dist/lib/FieldExternalizer.js.map +1 -1
  22. package/dist/lib/RecordProcessor.d.ts +3 -2
  23. package/dist/lib/RecordProcessor.d.ts.map +1 -0
  24. package/dist/lib/RecordProcessor.js +16 -25
  25. package/dist/lib/RecordProcessor.js.map +1 -1
  26. package/dist/lib/RelatedEntityHandler.d.ts +3 -2
  27. package/dist/lib/RelatedEntityHandler.d.ts.map +1 -0
  28. package/dist/lib/RelatedEntityHandler.js +3 -9
  29. package/dist/lib/RelatedEntityHandler.js.map +1 -1
  30. package/dist/lib/config-manager.d.ts +2 -1
  31. package/dist/lib/config-manager.d.ts.map +1 -0
  32. package/dist/lib/config-manager.js +10 -15
  33. package/dist/lib/config-manager.js.map +1 -1
  34. package/dist/lib/database-reference-scanner.d.ts +3 -2
  35. package/dist/lib/database-reference-scanner.d.ts.map +1 -0
  36. package/dist/lib/database-reference-scanner.js +7 -13
  37. package/dist/lib/database-reference-scanner.js.map +1 -1
  38. package/dist/lib/deletion-auditor.d.ts +18 -3
  39. package/dist/lib/deletion-auditor.d.ts.map +1 -0
  40. package/dist/lib/deletion-auditor.js +111 -20
  41. package/dist/lib/deletion-auditor.js.map +1 -1
  42. package/dist/lib/deletion-report-generator.d.ts +2 -1
  43. package/dist/lib/deletion-report-generator.d.ts.map +1 -0
  44. package/dist/lib/deletion-report-generator.js +1 -5
  45. package/dist/lib/deletion-report-generator.js.map +1 -1
  46. package/dist/lib/entity-foreign-key-helper.d.ts +1 -0
  47. package/dist/lib/entity-foreign-key-helper.d.ts.map +1 -0
  48. package/dist/lib/entity-foreign-key-helper.js +1 -5
  49. package/dist/lib/entity-foreign-key-helper.js.map +1 -1
  50. package/dist/lib/file-backup-manager.d.ts +1 -0
  51. package/dist/lib/file-backup-manager.d.ts.map +1 -0
  52. package/dist/lib/file-backup-manager.js +22 -27
  53. package/dist/lib/file-backup-manager.js.map +1 -1
  54. package/dist/lib/file-write-batch.d.ts +2 -1
  55. package/dist/lib/file-write-batch.d.ts.map +1 -0
  56. package/dist/lib/file-write-batch.js +16 -21
  57. package/dist/lib/file-write-batch.js.map +1 -1
  58. package/dist/lib/json-preprocessor.d.ts +1 -0
  59. package/dist/lib/json-preprocessor.d.ts.map +1 -0
  60. package/dist/lib/json-preprocessor.js +21 -26
  61. package/dist/lib/json-preprocessor.js.map +1 -1
  62. package/dist/lib/json-write-helper.d.ts +2 -1
  63. package/dist/lib/json-write-helper.d.ts.map +1 -0
  64. package/dist/lib/json-write-helper.js +4 -11
  65. package/dist/lib/json-write-helper.js.map +1 -1
  66. package/dist/lib/provider-utils.d.ts +2 -1
  67. package/dist/lib/provider-utils.d.ts.map +1 -0
  68. package/dist/lib/provider-utils.js +15 -46
  69. package/dist/lib/provider-utils.js.map +1 -1
  70. package/dist/lib/record-dependency-analyzer.d.ts +41 -2
  71. package/dist/lib/record-dependency-analyzer.d.ts.map +1 -0
  72. package/dist/lib/record-dependency-analyzer.js +108 -40
  73. package/dist/lib/record-dependency-analyzer.js.map +1 -1
  74. package/dist/lib/singleton-manager.d.ts +2 -1
  75. package/dist/lib/singleton-manager.d.ts.map +1 -0
  76. package/dist/lib/singleton-manager.js +4 -9
  77. package/dist/lib/singleton-manager.js.map +1 -1
  78. package/dist/lib/sql-logger.d.ts +2 -1
  79. package/dist/lib/sql-logger.d.ts.map +1 -0
  80. package/dist/lib/sql-logger.js +8 -16
  81. package/dist/lib/sql-logger.js.map +1 -1
  82. package/dist/lib/sync-engine.d.ts +2 -1
  83. package/dist/lib/sync-engine.d.ts.map +1 -0
  84. package/dist/lib/sync-engine.js +58 -76
  85. package/dist/lib/sync-engine.js.map +1 -1
  86. package/dist/lib/transaction-manager.d.ts +2 -1
  87. package/dist/lib/transaction-manager.d.ts.map +1 -0
  88. package/dist/lib/transaction-manager.js +6 -11
  89. package/dist/lib/transaction-manager.js.map +1 -1
  90. package/dist/services/FileResetService.d.ts +1 -0
  91. package/dist/services/FileResetService.d.ts.map +1 -0
  92. package/dist/services/FileResetService.js +17 -24
  93. package/dist/services/FileResetService.js.map +1 -1
  94. package/dist/services/FormattingService.d.ts +2 -1
  95. package/dist/services/FormattingService.d.ts.map +1 -0
  96. package/dist/services/FormattingService.js +68 -73
  97. package/dist/services/FormattingService.js.map +1 -1
  98. package/dist/services/InitService.d.ts +1 -0
  99. package/dist/services/InitService.d.ts.map +1 -0
  100. package/dist/services/InitService.js +12 -19
  101. package/dist/services/InitService.js.map +1 -1
  102. package/dist/services/PullService.d.ts +2 -1
  103. package/dist/services/PullService.d.ts.map +1 -0
  104. package/dist/services/PullService.js +49 -60
  105. package/dist/services/PullService.js.map +1 -1
  106. package/dist/services/PushService.d.ts +3 -1
  107. package/dist/services/PushService.d.ts.map +1 -0
  108. package/dist/services/PushService.js +144 -95
  109. package/dist/services/PushService.js.map +1 -1
  110. package/dist/services/StatusService.d.ts +2 -1
  111. package/dist/services/StatusService.d.ts.map +1 -0
  112. package/dist/services/StatusService.js +14 -22
  113. package/dist/services/StatusService.js.map +1 -1
  114. package/dist/services/ValidationService.d.ts +2 -1
  115. package/dist/services/ValidationService.d.ts.map +1 -0
  116. package/dist/services/ValidationService.js +41 -71
  117. package/dist/services/ValidationService.js.map +1 -1
  118. package/dist/services/WatchService.d.ts +4 -3
  119. package/dist/services/WatchService.d.ts.map +1 -0
  120. package/dist/services/WatchService.js +35 -43
  121. package/dist/services/WatchService.js.map +1 -1
  122. package/dist/services/index.d.ts +9 -8
  123. package/dist/services/index.d.ts.map +1 -0
  124. package/dist/services/index.js +8 -19
  125. package/dist/services/index.js.map +1 -1
  126. package/dist/types/validation.d.ts +2 -1
  127. package/dist/types/validation.d.ts.map +1 -0
  128. package/dist/types/validation.js +2 -23
  129. package/dist/types/validation.js.map +1 -1
  130. package/package.json +23 -21
@@ -1 +1 @@
1
- {"version":3,"file":"RelatedEntityHandler.js","sourceRoot":"","sources":["../../src/lib/RelatedEntityHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseEntity, RunView, UserInfo } from '@memberjunction/core';\nimport { SyncEngine, RecordData } from '../lib/sync-engine';\nimport { RelatedEntityConfig, EntityConfig } from '../config';\n\n/**\n * Handles loading and processing of related entities for records\n */\nexport class RelatedEntityHandler {\n constructor(\n private syncEngine: SyncEngine,\n private contextUser: UserInfo\n ) {}\n\n /**\n * Load related entities for a record\n */\n async loadRelatedEntities(\n parentRecord: BaseEntity,\n relationConfig: RelatedEntityConfig,\n parentEntityConfig: EntityConfig,\n existingRelatedEntities: RecordData[],\n processRecordData: (\n record: BaseEntity,\n primaryKey: Record<string, any>,\n targetDir: string,\n entityConfig: EntityConfig,\n verbose?: boolean,\n isNewRecord?: boolean,\n existingRecordData?: RecordData,\n currentDepth?: number,\n ancestryPath?: Set<string>,\n fieldOverrides?: Record<string, any>\n ) => Promise<RecordData>,\n currentDepth: number,\n ancestryPath: Set<string>,\n verbose?: boolean\n ): Promise<RecordData[]> {\n try {\n const parentPrimaryKey = this.getRecordPrimaryKey(parentRecord);\n if (!parentPrimaryKey) {\n this.logWarning('Unable to determine primary key for parent record', verbose);\n return [];\n }\n\n const relatedRecords = await this.queryRelatedEntities(\n parentPrimaryKey, \n relationConfig, \n verbose\n );\n\n if (!relatedRecords) {\n return [];\n }\n\n const relatedEntityConfig = this.createRelatedEntityConfig(relationConfig, parentEntityConfig);\n \n return await this.processRelatedRecords(\n relatedRecords,\n relationConfig,\n relatedEntityConfig,\n existingRelatedEntities,\n processRecordData,\n currentDepth,\n ancestryPath,\n verbose\n );\n } catch (error) {\n this.logError(`Error loading related entities for ${relationConfig.entity}`, error, verbose);\n return [];\n }\n }\n\n /**\n * Queries the database for related entities\n */\n private async queryRelatedEntities(\n parentPrimaryKey: string,\n relationConfig: RelatedEntityConfig,\n verbose?: boolean\n ): Promise<BaseEntity[] | null> {\n const filter = this.buildRelatedEntityFilter(parentPrimaryKey, relationConfig);\n \n if (verbose) {\n console.log(`Loading related entities: ${relationConfig.entity} with filter: ${filter}`);\n }\n\n const rv = new RunView();\n const result = await rv.RunView({\n EntityName: relationConfig.entity,\n ExtraFilter: filter,\n ResultType: 'entity_object'\n }, this.contextUser);\n\n if (!result.Success) {\n this.logWarning(`Failed to load related entities ${relationConfig.entity}: ${result.ErrorMessage}`, verbose);\n return null;\n }\n\n if (verbose) {\n console.log(`Found ${result.Results.length} related records for ${relationConfig.entity}`);\n }\n\n return result.Results;\n }\n\n /**\n * Builds the filter for querying related entities\n */\n private buildRelatedEntityFilter(parentPrimaryKey: string, relationConfig: RelatedEntityConfig): string {\n let filter = `${relationConfig.foreignKey} = '${parentPrimaryKey}'`;\n if (relationConfig.filter) {\n filter += ` AND (${relationConfig.filter})`;\n }\n return filter;\n }\n\n /**\n * Creates entity config for related entity processing\n */\n private createRelatedEntityConfig(\n relationConfig: RelatedEntityConfig, \n parentEntityConfig: EntityConfig\n ): EntityConfig {\n return {\n entity: relationConfig.entity,\n pull: {\n excludeFields: relationConfig.excludeFields || [],\n lookupFields: relationConfig.lookupFields || {},\n externalizeFields: relationConfig.externalizeFields || [],\n relatedEntities: relationConfig.relatedEntities || {},\n ignoreVirtualFields: parentEntityConfig.pull?.ignoreVirtualFields || false,\n ignoreNullFields: parentEntityConfig.pull?.ignoreNullFields || false\n }\n };\n }\n\n /**\n * Processes all related records (both existing and new)\n */\n private async processRelatedRecords(\n dbRecords: BaseEntity[],\n relationConfig: RelatedEntityConfig,\n relatedEntityConfig: EntityConfig,\n existingRelatedEntities: RecordData[],\n processRecordData: Function,\n currentDepth: number,\n ancestryPath: Set<string>,\n verbose?: boolean\n ): Promise<RecordData[]> {\n const dbRecordMap = this.buildDatabaseRecordMap(dbRecords);\n const relatedRecords: RecordData[] = [];\n const processedIds = new Set<string>();\n\n // Process existing related entities first (preserving order)\n await this.processExistingRelatedEntities(\n existingRelatedEntities,\n dbRecordMap,\n relationConfig,\n relatedEntityConfig,\n processRecordData,\n currentDepth,\n ancestryPath,\n relatedRecords,\n processedIds,\n verbose\n );\n\n // Process new related entities (append to end)\n await this.processNewRelatedEntities(\n dbRecords,\n relationConfig,\n relatedEntityConfig,\n processRecordData,\n currentDepth,\n ancestryPath,\n relatedRecords,\n processedIds,\n verbose\n );\n\n return relatedRecords;\n }\n\n /**\n * Builds a map of database records by primary key for efficient lookup\n */\n private buildDatabaseRecordMap(dbRecords: BaseEntity[]): Map<string, BaseEntity> {\n const dbRecordMap = new Map<string, BaseEntity>();\n \n for (const relatedRecord of dbRecords) {\n const relatedPrimaryKey = this.getRecordPrimaryKey(relatedRecord);\n if (relatedPrimaryKey) {\n dbRecordMap.set(relatedPrimaryKey, relatedRecord);\n }\n }\n \n return dbRecordMap;\n }\n\n /**\n * Processes existing related entities\n */\n private async processExistingRelatedEntities(\n existingRelatedEntities: RecordData[],\n dbRecordMap: Map<string, BaseEntity>,\n relationConfig: RelatedEntityConfig,\n relatedEntityConfig: EntityConfig,\n processRecordData: Function,\n currentDepth: number,\n ancestryPath: Set<string>,\n relatedRecords: RecordData[],\n processedIds: Set<string>,\n verbose?: boolean\n ): Promise<void> {\n for (const existingRelatedEntity of existingRelatedEntities) {\n const existingPrimaryKey = existingRelatedEntity.primaryKey?.ID;\n if (!existingPrimaryKey) {\n this.logWarning('Existing related entity missing primary key, skipping', verbose);\n continue;\n }\n\n const dbRecord = dbRecordMap.get(existingPrimaryKey);\n if (!dbRecord) {\n if (verbose) {\n console.log(`Related entity ${existingPrimaryKey} no longer exists in database, removing from results`);\n }\n continue; // Skip deleted records\n }\n\n const recordData = await this.processExistingRelatedEntity(\n dbRecord,\n existingPrimaryKey,\n relationConfig,\n relatedEntityConfig,\n processRecordData,\n existingRelatedEntity,\n currentDepth,\n ancestryPath,\n verbose\n );\n\n if (recordData) {\n relatedRecords.push(recordData);\n processedIds.add(existingPrimaryKey);\n }\n }\n }\n\n /**\n * Processes a single existing related entity\n */\n private async processExistingRelatedEntity(\n dbRecord: BaseEntity,\n existingPrimaryKey: string,\n relationConfig: RelatedEntityConfig,\n relatedEntityConfig: EntityConfig,\n processRecordData: Function,\n existingRelatedEntity: RecordData,\n currentDepth: number,\n ancestryPath: Set<string>,\n verbose?: boolean\n ): Promise<RecordData | null> {\n const relatedRecordPrimaryKey = this.buildPrimaryKeyForRecord(\n existingPrimaryKey, \n dbRecord, \n relationConfig.entity\n );\n\n const fieldOverrides = this.createFieldOverrides(dbRecord, relationConfig);\n if (!fieldOverrides) {\n return null;\n }\n\n return await processRecordData(\n dbRecord,\n relatedRecordPrimaryKey,\n '', // targetDir not needed for related entities\n relatedEntityConfig,\n verbose,\n false, // isNewRecord = false for existing records\n existingRelatedEntity, // Pass existing data for change detection\n currentDepth + 1,\n ancestryPath,\n fieldOverrides // Pass the field override for @parent:ID\n );\n }\n\n /**\n * Processes new related entities\n */\n private async processNewRelatedEntities(\n dbRecords: BaseEntity[],\n relationConfig: RelatedEntityConfig,\n relatedEntityConfig: EntityConfig,\n processRecordData: Function,\n currentDepth: number,\n ancestryPath: Set<string>,\n relatedRecords: RecordData[],\n processedIds: Set<string>,\n verbose?: boolean\n ): Promise<void> {\n for (const relatedRecord of dbRecords) {\n const relatedPrimaryKey = this.getRecordPrimaryKey(relatedRecord);\n if (!relatedPrimaryKey || processedIds.has(relatedPrimaryKey)) {\n continue; // Skip already processed records\n }\n\n const recordData = await this.processNewRelatedEntity(\n relatedRecord,\n relatedPrimaryKey,\n relationConfig,\n relatedEntityConfig,\n processRecordData,\n currentDepth,\n ancestryPath,\n verbose\n );\n\n if (recordData) {\n relatedRecords.push(recordData);\n processedIds.add(relatedPrimaryKey);\n }\n }\n }\n\n /**\n * Processes a single new related entity\n */\n private async processNewRelatedEntity(\n relatedRecord: BaseEntity,\n relatedPrimaryKey: string,\n relationConfig: RelatedEntityConfig,\n relatedEntityConfig: EntityConfig,\n processRecordData: Function,\n currentDepth: number,\n ancestryPath: Set<string>,\n verbose?: boolean\n ): Promise<RecordData | null> {\n const relatedRecordPrimaryKey = this.buildPrimaryKeyForRecord(\n relatedPrimaryKey, \n relatedRecord, \n relationConfig.entity\n );\n\n const fieldOverrides = this.createFieldOverrides(relatedRecord, relationConfig);\n if (!fieldOverrides) {\n return null;\n }\n\n return await processRecordData(\n relatedRecord,\n relatedRecordPrimaryKey,\n '', // targetDir not needed for related entities\n relatedEntityConfig,\n verbose,\n true, // isNewRecord = true for new records\n undefined, // No existing data for new records\n currentDepth + 1,\n ancestryPath,\n fieldOverrides // Pass the field override for @parent:ID\n );\n }\n\n /**\n * Creates field overrides for @parent:ID replacement\n */\n private createFieldOverrides(record: BaseEntity, relationConfig: RelatedEntityConfig): Record<string, any> | null {\n if (typeof record.GetAll === 'function') {\n const data = record.GetAll();\n if (data[relationConfig.foreignKey] !== undefined) {\n return { [relationConfig.foreignKey]: '@parent:ID' };\n }\n } else {\n if ((record as any)[relationConfig.foreignKey] !== undefined) {\n return { [relationConfig.foreignKey]: '@parent:ID' };\n }\n }\n return null;\n }\n\n /**\n * Builds primary key for a record\n */\n private buildPrimaryKeyForRecord(\n primaryKeyValue: string, \n record: BaseEntity, \n entityName: string\n ): Record<string, any> {\n const relatedRecordPrimaryKey: Record<string, any> = {};\n const entityInfo = this.syncEngine.getEntityInfo(entityName);\n \n for (const pk of entityInfo?.PrimaryKeys || []) {\n if (pk.Name === 'ID') {\n relatedRecordPrimaryKey[pk.Name] = primaryKeyValue;\n } else {\n // For compound keys, get the value from the related record\n relatedRecordPrimaryKey[pk.Name] = this.getFieldValue(record, pk.Name);\n }\n }\n \n return relatedRecordPrimaryKey;\n }\n\n /**\n * Get the primary key value from a record\n */\n private getRecordPrimaryKey(record: BaseEntity): string | null {\n if (!record) return null;\n \n // Try to get ID directly\n if ((record as any).ID) return (record as any).ID;\n \n // Try to get from GetAll() method if it's an entity object\n if (typeof record.GetAll === 'function') {\n const data = record.GetAll();\n if (data.ID) return data.ID;\n }\n \n // Try common variations\n if ((record as any).id) return (record as any).id;\n if ((record as any).Id) return (record as any).Id;\n \n return null;\n }\n\n /**\n * Get a field value from a record, handling both entity objects and plain objects\n */\n private getFieldValue(record: BaseEntity, fieldName: string): any {\n if (!record) return null;\n \n // Try to get field directly using bracket notation with type assertion\n if ((record as any)[fieldName] !== undefined) return (record as any)[fieldName];\n \n // Try to get from GetAll() method if it's an entity object\n if (typeof record.GetAll === 'function') {\n const data = record.GetAll();\n if (data[fieldName] !== undefined) return data[fieldName];\n }\n \n return null;\n }\n\n /**\n * Log warning message if verbose mode is enabled\n */\n private logWarning(message: string, verbose?: boolean): void {\n if (verbose) {\n console.warn(message);\n }\n }\n\n /**\n * Log error message if verbose mode is enabled\n */\n private logError(message: string, error: any, verbose?: boolean): void {\n if (verbose) {\n console.error(`${message}: ${error}`);\n }\n }\n}"]}
1
+ {"version":3,"file":"RelatedEntityHandler.js","sourceRoot":"","sources":["../../src/lib/RelatedEntityHandler.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@
6
6
  * loading MJ config from the original working directory, regardless of any
7
7
  * directory changes made during command execution.
8
8
  */
9
- import { MJConfig } from '../config';
9
+ import { MJConfig } from '../config.js';
10
10
  /**
11
11
  * Configuration manager singleton for handling MJ configuration
12
12
  *
@@ -54,3 +54,4 @@ export declare class ConfigManager {
54
54
  getMJConfig(): MJConfig | null;
55
55
  }
56
56
  export declare const configManager: ConfigManager;
57
+ //# sourceMappingURL=config-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-manager.d.ts","sourceRoot":"","sources":["../../src/lib/config-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAsBrC;;;;;;GAMG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgB;IACvC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO;IAIP;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,aAAa;IAOnC;;;;OAIG;IACH,cAAc,IAAI,MAAM;IAQxB;;;;OAIG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIjC;;;;;;;;OAQG;IACH,YAAY,CAAC,WAAW,UAAQ,GAAG,QAAQ,GAAG,IAAI;IA0BlD;;;;OAIG;IACH,WAAW,IAAI,QAAQ,GAAG,IAAI;CAM/B;AAGD,eAAO,MAAM,aAAa,eAA8B,CAAC"}
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * @fileoverview Shared configuration manager for MetadataSync commands
4
3
  * @module lib/config-manager
@@ -7,10 +6,8 @@
7
6
  * loading MJ config from the original working directory, regardless of any
8
7
  * directory changes made during command execution.
9
8
  */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.configManager = exports.ConfigManager = void 0;
12
- const cosmiconfig_1 = require("cosmiconfig");
13
- const config_1 = require("@memberjunction/config");
9
+ import { cosmiconfigSync } from 'cosmiconfig';
10
+ import { mergeConfigs, parseBooleanEnv } from '@memberjunction/config';
14
11
  /**
15
12
  * Default configuration for MetadataSync
16
13
  *
@@ -25,7 +22,7 @@ const DEFAULT_SYNC_CONFIG = {
25
22
  dbDatabase: process.env.DB_DATABASE,
26
23
  dbUsername: process.env.DB_USERNAME,
27
24
  dbPassword: process.env.DB_PASSWORD,
28
- dbTrustServerCertificate: (0, config_1.parseBooleanEnv)(process.env.DB_TRUST_SERVER_CERTIFICATE) ? 'Y' : 'N',
25
+ dbTrustServerCertificate: parseBooleanEnv(process.env.DB_TRUST_SERVER_CERTIFICATE) ? 'Y' : 'N',
29
26
  dbEncrypt: process.env.DB_ENCRYPT ?? undefined,
30
27
  dbInstanceName: process.env.DB_INSTANCE_NAME,
31
28
  mjCoreSchema: process.env.MJ_CORE_SCHEMA ?? '__mj',
@@ -37,12 +34,11 @@ const DEFAULT_SYNC_CONFIG = {
37
34
  * consistent access across all commands, even when the current working
38
35
  * directory changes during execution.
39
36
  */
40
- class ConfigManager {
41
- static instance;
42
- originalCwd = null;
43
- mjConfig = null;
44
- configLoaded = false;
37
+ export class ConfigManager {
45
38
  constructor() {
39
+ this.originalCwd = null;
40
+ this.mjConfig = null;
41
+ this.configLoaded = false;
46
42
  // Original cwd will be set on first access
47
43
  }
48
44
  /**
@@ -88,7 +84,7 @@ class ConfigManager {
88
84
  return this.mjConfig;
89
85
  }
90
86
  try {
91
- const explorer = (0, cosmiconfig_1.cosmiconfigSync)('mj');
87
+ const explorer = cosmiconfigSync('mj');
92
88
  // Always search from the original working directory
93
89
  const searchPath = this.getOriginalCwd();
94
90
  const result = explorer.search(searchPath);
@@ -96,7 +92,7 @@ class ConfigManager {
96
92
  // This ensures environment variables are used for database settings
97
93
  // when not explicitly set in the config file
98
94
  const userConfig = result?.config ?? {};
99
- this.mjConfig = (0, config_1.mergeConfigs)(DEFAULT_SYNC_CONFIG, userConfig);
95
+ this.mjConfig = mergeConfigs(DEFAULT_SYNC_CONFIG, userConfig);
100
96
  this.configLoaded = true;
101
97
  return this.mjConfig;
102
98
  }
@@ -119,7 +115,6 @@ class ConfigManager {
119
115
  return this.mjConfig;
120
116
  }
121
117
  }
122
- exports.ConfigManager = ConfigManager;
123
118
  // Export singleton instance for convenience
124
- exports.configManager = ConfigManager.getInstance();
119
+ export const configManager = ConfigManager.getInstance();
125
120
  //# sourceMappingURL=config-manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../src/lib/config-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Shared configuration manager for MetadataSync commands\n * @module lib/config-manager\n *\n * This module provides a centralized configuration management system that handles\n * loading MJ config from the original working directory, regardless of any\n * directory changes made during command execution.\n */\n\nimport { cosmiconfigSync } from 'cosmiconfig';\nimport { mergeConfigs, parseBooleanEnv } from '@memberjunction/config';\nimport { MJConfig } from '../config';\n\n/**\n * Default configuration for MetadataSync\n *\n * Provides database connection settings from environment variables,\n * matching the pattern used by MJServer's DEFAULT_SERVER_CONFIG.\n * This ensures consistent behavior with the MJ ecosystem.\n */\nconst DEFAULT_SYNC_CONFIG: Partial<MJConfig> = {\n // Database connection settings (environment-driven with defaults)\n dbHost: process.env.DB_HOST ?? 'localhost',\n dbPort: process.env.DB_PORT ? parseInt(process.env.DB_PORT, 10) : 1433,\n dbDatabase: process.env.DB_DATABASE,\n dbUsername: process.env.DB_USERNAME,\n dbPassword: process.env.DB_PASSWORD,\n dbTrustServerCertificate: parseBooleanEnv(process.env.DB_TRUST_SERVER_CERTIFICATE) ? 'Y' : 'N',\n dbEncrypt: process.env.DB_ENCRYPT ?? undefined,\n dbInstanceName: process.env.DB_INSTANCE_NAME,\n mjCoreSchema: process.env.MJ_CORE_SCHEMA ?? '__mj',\n};\n\n/**\n * Configuration manager singleton for handling MJ configuration\n * \n * Stores the original working directory and MJ configuration to ensure\n * consistent access across all commands, even when the current working\n * directory changes during execution.\n */\nexport class ConfigManager {\n private static instance: ConfigManager;\n private originalCwd: string | null = null;\n private mjConfig: MJConfig | null = null;\n private configLoaded = false;\n\n private constructor() {\n // Original cwd will be set on first access\n }\n\n /**\n * Get the singleton instance of ConfigManager\n */\n static getInstance(): ConfigManager {\n if (!ConfigManager.instance) {\n ConfigManager.instance = new ConfigManager();\n }\n return ConfigManager.instance;\n }\n\n /**\n * Get the original working directory from when the process started\n * \n * @returns The original working directory path\n */\n getOriginalCwd(): string {\n if (!this.originalCwd) {\n // Capture on first access\n this.originalCwd = process.cwd();\n }\n return this.originalCwd;\n }\n \n /**\n * Set the original working directory (for testing or special cases)\n * \n * @param cwd - The working directory to use as original\n */\n setOriginalCwd(cwd: string): void {\n this.originalCwd = cwd;\n }\n\n /**\n * Load MemberJunction configuration\n * \n * Searches for mj.config.cjs starting from the original working directory\n * and walking up the directory tree. Caches the result for subsequent calls.\n * \n * @param forceReload - Force reload the configuration even if cached\n * @returns MJConfig object if found, null if not found or invalid\n */\n loadMJConfig(forceReload = false): MJConfig | null {\n if (this.configLoaded && !forceReload) {\n return this.mjConfig;\n }\n\n try {\n const explorer = cosmiconfigSync('mj');\n // Always search from the original working directory\n const searchPath = this.getOriginalCwd();\n const result = explorer.search(searchPath);\n\n // Merge user config with DEFAULT_SYNC_CONFIG (user config takes precedence)\n // This ensures environment variables are used for database settings\n // when not explicitly set in the config file\n const userConfig = result?.config ?? {};\n this.mjConfig = mergeConfigs(DEFAULT_SYNC_CONFIG, userConfig) as MJConfig;\n this.configLoaded = true;\n return this.mjConfig;\n } catch (error) {\n console.error('Error loading MJ config:', error);\n this.mjConfig = null;\n this.configLoaded = true;\n return null;\n }\n }\n\n /**\n * Get the cached MJ configuration\n * \n * @returns The cached MJConfig or null if not loaded\n */\n getMJConfig(): MJConfig | null {\n if (!this.configLoaded) {\n return this.loadMJConfig();\n }\n return this.mjConfig;\n }\n}\n\n// Export singleton instance for convenience\nexport const configManager = ConfigManager.getInstance();"]}
1
+ {"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../src/lib/config-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGvE;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAsB;IAC7C,kEAAkE;IAClE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,WAAW;IAC1C,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;IACtE,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW;IACnC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW;IACnC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW;IACnC,wBAAwB,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;IAC9F,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,SAAS;IAC9C,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB;IAC5C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,MAAM;CACnD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,OAAO,aAAa;IAMxB;QAJQ,gBAAW,GAAkB,IAAI,CAAC;QAClC,aAAQ,GAAoB,IAAI,CAAC;QACjC,iBAAY,GAAG,KAAK,CAAC;QAG3B,2CAA2C;IAC7C,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC5B,aAAa,CAAC,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,aAAa,CAAC,QAAQ,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACH,cAAc;QACZ,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,0BAA0B;YAC1B,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QACnC,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACH,cAAc,CAAC,GAAW;QACxB,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;IACzB,CAAC;IAED;;;;;;;;OAQG;IACH,YAAY,CAAC,WAAW,GAAG,KAAK;QAC9B,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YACvC,oDAAoD;YACpD,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAE3C,4EAA4E;YAC5E,oEAAoE;YACpE,6CAA6C;YAC7C,MAAM,UAAU,GAAG,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC;YACxC,IAAI,CAAC,QAAQ,GAAG,YAAY,CAAC,mBAAmB,EAAE,UAAU,CAAa,CAAC;YAC1E,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;YACjD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,WAAW;QACT,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAED,4CAA4C;AAC5C,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { Metadata, UserInfo, CompositeKey } from '@memberjunction/core';
2
- import { FlattenedRecord } from './record-dependency-analyzer';
3
- import { ReverseFKInfo } from './entity-foreign-key-helper';
2
+ import { FlattenedRecord } from './record-dependency-analyzer.js';
3
+ import { ReverseFKInfo } from './entity-foreign-key-helper.js';
4
4
  /**
5
5
  * Represents a database record that references a record being deleted
6
6
  */
@@ -54,3 +54,4 @@ export declare class DatabaseReferenceScanner {
54
54
  */
55
55
  getMetadataReferences(references: DatabaseReference[]): DatabaseReference[];
56
56
  }
57
+ //# sourceMappingURL=database-reference-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-reference-scanner.d.ts","sourceRoot":"","sources":["../../src/lib/database-reference-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAW,QAAQ,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,YAAY,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,YAAY,CAAC;IAC5B,gBAAgB,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;GAKG;AACH,qBAAa,wBAAwB;IAE7B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,WAAW;gBADX,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,QAAQ;IAGjC;;;;;;;OAOG;IACG,iBAAiB,CACnB,eAAe,EAAE,eAAe,EAAE,EAClC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,EAC1C,kBAAkB,EAAE,eAAe,EAAE,GACtC,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAwE/B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoCzB;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAoCrC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqBzB;;;OAGG;IACH,qBAAqB,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,EAAE;IAI3E;;;OAGG;IACH,qBAAqB,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,EAAE;CAG9E"}
@@ -1,16 +1,11 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DatabaseReferenceScanner = void 0;
4
- const core_1 = require("@memberjunction/core");
1
+ import { RunView, CompositeKey } from '@memberjunction/core';
5
2
  /**
6
3
  * Scans the database for existing records that reference records marked for deletion
7
4
  * This helps identify:
8
5
  * 1. Database-only records that will prevent deletion
9
6
  * 2. Records that should be included in the deletion plan
10
7
  */
11
- class DatabaseReferenceScanner {
12
- metadata;
13
- contextUser;
8
+ export class DatabaseReferenceScanner {
14
9
  constructor(metadata, contextUser) {
15
10
  this.metadata = metadata;
16
11
  this.contextUser = contextUser;
@@ -25,7 +20,7 @@ class DatabaseReferenceScanner {
25
20
  */
26
21
  async scanForReferences(recordsToDelete, reverseFKMap, allMetadataRecords) {
27
22
  const references = [];
28
- const rv = new core_1.RunView();
23
+ const rv = new RunView();
29
24
  for (const record of recordsToDelete) {
30
25
  const entityName = record.entityName;
31
26
  const primaryKey = this.extractPrimaryKey(record);
@@ -95,7 +90,7 @@ class DatabaseReferenceScanner {
95
90
  if (!pkValue) {
96
91
  return null;
97
92
  }
98
- return core_1.CompositeKey.FromID(pkValue.toString());
93
+ return CompositeKey.FromID(pkValue.toString());
99
94
  }
100
95
  // Composite primary key
101
96
  const keyPairs = [];
@@ -106,7 +101,7 @@ class DatabaseReferenceScanner {
106
101
  }
107
102
  keyPairs.push({ FieldName: pk.Name, Value: value.toString() });
108
103
  }
109
- return core_1.CompositeKey.FromKeyValuePairs(keyPairs);
104
+ return CompositeKey.FromKeyValuePairs(keyPairs);
110
105
  }
111
106
  /**
112
107
  * Get primary key from a simple record (plain object from RunView with ResultType: 'simple')
@@ -127,7 +122,7 @@ class DatabaseReferenceScanner {
127
122
  if (!pkValue) {
128
123
  return null;
129
124
  }
130
- return core_1.CompositeKey.FromID(pkValue.toString());
125
+ return CompositeKey.FromID(pkValue.toString());
131
126
  }
132
127
  // Composite primary key
133
128
  const keyPairs = [];
@@ -138,7 +133,7 @@ class DatabaseReferenceScanner {
138
133
  }
139
134
  keyPairs.push({ FieldName: pk.Name, Value: value.toString() });
140
135
  }
141
- return core_1.CompositeKey.FromKeyValuePairs(keyPairs);
136
+ return CompositeKey.FromKeyValuePairs(keyPairs);
142
137
  }
143
138
  /**
144
139
  * Check if a database record exists in metadata files
@@ -171,5 +166,4 @@ class DatabaseReferenceScanner {
171
166
  return references.filter(ref => ref.existsInMetadata);
172
167
  }
173
168
  }
174
- exports.DatabaseReferenceScanner = DatabaseReferenceScanner;
175
169
  //# sourceMappingURL=database-reference-scanner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"database-reference-scanner.js","sourceRoot":"","sources":["../../src/lib/database-reference-scanner.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata, RunView, UserInfo, CompositeKey } from '@memberjunction/core';\nimport { FlattenedRecord } from './record-dependency-analyzer';\nimport { ReverseFKInfo } from './entity-foreign-key-helper';\n\n/**\n * Represents a database record that references a record being deleted\n */\nexport interface DatabaseReference {\n entityName: string; // Entity containing the referencing record\n primaryKey: CompositeKey; // Primary key of the referencing record\n referencingField: string; // Foreign key field making the reference\n referencedEntity: string; // Entity being referenced\n referencedKey: CompositeKey; // Primary key of referenced record\n existsInMetadata: boolean; // Whether this record exists in metadata files\n}\n\n/**\n * Scans the database for existing records that reference records marked for deletion\n * This helps identify:\n * 1. Database-only records that will prevent deletion\n * 2. Records that should be included in the deletion plan\n */\nexport class DatabaseReferenceScanner {\n constructor(\n private metadata: Metadata,\n private contextUser: UserInfo\n ) {}\n\n /**\n * Scan database for records that reference records marked for deletion\n *\n * @param recordsToDelete Records that will be deleted\n * @param reverseFKMap Map of entity -> entities that reference it\n * @param allMetadataRecords All records from metadata (for checking if DB record exists in metadata)\n * @returns Array of database references found\n */\n async scanForReferences(\n recordsToDelete: FlattenedRecord[],\n reverseFKMap: Map<string, ReverseFKInfo[]>,\n allMetadataRecords: FlattenedRecord[]\n ): Promise<DatabaseReference[]> {\n const references: DatabaseReference[] = [];\n const rv = new RunView();\n\n for (const record of recordsToDelete) {\n const entityName = record.entityName;\n const primaryKey = this.extractPrimaryKey(record);\n\n if (!primaryKey) {\n console.warn(`Cannot scan references for ${entityName}: no primary key found`);\n continue;\n }\n\n // Find all entities that could reference this one\n const referencingEntities = reverseFKMap.get(entityName) || [];\n\n for (const refInfo of referencingEntities) {\n try {\n // Query database for existing references\n // Use the actual value from the primary key, not the concatenated string format\n const pkValue = primaryKey.KeyValuePairs.length === 1\n ? primaryKey.KeyValuePairs[0].Value\n : primaryKey.ToConcatenatedString();\n\n const filter = `${refInfo.fieldName} = '${pkValue}'`;\n\n const result = await rv.RunView({\n EntityName: refInfo.entityName,\n ExtraFilter: filter,\n ResultType: 'simple' // More efficient - we don't need entity objects\n }, this.contextUser);\n\n if (result.Success && result.Results && result.Results.length > 0) {\n // Found database records that reference this record\n for (const dbRecord of result.Results) {\n const refPrimaryKey = this.getPrimaryKeyFromSimpleRecord(\n dbRecord,\n refInfo.entityName\n );\n\n if (!refPrimaryKey) {\n console.warn(`Cannot get primary key for ${refInfo.entityName} record`);\n continue;\n }\n\n references.push({\n entityName: refInfo.entityName,\n primaryKey: refPrimaryKey,\n referencingField: refInfo.fieldName,\n referencedEntity: entityName,\n referencedKey: primaryKey,\n existsInMetadata: this.checkIfInMetadata(\n refInfo.entityName,\n refPrimaryKey,\n allMetadataRecords // Check against ALL metadata, not just deletes\n )\n });\n }\n }\n } catch (error) {\n console.error(\n `Error scanning references from ${refInfo.entityName}.${refInfo.fieldName} ` +\n `to ${entityName}:`,\n error\n );\n }\n }\n }\n\n return references;\n }\n\n /**\n * Extract primary key from a flattened record\n */\n private extractPrimaryKey(record: FlattenedRecord): CompositeKey | null {\n const entityInfo = this.metadata.Entities.find(e => e.Name === record.entityName);\n if (!entityInfo) {\n return null;\n }\n\n const primaryKeys = entityInfo.PrimaryKeys;\n if (primaryKeys.length === 0) {\n return null;\n }\n\n // Single primary key\n if (primaryKeys.length === 1) {\n const pkField = primaryKeys[0].Name;\n const pkValue = record.record.primaryKey?.[pkField] || record.record.fields?.[pkField];\n\n if (!pkValue) {\n return null;\n }\n\n return CompositeKey.FromID(pkValue.toString());\n }\n\n // Composite primary key\n const keyPairs: { FieldName: string; Value: string }[] = [];\n for (const pk of primaryKeys) {\n const value = record.record.primaryKey?.[pk.Name] || record.record.fields?.[pk.Name];\n if (!value) {\n return null;\n }\n keyPairs.push({ FieldName: pk.Name, Value: value.toString() });\n }\n\n return CompositeKey.FromKeyValuePairs(keyPairs);\n }\n\n /**\n * Get primary key from a simple record (plain object from RunView with ResultType: 'simple')\n */\n private getPrimaryKeyFromSimpleRecord(record: Record<string, unknown>, entityName: string): CompositeKey | null {\n const entityInfo = this.metadata.Entities.find(e => e.Name === entityName);\n if (!entityInfo) {\n return null;\n }\n\n const primaryKeys = entityInfo.PrimaryKeys;\n if (primaryKeys.length === 0) {\n return null;\n }\n\n // Single primary key\n if (primaryKeys.length === 1) {\n const pkField = primaryKeys[0].Name;\n const pkValue = record[pkField];\n\n if (!pkValue) {\n return null;\n }\n\n return CompositeKey.FromID(pkValue.toString());\n }\n\n // Composite primary key\n const keyPairs: { FieldName: string; Value: string }[] = [];\n for (const pk of primaryKeys) {\n const value = record[pk.Name];\n if (!value) {\n return null;\n }\n keyPairs.push({ FieldName: pk.Name, Value: value.toString() });\n }\n\n return CompositeKey.FromKeyValuePairs(keyPairs);\n }\n\n /**\n * Check if a database record exists in metadata files\n */\n private checkIfInMetadata(\n entityName: string,\n primaryKey: CompositeKey,\n records: FlattenedRecord[]\n ): boolean {\n const keyString = primaryKey.ToConcatenatedString();\n\n for (const record of records) {\n if (record.entityName !== entityName) {\n continue;\n }\n\n const recordKey = this.extractPrimaryKey(record);\n if (recordKey && recordKey.ToConcatenatedString() === keyString) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get orphaned references (database-only records not in metadata)\n * These will prevent deletion unless handled\n */\n getOrphanedReferences(references: DatabaseReference[]): DatabaseReference[] {\n return references.filter(ref => !ref.existsInMetadata);\n }\n\n /**\n * Get metadata references (records in metadata that reference deletion targets)\n * These should already be marked for deletion if the user set things up correctly\n */\n getMetadataReferences(references: DatabaseReference[]): DatabaseReference[] {\n return references.filter(ref => ref.existsInMetadata);\n }\n}\n"]}
1
+ {"version":3,"file":"database-reference-scanner.js","sourceRoot":"","sources":["../../src/lib/database-reference-scanner.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { Metadata, UserInfo } from '@memberjunction/core';
2
- import { FlattenedRecord, ReverseDependency } from './record-dependency-analyzer';
3
- import { DatabaseReference } from './database-reference-scanner';
2
+ import { FlattenedRecord, ReverseDependency } from './record-dependency-analyzer.js';
3
+ import { DatabaseReference } from './database-reference-scanner.js';
4
4
  /**
5
5
  * Complete audit result for deletion operations
6
6
  */
@@ -9,6 +9,7 @@ export interface DeletionAudit {
9
9
  implicitDeletes: Map<string, FlattenedRecord>;
10
10
  alreadyDeleted: Map<string, FlattenedRecord>;
11
11
  databaseOnlyReferences: DatabaseReference[];
12
+ databaseOnlyDeletions: FlattenedRecord[];
12
13
  reverseDependencies: Map<string, ReverseDependency[]>;
13
14
  deletionLevels: FlattenedRecord[][];
14
15
  circularDependencies: string[][];
@@ -33,9 +34,10 @@ export declare class DeletionAuditor {
33
34
  * 5. Circular dependencies
34
35
  *
35
36
  * @param allRecords All flattened records from all metadata files
37
+ * @param deleteDbOnly If true, includes database-only references in the deletion levels
36
38
  * @returns Complete deletion audit
37
39
  */
38
- auditDeletions(allRecords: FlattenedRecord[]): Promise<DeletionAudit>;
40
+ auditDeletions(allRecords: FlattenedRecord[], deleteDbOnly?: boolean): Promise<DeletionAudit>;
39
41
  /**
40
42
  * Find all records marked with delete: true
41
43
  */
@@ -55,6 +57,18 @@ export declare class DeletionAuditor {
55
57
  * These will prevent deletion unless handled
56
58
  */
57
59
  private findOrphanedReferences;
60
+ /**
61
+ * Create synthetic FlattenedRecord objects from database-only references.
62
+ * These records exist in the database but not in metadata files, and they
63
+ * reference records that are being deleted. When deleteDbOnly is enabled,
64
+ * these synthetic records are included in the deletion levels so they are
65
+ * deleted before the records they reference.
66
+ *
67
+ * @param databaseReferences All database references found
68
+ * @param existingMetadataRecords Metadata records that exist in the database
69
+ * @returns Synthetic FlattenedRecord objects for database-only references
70
+ */
71
+ private createSyntheticRecordsFromDatabaseReferences;
58
72
  /**
59
73
  * Check for circular dependencies among records to delete
60
74
  * This would prevent safe deletion order
@@ -74,3 +88,4 @@ export declare class DeletionAuditor {
74
88
  */
75
89
  requiresConfirmation(audit: DeletionAudit): boolean;
76
90
  }
91
+ //# sourceMappingURL=deletion-auditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deletion-auditor.d.ts","sourceRoot":"","sources":["../../src/lib/deletion-auditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACH,eAAe,EACf,iBAAiB,EAEpB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAA4B,MAAM,8BAA8B,CAAC;AAG3F;;GAEG;AACH,MAAM,WAAW,aAAa;IAE1B,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAG9C,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAG9C,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAG7C,sBAAsB,EAAE,iBAAiB,EAAE,CAAC;IAI5C,qBAAqB,EAAE,eAAe,EAAE,CAAC;IAGzC,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAGtD,cAAc,EAAE,eAAe,EAAE,EAAE,CAAC;IAGpC,oBAAoB,EAAE,MAAM,EAAE,EAAE,CAAC;IACjC,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;CAC3C;AAED;;;GAGG;AACH,qBAAa,eAAe;IAEpB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,WAAW;gBADX,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,QAAQ;IAGjC;;;;;;;;;;;;;OAaG;IACG,cAAc,CAAC,UAAU,EAAE,eAAe,EAAE,EAAE,YAAY,GAAE,OAAe,GAAG,OAAO,CAAC,aAAa,CAAC;IA8F1G;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAY3B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAmC3B;;;OAGG;YACW,oBAAoB;IA+BlC;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAqB9B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,4CAA4C;IAsEpD;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IA2ChC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAO5B;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;IAKtC;;;OAGG;IACH,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;CAGtD"}
@@ -1,17 +1,12 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DeletionAuditor = void 0;
4
- const record_dependency_analyzer_1 = require("./record-dependency-analyzer");
5
- const database_reference_scanner_1 = require("./database-reference-scanner");
6
- const entity_foreign_key_helper_1 = require("./entity-foreign-key-helper");
7
- const sync_engine_1 = require("./sync-engine");
1
+ import { RecordDependencyAnalyzer } from './record-dependency-analyzer.js';
2
+ import { DatabaseReferenceScanner } from './database-reference-scanner.js';
3
+ import { EntityForeignKeyHelper } from './entity-foreign-key-helper.js';
4
+ import { SyncEngine } from './sync-engine.js';
8
5
  /**
9
6
  * Performs comprehensive deletion auditing across all metadata files
10
7
  * Identifies all records that need to be deleted, in what order, and potential issues
11
8
  */
12
- class DeletionAuditor {
13
- metadata;
14
- contextUser;
9
+ export class DeletionAuditor {
15
10
  constructor(metadata, contextUser) {
16
11
  this.metadata = metadata;
17
12
  this.contextUser = contextUser;
@@ -27,13 +22,14 @@ class DeletionAuditor {
27
22
  * 5. Circular dependencies
28
23
  *
29
24
  * @param allRecords All flattened records from all metadata files
25
+ * @param deleteDbOnly If true, includes database-only references in the deletion levels
30
26
  * @returns Complete deletion audit
31
27
  */
32
- async auditDeletions(allRecords) {
28
+ async auditDeletions(allRecords, deleteDbOnly = false) {
33
29
  // Step 1: Identify records explicitly marked for deletion
34
30
  const explicitDeletes = this.findExplicitDeletes(allRecords);
35
31
  // Step 2: Build reverse dependency map for all records
36
- const analyzer = new record_dependency_analyzer_1.RecordDependencyAnalyzer();
32
+ const analyzer = new RecordDependencyAnalyzer();
37
33
  const reverseDependencies = analyzer.buildReverseDependencyMap(allRecords);
38
34
  // Step 3: Find implicit deletes (records that depend on explicit deletes)
39
35
  const implicitDeletes = this.findImplicitDeletes(explicitDeletes, reverseDependencies, allRecords);
@@ -41,22 +37,51 @@ class DeletionAuditor {
41
37
  const allDeletes = new Map([...explicitDeletes, ...implicitDeletes]);
42
38
  const { existingRecords, alreadyDeleted } = await this.checkRecordExistence(Array.from(allDeletes.values()));
43
39
  // Step 5: Scan database for existing references (only for records that still exist)
44
- const reverseFKMap = entity_foreign_key_helper_1.EntityForeignKeyHelper.buildReverseFKMap(this.metadata);
45
- const scanner = new database_reference_scanner_1.DatabaseReferenceScanner(this.metadata, this.contextUser);
40
+ const reverseFKMap = EntityForeignKeyHelper.buildReverseFKMap(this.metadata);
41
+ const scanner = new DatabaseReferenceScanner(this.metadata, this.contextUser);
46
42
  const databaseReferences = await scanner.scanForReferences(existingRecords, reverseFKMap, allRecords // Pass all metadata records for correct exists-in-metadata check
47
43
  );
48
44
  // Step 6: Identify orphaned references (DB records not in metadata)
49
45
  const orphanedReferences = this.findOrphanedReferences(databaseReferences, allRecords);
50
- // Step 7: Calculate deletion order (reverse topological sort) - only for existing records
51
- const deletionLevels = analyzer.reverseTopologicalSort(existingRecords, reverseDependencies);
46
+ // Step 6.5: Create synthetic FlattenedRecords for database-only references
47
+ // These represent records in the DB that reference records being deleted but are not in metadata
48
+ const databaseOnlyDeletions = this.createSyntheticRecordsFromDatabaseReferences(databaseReferences, existingRecords);
49
+ // Step 7: Calculate deletion order (reverse topological sort)
50
+ // If deleteDbOnly is enabled, include synthetic records in the sort
51
+ let recordsForSort = existingRecords;
52
+ let reverseDepsForSort = reverseDependencies;
53
+ if (deleteDbOnly && databaseOnlyDeletions.length > 0) {
54
+ // Combine metadata records with synthetic DB-only records
55
+ recordsForSort = [...existingRecords, ...databaseOnlyDeletions];
56
+ // Build reverse dependencies for synthetic records
57
+ reverseDepsForSort = new Map(reverseDependencies);
58
+ for (const syntheticRecord of databaseOnlyDeletions) {
59
+ // Each synthetic record depends on a metadata record being deleted
60
+ // Add the synthetic record as a dependent of the referenced record
61
+ for (const depId of syntheticRecord.dependencies) {
62
+ if (!reverseDepsForSort.has(depId)) {
63
+ reverseDepsForSort.set(depId, []);
64
+ }
65
+ reverseDepsForSort.get(depId).push({
66
+ recordId: depId,
67
+ dependentId: syntheticRecord.id,
68
+ entityName: syntheticRecord.entityName,
69
+ fieldName: null, // We don't track which field for synthetic records
70
+ filePath: syntheticRecord.path
71
+ });
72
+ }
73
+ }
74
+ }
75
+ const deletionLevels = analyzer.reverseTopologicalSort(recordsForSort, reverseDepsForSort);
52
76
  // Step 8: Check for circular dependencies among records to delete
53
- const circularDependencies = this.findCircularDependencies(existingRecords);
77
+ const circularDependencies = this.findCircularDependencies(recordsForSort);
54
78
  return {
55
79
  explicitDeletes,
56
80
  implicitDeletes,
57
81
  alreadyDeleted,
58
82
  databaseOnlyReferences: databaseReferences,
59
- reverseDependencies,
83
+ databaseOnlyDeletions,
84
+ reverseDependencies: reverseDepsForSort,
60
85
  deletionLevels,
61
86
  circularDependencies,
62
87
  orphanedReferences
@@ -111,7 +136,7 @@ class DeletionAuditor {
111
136
  const existingRecords = [];
112
137
  const alreadyDeleted = new Map();
113
138
  // Import SyncEngine to check record existence
114
- const syncEngine = new sync_engine_1.SyncEngine(this.contextUser);
139
+ const syncEngine = new SyncEngine(this.contextUser);
115
140
  for (const record of records) {
116
141
  try {
117
142
  // Check if record exists in database
@@ -149,6 +174,73 @@ class DeletionAuditor {
149
174
  }
150
175
  return orphaned;
151
176
  }
177
+ /**
178
+ * Create synthetic FlattenedRecord objects from database-only references.
179
+ * These records exist in the database but not in metadata files, and they
180
+ * reference records that are being deleted. When deleteDbOnly is enabled,
181
+ * these synthetic records are included in the deletion levels so they are
182
+ * deleted before the records they reference.
183
+ *
184
+ * @param databaseReferences All database references found
185
+ * @param existingMetadataRecords Metadata records that exist in the database
186
+ * @returns Synthetic FlattenedRecord objects for database-only references
187
+ */
188
+ createSyntheticRecordsFromDatabaseReferences(databaseReferences, existingMetadataRecords) {
189
+ const syntheticRecords = [];
190
+ const seenPrimaryKeys = new Set();
191
+ // Build a map of metadata record primary keys for quick lookup
192
+ const metadataRecordIdMap = new Map();
193
+ for (const record of existingMetadataRecords) {
194
+ const pkValue = record.record.primaryKey?.ID || record.record.fields?.ID;
195
+ if (pkValue) {
196
+ metadataRecordIdMap.set(`${record.entityName}:${pkValue}`, record);
197
+ }
198
+ }
199
+ for (const ref of databaseReferences) {
200
+ // Only process database-only references (not in metadata)
201
+ if (ref.existsInMetadata) {
202
+ continue;
203
+ }
204
+ // Dedupe by primary key to avoid creating multiple synthetic records for same DB record
205
+ const pkString = ref.primaryKey.ToConcatenatedString();
206
+ const dedupeKey = `${ref.entityName}:${pkString}`;
207
+ if (seenPrimaryKeys.has(dedupeKey)) {
208
+ continue;
209
+ }
210
+ seenPrimaryKeys.add(dedupeKey);
211
+ // Find the metadata record this reference points to
212
+ const referencedPkValue = ref.referencedKey.KeyValuePairs[0]?.Value;
213
+ const metadataRecordKey = `${ref.referencedEntity}:${referencedPkValue}`;
214
+ const referencedMetadataRecord = metadataRecordIdMap.get(metadataRecordKey);
215
+ // Create a synthetic FlattenedRecord for this database-only reference
216
+ const syntheticId = `DB_ONLY_${ref.entityName}_${pkString}`;
217
+ // Build the primary key object from CompositeKey
218
+ const primaryKeyObj = {};
219
+ for (const kvp of ref.primaryKey.KeyValuePairs) {
220
+ primaryKeyObj[kvp.FieldName] = kvp.Value;
221
+ }
222
+ const syntheticRecord = {
223
+ record: {
224
+ primaryKey: primaryKeyObj,
225
+ fields: {}, // We don't have the full record data, just the primary key
226
+ },
227
+ entityName: ref.entityName,
228
+ parentContext: undefined,
229
+ depth: 0,
230
+ path: '<DATABASE>', // Special marker indicating this is a DB-only record
231
+ dependencies: new Set(),
232
+ id: syntheticId,
233
+ originalIndex: -1, // Not from a file
234
+ };
235
+ // Add dependency on the referenced metadata record
236
+ // This ensures the synthetic record is deleted BEFORE the metadata record
237
+ if (referencedMetadataRecord) {
238
+ syntheticRecord.dependencies.add(referencedMetadataRecord.id);
239
+ }
240
+ syntheticRecords.push(syntheticRecord);
241
+ }
242
+ return syntheticRecords;
243
+ }
152
244
  /**
153
245
  * Check for circular dependencies among records to delete
154
246
  * This would prevent safe deletion order
@@ -215,5 +307,4 @@ class DeletionAuditor {
215
307
  return audit.implicitDeletes.size > 0;
216
308
  }
217
309
  }
218
- exports.DeletionAuditor = DeletionAuditor;
219
310
  //# sourceMappingURL=deletion-auditor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"deletion-auditor.js","sourceRoot":"","sources":["../../src/lib/deletion-auditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata, UserInfo } from '@memberjunction/core';\nimport {\n FlattenedRecord,\n ReverseDependency,\n RecordDependencyAnalyzer\n} from './record-dependency-analyzer';\nimport { DatabaseReference, DatabaseReferenceScanner } from './database-reference-scanner';\nimport { EntityForeignKeyHelper } from './entity-foreign-key-helper';\nimport { SyncEngine } from './sync-engine';\n/**\n * Complete audit result for deletion operations\n */\nexport interface DeletionAudit {\n // Records explicitly marked for deletion (delete: true in metadata)\n explicitDeletes: Map<string, FlattenedRecord>;\n\n // Records that must be deleted due to FK dependencies\n implicitDeletes: Map<string, FlattenedRecord>;\n\n // Records marked for deletion that already don't exist in the database\n alreadyDeleted: Map<string, FlattenedRecord>;\n\n // Database records that reference records being deleted (not in metadata)\n databaseOnlyReferences: DatabaseReference[];\n\n // Reverse dependency map: recordId -> records that depend on it\n reverseDependencies: Map<string, ReverseDependency[]>;\n\n // Deletion order (reverse topological sort) - highest dependency level first\n deletionLevels: FlattenedRecord[][];\n\n // Errors/warnings\n circularDependencies: string[][];\n orphanedReferences: ReverseDependency[];\n}\n\n/**\n * Performs comprehensive deletion auditing across all metadata files\n * Identifies all records that need to be deleted, in what order, and potential issues\n */\nexport class DeletionAuditor {\n constructor(\n private metadata: Metadata,\n private contextUser: UserInfo\n ) {}\n\n /**\n * Perform comprehensive deletion audit across all metadata files\n *\n * This analyzes:\n * 1. Which records are explicitly marked for deletion\n * 2. Which records must be implicitly deleted (due to FK constraints)\n * 3. Database-only references that will prevent deletion\n * 4. Correct deletion order (reverse topological sort)\n * 5. Circular dependencies\n *\n * @param allRecords All flattened records from all metadata files\n * @returns Complete deletion audit\n */\n async auditDeletions(allRecords: FlattenedRecord[]): Promise<DeletionAudit> {\n // Step 1: Identify records explicitly marked for deletion\n const explicitDeletes = this.findExplicitDeletes(allRecords);\n\n // Step 2: Build reverse dependency map for all records\n const analyzer = new RecordDependencyAnalyzer();\n const reverseDependencies = analyzer.buildReverseDependencyMap(allRecords);\n\n // Step 3: Find implicit deletes (records that depend on explicit deletes)\n const implicitDeletes = this.findImplicitDeletes(\n explicitDeletes,\n reverseDependencies,\n allRecords\n );\n\n // Step 4: Check which records actually exist in the database\n const allDeletes = new Map([...explicitDeletes, ...implicitDeletes]);\n const { existingRecords, alreadyDeleted } = await this.checkRecordExistence(\n Array.from(allDeletes.values())\n );\n\n // Step 5: Scan database for existing references (only for records that still exist)\n const reverseFKMap = EntityForeignKeyHelper.buildReverseFKMap(this.metadata);\n const scanner = new DatabaseReferenceScanner(this.metadata, this.contextUser);\n\n const databaseReferences = await scanner.scanForReferences(\n existingRecords,\n reverseFKMap,\n allRecords // Pass all metadata records for correct exists-in-metadata check\n );\n\n // Step 6: Identify orphaned references (DB records not in metadata)\n const orphanedReferences = this.findOrphanedReferences(\n databaseReferences,\n allRecords\n );\n\n // Step 7: Calculate deletion order (reverse topological sort) - only for existing records\n const deletionLevels = analyzer.reverseTopologicalSort(\n existingRecords,\n reverseDependencies\n );\n\n // Step 8: Check for circular dependencies among records to delete\n const circularDependencies = this.findCircularDependencies(existingRecords);\n\n return {\n explicitDeletes,\n implicitDeletes,\n alreadyDeleted,\n databaseOnlyReferences: databaseReferences,\n reverseDependencies,\n deletionLevels,\n circularDependencies,\n orphanedReferences\n };\n }\n\n /**\n * Find all records marked with delete: true\n */\n private findExplicitDeletes(records: FlattenedRecord[]): Map<string, FlattenedRecord> {\n const deletes = new Map<string, FlattenedRecord>();\n\n for (const record of records) {\n if (record.record.deleteRecord?.delete === true) {\n deletes.set(record.id, record);\n }\n }\n\n return deletes;\n }\n\n /**\n * Find all records that depend on records being deleted (implicit deletes)\n * Uses BFS to find transitive dependents\n */\n private findImplicitDeletes(\n explicitDeletes: Map<string, FlattenedRecord>,\n reverseDependencies: Map<string, ReverseDependency[]>,\n allRecords: FlattenedRecord[]\n ): Map<string, FlattenedRecord> {\n const implicitDeletes = new Map<string, FlattenedRecord>();\n const visited = new Set<string>();\n\n // BFS to find all transitive dependents\n const queue = Array.from(explicitDeletes.keys());\n\n while (queue.length > 0) {\n const recordId = queue.shift()!;\n if (visited.has(recordId)) continue;\n visited.add(recordId);\n\n const dependents = reverseDependencies.get(recordId) || [];\n\n for (const dep of dependents) {\n // Add dependent to implicit deletes if not already explicit\n if (!explicitDeletes.has(dep.dependentId) &&\n !implicitDeletes.has(dep.dependentId)) {\n\n const record = allRecords.find(r => r.id === dep.dependentId);\n if (record) {\n implicitDeletes.set(dep.dependentId, record);\n queue.push(dep.dependentId);\n }\n }\n }\n }\n\n return implicitDeletes;\n }\n\n /**\n * Check which records actually exist in the database\n * Returns records separated into existing (need deletion) and already deleted\n */\n private async checkRecordExistence(\n records: FlattenedRecord[]\n ): Promise<{ existingRecords: FlattenedRecord[]; alreadyDeleted: Map<string, FlattenedRecord> }> {\n const existingRecords: FlattenedRecord[] = [];\n const alreadyDeleted = new Map<string, FlattenedRecord>();\n\n // Import SyncEngine to check record existence\n const syncEngine = new SyncEngine(this.contextUser);\n\n for (const record of records) {\n try {\n // Check if record exists in database\n const existingEntity = await syncEngine.loadEntity(\n record.entityName,\n record.record.primaryKey || {}\n );\n\n if (existingEntity) {\n existingRecords.push(record);\n } else {\n alreadyDeleted.set(record.id, record);\n }\n } catch (error) {\n // If we can't check, assume it exists to be safe\n existingRecords.push(record);\n }\n }\n\n return { existingRecords, alreadyDeleted };\n }\n\n /**\n * Find orphaned references (database records not in metadata files)\n * These will prevent deletion unless handled\n */\n private findOrphanedReferences(\n databaseReferences: DatabaseReference[],\n allRecords: FlattenedRecord[]\n ): ReverseDependency[] {\n const orphaned: ReverseDependency[] = [];\n\n for (const ref of databaseReferences) {\n if (!ref.existsInMetadata) {\n orphaned.push({\n recordId: ref.referencedKey.ToConcatenatedString(),\n dependentId: ref.primaryKey.ToConcatenatedString(),\n entityName: ref.entityName,\n fieldName: ref.referencingField,\n filePath: '<DATABASE ONLY>'\n });\n }\n }\n\n return orphaned;\n }\n\n /**\n * Check for circular dependencies among records to delete\n * This would prevent safe deletion order\n */\n private findCircularDependencies(records: FlattenedRecord[]): string[][] {\n const cycles: string[][] = [];\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n\n const detectCycle = (record: FlattenedRecord, path: string[]): boolean => {\n visited.add(record.id);\n recursionStack.add(record.id);\n path.push(`${record.entityName}:${this.getRecordDisplayName(record)}`);\n\n for (const depId of record.dependencies) {\n // Only check dependencies among records being deleted\n const depRecord = records.find(r => r.id === depId);\n if (!depRecord) continue;\n\n if (!visited.has(depId)) {\n if (detectCycle(depRecord, [...path])) {\n return true;\n }\n } else if (recursionStack.has(depId)) {\n // Found a cycle\n const cycleStart = path.findIndex(p => p.startsWith(depRecord.entityName));\n const cycle = path.slice(cycleStart);\n cycle.push(`${depRecord.entityName}:${this.getRecordDisplayName(depRecord)}`);\n cycles.push(cycle);\n return true;\n }\n }\n\n recursionStack.delete(record.id);\n return false;\n };\n\n // Check all records for cycles\n for (const record of records) {\n if (!visited.has(record.id)) {\n detectCycle(record, []);\n }\n }\n\n return cycles;\n }\n\n /**\n * Get a display name for a record (for error messages)\n */\n private getRecordDisplayName(record: FlattenedRecord): string {\n return record.record.fields?.Name ||\n record.record.primaryKey?.ID ||\n record.record.fields?.ID ||\n record.id;\n }\n\n /**\n * Check if deletion audit has blocking issues\n */\n isValid(audit: DeletionAudit): boolean {\n return audit.orphanedReferences.length === 0 &&\n audit.circularDependencies.length === 0;\n }\n\n /**\n * Check if deletion audit requires user confirmation\n * (due to implicit deletes)\n */\n requiresConfirmation(audit: DeletionAudit): boolean {\n return audit.implicitDeletes.size > 0;\n }\n}\n"]}
1
+ {"version":3,"file":"deletion-auditor.js","sourceRoot":"","sources":["../../src/lib/deletion-auditor.ts"],"names":[],"mappings":"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"}