diff --git a/index.js b/index.js index 9654a47e..7154212f 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,3 @@ -import bids from './src/bids' +export * from './src/bids' -export { bids } - -export default { - bids, -} +export { IssueError } from './src/issues/issues' diff --git a/src/bids/index.js b/src/bids/index.js index c6548af1..b805fb9a 100644 --- a/src/bids/index.js +++ b/src/bids/index.js @@ -2,25 +2,13 @@ import { buildBidsSchemas } from './schema' import { BidsJsonFile, BidsSidecar } from './types/json' import { BidsTsvFile } from './types/tsv' import { BidsHedIssue } from './types/issues' -import BidsHedSidecarValidator from './validator/sidecarValidator' -import BidsHedTsvValidator from './validator/tsvValidator' -export { - BidsTsvFile, - BidsJsonFile, - BidsSidecar, - BidsHedIssue, - BidsHedSidecarValidator, - BidsHedTsvValidator, - buildBidsSchemas, -} +export { BidsTsvFile, BidsJsonFile, BidsSidecar, BidsHedIssue, buildBidsSchemas } export default { BidsTsvFile, BidsJsonFile, BidsSidecar, BidsHedIssue, - BidsHedSidecarValidator, - BidsHedTsvValidator, buildBidsSchemas, } diff --git a/src/bids/schema.js b/src/bids/schema.js index 8ddb0617..65ddd639 100644 --- a/src/bids/schema.js +++ b/src/bids/schema.js @@ -11,12 +11,11 @@ const alphabeticRegExp = new RegExp('^[a-zA-Z]+$') * Build a HED schema collection based on the defined BIDS schemas. * * @param {BidsJsonFile} datasetDescription The description of the BIDS dataset being validated. - * @param {SchemasSpec} schemaDefinition The version spec override for the schema to be loaded. * @returns {Promise} A Promise with the schema collection, or null if the specification is missing. * @throws {IssueError} If the schema specification is invalid. */ -export async function buildBidsSchemas(datasetDescription, schemaDefinition) { - const schemasSpec = buildSchemasSpec(datasetDescription, schemaDefinition) +export async function buildBidsSchemas(datasetDescription) { + const schemasSpec = buildSchemasSpec(datasetDescription) if (schemasSpec === null) { return null } @@ -27,28 +26,17 @@ export async function buildBidsSchemas(datasetDescription, schemaDefinition) { * Build a HED schema specification based on the defined BIDS schemas. * * @param {BidsJsonFile} datasetDescription The description of the BIDS dataset being validated. - * @param {SchemasSpec} schemaDefinition The version spec override for the schema to be loaded. * @returns {SchemasSpec|null} The schema specification to be used to build the schemas, or null if the specification is missing. * @throws {IssueError} If the schema specification is invalid. */ -export function buildSchemasSpec(datasetDescription, schemaDefinition) { - if (schemaDefinition) { - return validateSchemasSpec(schemaDefinition) - } else if (datasetDescription.jsonData?.HEDVersion) { +export function buildSchemasSpec(datasetDescription) { + if (datasetDescription.jsonData?.HEDVersion) { return parseSchemasSpec(datasetDescription.jsonData.HEDVersion) } else { return null } } -function validateSchemasSpec(schemasSpec) { - if (schemasSpec instanceof SchemasSpec) { - return schemasSpec - } else { - IssueError.generateAndThrow('invalidSchemaSpecification', { spec: JSON.stringify(schemasSpec) }) - } -} - export function parseSchemasSpec(hedVersion) { const schemasSpec = new SchemasSpec() const processVersion = castArray(hedVersion) diff --git a/src/bids/types/file.js b/src/bids/types/file.js index 3b53c9b9..942dd3f5 100644 --- a/src/bids/types/file.js +++ b/src/bids/types/file.js @@ -59,7 +59,7 @@ export class BidsFile { * Validate this validator's tsv file. * * @param {Schemas} schemas - The HED schemas used to validate this file. - * @returns {BidsHedIssue[], BidsHedIssue[]} - Any issues found during validation of this TSV file. + * @returns {BidsHedIssue[]} - Any issues found during validation of this TSV file. */ validate(schemas) { if (!this.hasHedData) { diff --git a/src/bids/types/issues.js b/src/bids/types/issues.js index 04715638..bf0b9dcf 100644 --- a/src/bids/types/issues.js +++ b/src/bids/types/issues.js @@ -1,26 +1,48 @@ +import groupBy from 'lodash/groupBy' + import { generateIssue, IssueError } from '../../issues/issues' export class BidsHedIssue { + /** + * The file associated with this issue. + * @type {Object} + */ + file + /** + * The HED Issue object corresponding to this object. + * @type {Issue} + */ + hedIssue /** * The BIDS issue code. * @type {string} */ - bidsCode + code /** - * The file associated with this issue. - * @type {Object} + * The HED spec code for this issue. + * @type {string} */ - file + subCode /** - * The evidence for this issue. + * The severity of this issue. * @type {string} */ - message + severity /** - * The HED Issue object corresponding to this object. - * @type {Issue} + * The issue message for this issue. + * @type {string} */ - hedIssue + issueMessage + /** + * The line at which the issue was found. + * @type {number} + */ + line + /** + * The location of the file at which the issue was found. + * @type {string} + */ + location /** * Constructor. @@ -30,60 +52,29 @@ export class BidsHedIssue { */ constructor(hedIssue, file) { this.hedIssue = hedIssue - this.bidsCode = BidsHedIssue._determineBidsIssueCode(hedIssue) - this.message = hedIssue.message this.file = file - } - - /** - * The HED spec code for this issue. - * - * @returns {string} - */ - get hedCode() { - return this.hedIssue.hedCode - } - /** - * Whether this issue is an error. - * - * @returns {boolean} - */ - get isError() { - return this.hedIssue.level === 'error' + // BIDS fields + if (hedIssue.level === 'warning') { + this.code = 'HED_WARNING' + } else { + this.code = 'HED_ERROR' + } + this.subCode = hedIssue.hedCode + this.severity = hedIssue.level + this.issueMessage = hedIssue.message + this.line = hedIssue.parameters?.tsvLine + this.location = file?.path } /** - * Determine if any of the passed issues are errors. + * Split a list of issues into errors and warnings. * * @param {BidsHedIssue[]} issues A list of issues. - * @returns {boolean} Whether any of the passed issues are errors (rather than warnings). + * @returns {Object} The list of issues divided into errors and warnings. */ - static anyAreErrors(issues) { - return issues.some((issue) => issue.isError) - } - static splitErrors(issues) { - const errors = issues.filter((item) => item.isError) - const warnings = issues.filter((item) => !item.isError) - return [errors, warnings] - } - - /** - * Determine the BIDS issue code for this issue. - * - * @param {Issue} hedIssue The HED issue object to be wrapped. - * @returns {string} The BIDS issue code for this issue. - * @private - */ - static _determineBidsIssueCode(hedIssue) { - if (hedIssue.internalCode === 'internalError') { - return 'HED_INTERNAL_ERROR' - } - if (hedIssue.level === 'warning') { - return 'HED_WARNING' - } - return 'HED_ERROR' + return groupBy(issues, (issue) => issue.severity) } /** diff --git a/src/bids/types/tsv.js b/src/bids/types/tsv.js index 614bee05..58ec5d8c 100644 --- a/src/bids/types/tsv.js +++ b/src/bids/types/tsv.js @@ -42,7 +42,7 @@ export class BidsTsvFile extends BidsFile { if (typeof tsvData === 'string') { this.parsedTsv = parseTSV(tsvData) } else if (tsvData instanceof Map) { - this.parsedTsv = tsvData + this.parsedTsv = new Map(tsvData) } else if (isPlainObject(tsvData)) { this.parsedTsv = convertParsedTSVData(tsvData) } else { diff --git a/src/bids/validator/tsvValidator.js b/src/bids/validator/tsvValidator.js index 39006b32..54567114 100644 --- a/src/bids/validator/tsvValidator.js +++ b/src/bids/validator/tsvValidator.js @@ -37,9 +37,9 @@ export class BidsHedTsvValidator extends BidsValidator { // Validate the BIDS bidsFile if it exists and return if there are errors if (this.bidsFile.mergedSidecar) { const issues = this.bidsFile.mergedSidecar.validate(this.hedSchemas) - const [errorIssues, warningIssues] = BidsHedIssue.splitErrors(issues) - this.errors.push(...errorIssues) - this.warnings.push(...warningIssues) + const splitErrors = BidsHedIssue.splitErrors(issues) + this.errors.push(...(splitErrors.error ?? [])) + this.warnings.push(...(splitErrors.warning ?? [])) if (this.errors.length > 0) { return } diff --git a/src/schema/containers.js b/src/schema/containers.js index d2e4c415..215f6e22 100644 --- a/src/schema/containers.js +++ b/src/schema/containers.js @@ -1,5 +1,6 @@ +import lt from 'semver/functions/lt' + import { IssueError } from '../issues/issues' -import { getGenerationForSchemaVersion } from '../utils/hedData' /** * An imported HED 3 schema. @@ -10,11 +11,6 @@ export class Schema { * @type {string} */ version - /** - * The HED generation of this schema. - * @type {Number} - */ - generation /** * The HED library schema name. * @type {string} @@ -47,10 +43,10 @@ export class Schema { this.version = rootElement?.$?.version this.library = rootElement?.$?.library ?? '' - if (this.library) { - this.generation = 3 - } else if (this.version) { - this.generation = getGenerationForSchemaVersion(this.version) + if (!this.library && this.version && lt(this.version, '8.0.0')) { + IssueError.generateAndThrow('deprecatedStandardSchemaVersion', { + version: this.version, + }) } if (!this.library) { @@ -93,7 +89,6 @@ export class PartneredSchema extends Schema { this.actualSchemas = actualSchemas this.withStandard = actualSchemas[0].withStandard this.library = undefined - this.generation = 3 } } @@ -186,38 +181,4 @@ export class Schemas { return null } } - - /** - * The HED generation of this schema. - * - * If baseSchema is null, generation is set to 0. - * @type {Number} - */ - get generation() { - if (this.schemas === null || this.schemas.size === 0) { - return 0 - } else if (this.librarySchemas.size > 0) { - return 3 - } else if (this.baseSchema) { - return this.baseSchema.generation - } else { - return 0 - } - } - - /** - * Whether this schema collection is for syntactic validation only. - * @returns {boolean} - */ - get isSyntaxOnly() { - return this.generation === 0 - } - - /** - * Whether this schema collection comprises HED 3 schemas. - * @returns {boolean} - */ - get isHed3() { - return this.generation === 3 - } } diff --git a/src/schema/schemaMerger.js b/src/schema/schemaMerger.js index 13056f25..46d7a2ce 100644 --- a/src/schema/schemaMerger.js +++ b/src/schema/schemaMerger.js @@ -35,10 +35,6 @@ export default class PartneredSchemaMerger { * @private */ _validate() { - if (!this.sourceSchemas.every((schema) => schema.generation === 3)) { - IssueError.generateAndThrowInternalError('Partnered schemas must be HED-3G schemas') - } - for (const schema of this.sourceSchemas.slice(1)) { if (schema.withStandard !== this.destination.withStandard) { IssueError.generateAndThrow('differentWithStandard', { diff --git a/src/utils/hedData.js b/src/utils/hedData.js deleted file mode 100644 index 5e75e83a..00000000 --- a/src/utils/hedData.js +++ /dev/null @@ -1,17 +0,0 @@ -import lt from 'semver/functions/lt' - -/** - * Determine the HED generation for a base schema version number. - * - * @param {string} version A HED base schema version number. - * @returns {number} The HED generation the base schema belongs to. - */ -export const getGenerationForSchemaVersion = function (version) { - if (lt(version, '4.0.0')) { - return 1 - } else if (lt(version, '8.0.0-alpha')) { - return 2 - } else { - return 3 - } -} diff --git a/tests/schema.spec.js b/tests/schema.spec.js index 8da7449c..d9e2ed4e 100644 --- a/tests/schema.spec.js +++ b/tests/schema.spec.js @@ -18,7 +18,6 @@ describe('HED schemas', () => { const hedSchemas = await buildSchemas(specs) assert.strictEqual(hedSchemas.baseSchema.version, spec1.version, 'Schema has wrong version number') - assert.strictEqual(hedSchemas.generation, 3, 'Schema collection has wrong generation') }) it('a library schema can be loaded from locally stored schema', async () => { @@ -29,7 +28,6 @@ describe('HED schemas', () => { assert.strictEqual(hedSchemas.baseSchema.version, spec1.version, 'Schema has wrong version number') assert.strictEqual(hedSchemas.baseSchema.library, spec1.library, 'Schema has wrong library name') - assert.strictEqual(hedSchemas.generation, 3, 'Schema collection has wrong generation') }) it('a base schema with a nickname can be loaded from locally stored schema', async () => { @@ -41,7 +39,6 @@ describe('HED schemas', () => { assert.strictEqual(schema1.version, spec1.version, 'Schema has wrong version number') assert.strictEqual(schema1.library, spec1.library, 'Schema has wrong library name') - assert.strictEqual(hedSchemas.generation, 3, 'Schema collection has wrong generation') }) it('multiple local schemas can be loaded', async () => { @@ -64,7 +61,6 @@ describe('HED schemas', () => { const schema4 = hedSchemas.getSchema('baloney') assert.isUndefined(schema4, 'baloney schema exists') - assert.strictEqual(hedSchemas.generation, 3, 'Schema collection has wrong generation') }) }) @@ -78,7 +74,6 @@ describe('HED schemas', () => { assert.strictEqual(schema1.version, spec1.version, 'Schema has wrong version number') assert.strictEqual(schema1.library, spec1.library, 'Schema has wrong library name') - assert.strictEqual(hedSchemas.generation, 3, 'Schema collection has wrong generation') }) }) @@ -91,7 +86,6 @@ describe('HED schemas', () => { const hedSchemas = await buildSchemas(schemasSpec) - assert.strictEqual(hedSchemas.generation, 3, 'Schema collection has wrong generation') const hedSchemaVersion = hedSchemas.baseSchema.version assert.strictEqual(hedSchemaVersion, localHedSchemaVersion, 'Schema has wrong version number') }) @@ -105,10 +99,7 @@ describe('HED schemas', () => { const hedSchemas = await buildSchemas(schemasSpec) - assert.strictEqual(hedSchemas.generation, 3, 'Schema collection has wrong generation') - const hedSchema = hedSchemas.getSchema(localHedLibrarySchemaName) - assert.strictEqual(hedSchema.generation, 3, 'Schema has wrong generation') assert.strictEqual(hedSchema.library, localHedLibrarySchemaName, 'Schema has wrong library name') assert.strictEqual(hedSchema.version, localHedLibrarySchemaVersion, 'Schema has wrong version number') })