@memberjunction/metadata-sync 2.46.0 → 2.48.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.
@@ -1,4 +1,34 @@
1
+ /**
2
+ * @fileoverview Pull command implementation for MetadataSync
3
+ * @module commands/pull
4
+ *
5
+ * This module implements the pull command which retrieves metadata records from
6
+ * the MemberJunction database and saves them as local JSON files. It supports:
7
+ * - Filtering records with SQL expressions
8
+ * - Pulling related entities with foreign key relationships
9
+ * - Externalizing large text fields to separate files
10
+ * - Creating multi-record JSON files
11
+ * - Recursive directory search for entity configurations
12
+ */
1
13
  import { Command } from '@oclif/core';
14
+ /**
15
+ * Pull metadata records from database to local files
16
+ *
17
+ * @class Pull
18
+ * @extends Command
19
+ *
20
+ * @example
21
+ * ```bash
22
+ * # Pull all records for an entity
23
+ * mj-sync pull --entity="AI Prompts"
24
+ *
25
+ * # Pull with filter
26
+ * mj-sync pull --entity="AI Prompts" --filter="CategoryID='123'"
27
+ *
28
+ * # Pull to multi-record file
29
+ * mj-sync pull --entity="AI Prompts" --multi-file="all-prompts.json"
30
+ * ```
31
+ */
2
32
  export default class Pull extends Command {
3
33
  static description: string;
4
34
  static examples: string[];
@@ -6,13 +36,203 @@ export default class Pull extends Command {
6
36
  entity: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
7
37
  filter: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
38
  'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
39
+ 'multi-file': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
40
+ verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
9
41
  };
10
42
  run(): Promise<void>;
43
+ /**
44
+ * Find directories containing configuration for the specified entity
45
+ *
46
+ * Recursively searches the current working directory for .mj-sync.json files
47
+ * that specify the given entity name. Returns all matching directories to
48
+ * allow user selection when multiple locations exist.
49
+ *
50
+ * @param entityName - Name of the entity to search for
51
+ * @returns Promise resolving to array of directory paths
52
+ * @private
53
+ */
11
54
  private findEntityDirectories;
55
+ /**
56
+ * Process a single record and save to file
57
+ *
58
+ * Converts a database record into the file format and writes it to disk.
59
+ * This is a wrapper around processRecordData that handles file writing.
60
+ *
61
+ * @param record - Raw database record
62
+ * @param primaryKey - Primary key fields and values
63
+ * @param targetDir - Directory to save the file
64
+ * @param entityConfig - Entity configuration with pull settings
65
+ * @param syncEngine - Sync engine instance
66
+ * @returns Promise that resolves when file is written
67
+ * @private
68
+ */
12
69
  private processRecord;
70
+ /**
71
+ * Process record data for storage
72
+ *
73
+ * Transforms a raw database record into the RecordData format used for file storage.
74
+ * Handles field externalization, related entity pulling, and checksum calculation.
75
+ *
76
+ * @param record - Raw database record
77
+ * @param primaryKey - Primary key fields and values
78
+ * @param targetDir - Directory where files will be saved
79
+ * @param entityConfig - Entity configuration with defaults and settings
80
+ * @param syncEngine - Sync engine for checksum calculation
81
+ * @param flags - Command flags
82
+ * @param isNewRecord - Whether this is a new record
83
+ * @param existingRecordData - Existing record data to preserve field selection
84
+ * @returns Promise resolving to formatted RecordData
85
+ * @private
86
+ */
87
+ private processRecordData;
88
+ /**
89
+ * Convert a foreign key value to a @lookup reference
90
+ *
91
+ * Looks up the related record and creates a @lookup string that can be
92
+ * resolved during push operations.
93
+ *
94
+ * @param foreignKeyValue - The foreign key value (ID)
95
+ * @param targetEntity - Name of the target entity
96
+ * @param targetField - Field in target entity to use for lookup
97
+ * @param syncEngine - Sync engine instance
98
+ * @returns @lookup string or null if lookup fails
99
+ * @private
100
+ */
101
+ private convertToLookup;
102
+ /**
103
+ * Determine if a field should be saved to an external file
104
+ *
105
+ * Checks if a field is configured for externalization or contains substantial
106
+ * text content that would be better stored in a separate file.
107
+ *
108
+ * @param fieldName - Name of the field to check
109
+ * @param fieldValue - Value of the field
110
+ * @param entityConfig - Entity configuration with externalization settings
111
+ * @returns Promise resolving to true if field should be externalized
112
+ * @private
113
+ */
13
114
  private shouldExternalizeField;
115
+ /**
116
+ * Create an external file for a field value
117
+ *
118
+ * Saves large text content to a separate file and returns the filename.
119
+ * Automatically determines appropriate file extension based on field name
120
+ * and content type (e.g., .md for prompts, .html for templates).
121
+ * Uses the entity's name field for the filename if available.
122
+ *
123
+ * @param targetDir - Directory to save the file
124
+ * @param record - Full record to extract name field from
125
+ * @param primaryKey - Primary key for filename generation fallback
126
+ * @param fieldName - Name of the field being externalized
127
+ * @param content - Content to write to the file
128
+ * @param entityConfig - Entity configuration
129
+ * @returns Promise resolving to the created filename
130
+ * @private
131
+ */
14
132
  private createExternalFile;
133
+ /**
134
+ * Build a filename from primary key values
135
+ *
136
+ * Creates a safe filename based on the entity's primary key values.
137
+ * Handles GUIDs by using first 8 characters, sanitizes special characters,
138
+ * and creates composite names for multi-field keys.
139
+ * Files are prefixed with a dot to follow the metadata file convention.
140
+ *
141
+ * @param primaryKey - Primary key fields and values
142
+ * @param entityConfig - Entity configuration (for future extension)
143
+ * @returns Filename with .json extension
144
+ * @private
145
+ */
15
146
  private buildFileName;
147
+ /**
148
+ * Pull related entities for a parent record
149
+ *
150
+ * Retrieves child records that have foreign key relationships to the parent.
151
+ * Converts foreign key values to @parent references and supports nested
152
+ * related entities for deep object graphs.
153
+ *
154
+ * @param parentRecord - Parent entity record
155
+ * @param relatedConfig - Configuration for related entities to pull
156
+ * @param syncEngine - Sync engine instance
157
+ * @returns Promise resolving to map of entity names to related records
158
+ * @private
159
+ */
16
160
  private pullRelatedEntities;
161
+ /**
162
+ * Find which field in the parent record contains a specific value
163
+ *
164
+ * Used to convert foreign key references to @parent references by finding
165
+ * the parent field that contains the foreign key value. Typically finds
166
+ * the primary key field but can match any field.
167
+ *
168
+ * @param parentRecord - Parent record to search
169
+ * @param value - Value to search for
170
+ * @returns Field name containing the value, or null if not found
171
+ * @private
172
+ */
17
173
  private findParentField;
174
+ /**
175
+ * Find existing files in a directory matching a pattern
176
+ *
177
+ * Searches for files that match the configured file pattern, used to identify
178
+ * which records already exist locally for smart update functionality.
179
+ *
180
+ * @param dir - Directory to search in
181
+ * @param pattern - Glob pattern to match files (e.g., "*.json")
182
+ * @returns Promise resolving to array of file paths
183
+ * @private
184
+ */
185
+ private findExistingFiles;
186
+ /**
187
+ * Load existing records from files and build a lookup map
188
+ *
189
+ * Reads all existing files and creates a map from primary key to file location,
190
+ * enabling efficient lookup during the update process.
191
+ *
192
+ * @param files - Array of file paths to load
193
+ * @param entityInfo - Entity metadata for primary key information
194
+ * @returns Map from primary key string to file info
195
+ * @private
196
+ */
197
+ private loadExistingRecords;
198
+ /**
199
+ * Create a string lookup key from primary key values
200
+ *
201
+ * Generates a consistent string representation of primary key values
202
+ * for use in maps and comparisons.
203
+ *
204
+ * @param primaryKey - Primary key field names and values
205
+ * @returns String representation of the primary key
206
+ * @private
207
+ */
208
+ private createPrimaryKeyLookup;
209
+ /**
210
+ * Merge two record data objects based on configured strategy
211
+ *
212
+ * Combines existing and new record data according to the merge strategy:
213
+ * - 'overwrite': Replace all fields with new values
214
+ * - 'merge': Combine fields, with new values taking precedence
215
+ * - 'skip': Keep existing record unchanged
216
+ *
217
+ * @param existing - Existing record data
218
+ * @param newData - New record data from database
219
+ * @param strategy - Merge strategy to apply
220
+ * @param preserveFields - Field names that should never be overwritten
221
+ * @returns Merged record data
222
+ * @private
223
+ */
224
+ private mergeRecords;
225
+ /**
226
+ * Create a backup of a file before updating
227
+ *
228
+ * Creates a timestamped backup copy of the file in a backup directory
229
+ * with the original filename, timestamp suffix, and .backup extension.
230
+ * The backup directory defaults to .backups but can be configured.
231
+ *
232
+ * @param filePath - Path to the file to backup
233
+ * @param backupDirName - Name of the backup directory (optional)
234
+ * @returns Promise that resolves when backup is created
235
+ * @private
236
+ */
237
+ private createBackup;
18
238
  }