@@ -21,36 +21,47 @@ const __dirname = dirname(__filename);
2121export function loadConfig ( configPath = null ) {
2222 try {
2323 let config ;
24+ let source ;
2425
2526 // Handle different input types
2627 if ( configPath === null || configPath === undefined ) {
2728 // Default to config.yaml in project root
2829 const path = join ( __dirname , '..' , 'config.yaml' ) ;
30+ logger . debug ( `[ConfigLoader.loadConfig] Loading config from default path: ${ path } ` ) ;
2931 const fileContent = readFileSync ( path , 'utf8' ) ;
3032 config = parse ( fileContent ) ;
33+ source = path ;
3134 } else if ( typeof configPath === 'string' ) {
3235 // Path to config file
36+ logger . debug ( `[ConfigLoader.loadConfig] Loading config from: ${ configPath } ` ) ;
3337 const fileContent = readFileSync ( configPath , 'utf8' ) ;
3438 config = parse ( fileContent ) ;
39+ source = configPath ;
3540 } else if ( typeof configPath === 'object' ) {
3641 // Config object passed directly (for testing)
42+ logger . debug ( '[ConfigLoader.loadConfig] Using config object passed directly' ) ;
3743 // Check if it's an options object with 'config' property
3844 if ( configPath . config ) {
3945 config = configPath . config ;
4046 } else {
4147 config = configPath ;
4248 }
49+ source = 'object' ;
4350 } else {
4451 throw new Error ( 'configPath must be a string, object, or null' ) ;
4552 }
4653
4754 if ( ! config ) {
55+ logger . error ( '[ConfigLoader.loadConfig] Failed to parse configuration' ) ;
4856 throw new Error ( 'Failed to parse configuration' ) ;
4957 }
5058
59+ logger . info ( `[ConfigLoader.loadConfig] Successfully loaded config from: ${ source } ` ) ;
60+
5161 // Normalize to multi-table format if needed
5262 return normalizeConfig ( config ) ;
5363 } catch ( error ) {
64+ logger . error ( `[ConfigLoader.loadConfig] Configuration loading failed: ${ error . message } ` ) ;
5465 throw new Error ( `Failed to load configuration: ${ error . message } ` ) ;
5566 }
5667}
@@ -64,17 +75,22 @@ export function loadConfig(configPath = null) {
6475 */
6576function normalizeConfig ( config ) {
6677 if ( ! config . bigquery ) {
78+ logger . error ( '[ConfigLoader.normalizeConfig] bigquery section missing in configuration' ) ;
6779 throw new Error ( 'bigquery section missing in configuration' ) ;
6880 }
6981
7082 // Check if already in multi-table format
7183 if ( config . bigquery . tables && Array . isArray ( config . bigquery . tables ) ) {
84+ logger . info (
85+ `[ConfigLoader.normalizeConfig] Config already in multi-table format with ${ config . bigquery . tables . length } tables`
86+ ) ;
7287 // Validate multi-table configuration
7388 validateMultiTableConfig ( config ) ;
7489 return config ;
7590 }
7691
7792 // Legacy single-table format - wrap in tables array
93+ logger . info ( '[ConfigLoader.normalizeConfig] Converting legacy single-table config to multi-table format' ) ;
7894 const legacyBigQueryConfig = config . bigquery ;
7995
8096 // Extract table-specific config
@@ -92,6 +108,10 @@ function normalizeConfig(config) {
92108 } ,
93109 } ;
94110
111+ logger . debug (
112+ `[ConfigLoader.normalizeConfig] Created table config: ${ tableConfig . dataset } .${ tableConfig . table } -> ${ tableConfig . targetTable } `
113+ ) ;
114+
95115 // Create normalized multi-table config
96116 const normalizedConfig = {
97117 operations : config . operations , // Preserve operations config if present
@@ -108,6 +128,7 @@ function normalizeConfig(config) {
108128 } ,
109129 } ;
110130
131+ logger . info ( '[ConfigLoader.normalizeConfig] Successfully normalized config to multi-table format' ) ;
111132 return normalizedConfig ;
112133}
113134
@@ -118,11 +139,15 @@ function normalizeConfig(config) {
118139 * @private
119140 */
120141function validateMultiTableConfig ( config ) {
142+ logger . debug ( '[ConfigLoader.validateMultiTableConfig] Validating multi-table configuration' ) ;
143+
121144 if ( ! config . bigquery . tables || ! Array . isArray ( config . bigquery . tables ) ) {
145+ logger . error ( '[ConfigLoader.validateMultiTableConfig] bigquery.tables must be an array' ) ;
122146 throw new Error ( 'bigquery.tables must be an array' ) ;
123147 }
124148
125149 if ( config . bigquery . tables . length === 0 ) {
150+ logger . error ( '[ConfigLoader.validateMultiTableConfig] bigquery.tables array cannot be empty' ) ;
126151 throw new Error ( 'bigquery.tables array cannot be empty' ) ;
127152 }
128153
@@ -132,29 +157,38 @@ function validateMultiTableConfig(config) {
132157 for ( const table of config . bigquery . tables ) {
133158 // Check required fields
134159 if ( ! table . id ) {
160+ logger . error ( '[ConfigLoader.validateMultiTableConfig] Missing required field: table.id' ) ;
135161 throw new Error ( 'Missing required field: table.id' ) ;
136162 }
137163 if ( ! table . dataset ) {
164+ logger . error ( `[ConfigLoader.validateMultiTableConfig] Missing 'dataset' for table: ${ table . id } ` ) ;
138165 throw new Error ( `Missing required field 'dataset' for table: ${ table . id } ` ) ;
139166 }
140167 if ( ! table . table ) {
168+ logger . error ( `[ConfigLoader.validateMultiTableConfig] Missing 'table' for table: ${ table . id } ` ) ;
141169 throw new Error ( `Missing required field 'table' for table: ${ table . id } ` ) ;
142170 }
143171 if ( ! table . timestampColumn ) {
172+ logger . error ( `[ConfigLoader.validateMultiTableConfig] Missing 'timestampColumn' for table: ${ table . id } ` ) ;
144173 throw new Error ( `Missing required field 'timestampColumn' for table: ${ table . id } ` ) ;
145174 }
146175 if ( ! table . targetTable ) {
176+ logger . error ( `[ConfigLoader.validateMultiTableConfig] Missing 'targetTable' for table: ${ table . id } ` ) ;
147177 throw new Error ( `Missing required field 'targetTable' for table: ${ table . id } ` ) ;
148178 }
149179
150180 // Check for duplicate IDs
151181 if ( tableIds . has ( table . id ) ) {
182+ logger . error ( `[ConfigLoader.validateMultiTableConfig] Duplicate table ID: ${ table . id } ` ) ;
152183 throw new Error ( `Duplicate table ID: ${ table . id } ` ) ;
153184 }
154185 tableIds . add ( table . id ) ;
155186
156187 // Check for duplicate target Harper tables
157188 if ( targetTables . has ( table . targetTable ) ) {
189+ logger . error (
190+ `[ConfigLoader.validateMultiTableConfig] Duplicate targetTable '${ table . targetTable } ' for: ${ table . id } `
191+ ) ;
158192 throw new Error (
159193 `Duplicate targetTable '${ table . targetTable } ' for table: ${ table . id } . ` +
160194 `Each BigQuery table must sync to a DIFFERENT Harper table. ` +
@@ -164,7 +198,15 @@ function validateMultiTableConfig(config) {
164198 ) ;
165199 }
166200 targetTables . add ( table . targetTable ) ;
201+
202+ logger . debug (
203+ `[ConfigLoader.validateMultiTableConfig] Validated table: ${ table . id } (${ table . dataset } .${ table . table } -> ${ table . targetTable } )`
204+ ) ;
167205 }
206+
207+ logger . info (
208+ `[ConfigLoader.validateMultiTableConfig] Successfully validated ${ config . bigquery . tables . length } table configurations`
209+ ) ;
168210}
169211
170212/**
0 commit comments