@@ -218,46 +218,50 @@ export function evalColumns(
218218 schemaPath : string ,
219219) : void {
220220 if ( ! rule . columns || ! [ '.tsv' , '.tsv.gz' ] . includes ( context . extension ) ) return
221- const headers = [ ...Object . keys ( context . columns ) ]
222- for ( const [ ruleHeader , requirement ] of Object . entries ( rule . columns ) ) {
223- const columnObject : ColumnSchema = schema . objects . columns [ ruleHeader ]
221+ const columns = rule . columns as Record < string , string | { level : string } >
224222
225- // What is this?
226- if ( ! ( 'name' in columnObject ) || ! columnObject [ ' name' ] ) {
227- return
228- }
223+ const columnLookup = Object . fromEntries (
224+ Object . keys ( rule . columns ) . map ( ( col ) => [ schema . objects . columns [ col ] . name , col ] ) ,
225+ )
226+ const additionalColumns = Object . keys ( context . columns ) . filter ( ( name ) => ! ( name in columnLookup ) )
229227
230- const name = columnObject . name
231- if ( ! headers . includes ( name ) ) {
232- if (
233- getRequirement ( rule as ColumnRule , ruleHeader ) === 'required' &&
234- // A more precise error will be generated by evalInitialColumns
235- ! ( rule ?. initial_columns && rule . initial_columns . includes ( ruleHeader ) )
236- ) {
237- context . dataset . issues . add ( {
238- code : 'TSV_COLUMN_MISSING' ,
239- subCode : name ,
240- location : context . path ,
241- rule : schemaPath ,
242- } )
243- }
244- return
245- }
228+ for ( const name of new Set ( [ ...Object . keys ( columnLookup ) , ...additionalColumns ] ) ) {
229+ const ruleHeader = columnLookup [ name ]
230+ const sidecarDef = context . sidecar [ name ] as ColumnDefinition | undefined
231+ const requirement = getRequirement ( rule as ColumnRule , ruleHeader )
232+ const column = context . columns [ name ] as string [ ]
233+
234+ const issue = { subCode : name , location : context . path , rule : schemaPath }
246235
247236 let signature : ValueSignature
248- try {
249- signature = getValueSignature ( columnObject , context ?. sidecar [ name ] )
250- } catch ( e : any ) {
251- if ( e ?. code ) {
252- context . dataset . issues . add ( {
253- ...e ,
254- subCode : name ,
255- location : context . sidecarKeyOrigin [ name ] ,
256- rule : schemaPath ,
257- } )
258- signature = getValueSignature ( columnObject , undefined )
259- } else {
260- throw e
237+ if ( ! ruleHeader ) { // Additional column
238+ if ( requirement === 'not_allowed' || ! sidecarDef ) {
239+ continue
240+ }
241+ signature = extractDefinition ( sidecarDef )
242+ } else {
243+ const columnObject = schema . objects . columns [ ruleHeader ]
244+ if ( ! column ) {
245+ if ( requirement === 'required' && ! ( rule ?. initial_columns ?. includes ( ruleHeader ) ) ) {
246+ context . dataset . issues . add ( { code : 'TSV_COLUMN_MISSING' , ...issue } )
247+ }
248+ continue
249+ }
250+
251+ try {
252+ signature = getValueSignature ( columnObject , sidecarDef )
253+ } catch ( e : any ) {
254+ if ( e ?. code ) {
255+ context . dataset . issues . add ( {
256+ ...e ,
257+ subCode : name ,
258+ location : context . sidecarKeyOrigin [ name ] ,
259+ rule : schemaPath ,
260+ } )
261+ signature = extractSchema ( columnObject )
262+ } else {
263+ throw e
264+ }
261265 }
262266 }
263267
@@ -267,17 +271,9 @@ export function evalColumns(
267271
268272 const spec = compileSignature ( signature , schema . objects . formats )
269273
270- const issue = {
271- code : 'TSV_VALUE_INCORRECT_TYPE' ,
272- subCode : name ,
273- location : context . path ,
274- rule : schemaPath ,
275- }
276-
277274 const ageCheck = name === 'age'
278275 let ageWarningIssued = false
279276
280- const column = context . columns [ name ] as string [ ]
281277 for ( const [ index , value ] of column . entries ( ) ) {
282278 if ( ! checkValue ( value , spec ) ) {
283279 if ( ageCheck && value === '89+' ) {
@@ -295,6 +291,7 @@ export function evalColumns(
295291 ( value . match ( / ^ \s * ( N A | n a | n a n | N a N | n \/ a ) \s * $ / ) ? ", did you mean 'n/a'?" : '' )
296292 context . dataset . issues . add ( {
297293 ...issue ,
294+ code : 'TSV_VALUE_INCORRECT_TYPE' ,
298295 line : index + 2 ,
299296 issueMessage,
300297 } )
0 commit comments