bids-validator-deno 2.0.7__tar.gz → 2.0.8__tar.gz

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.

Potentially problematic release.


This version of bids-validator-deno might be problematic. Click here for more details.

Files changed (105) hide show
  1. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/PKG-INFO +1 -1
  2. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/deno.json +1 -1
  3. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/pyproject.toml +1 -1
  4. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/inheritance.test.ts +25 -0
  5. bids_validator_deno-2.0.8/src/files/inheritance.ts +80 -0
  6. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/associations.ts +30 -41
  7. bids_validator_deno-2.0.7/src/files/inheritance.ts +0 -51
  8. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/LICENSE +0 -0
  9. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/README.md +0 -0
  10. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/pdm_build.py +0 -0
  11. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/.git-meta.json +0 -0
  12. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/bids-validator.ts +0 -0
  13. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/browser.test.ts +0 -0
  14. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/browser.ts +0 -0
  15. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/deno.test.ts +0 -0
  16. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/deno.ts +0 -0
  17. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/dwi.test.ts +0 -0
  18. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/dwi.ts +0 -0
  19. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/filetree.test.ts +0 -0
  20. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/filetree.ts +0 -0
  21. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/gzip.test.ts +0 -0
  22. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/gzip.ts +0 -0
  23. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/ignore.test.ts +0 -0
  24. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/ignore.ts +0 -0
  25. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/json.test.ts +0 -0
  26. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/json.ts +0 -0
  27. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/nifti.test.ts +0 -0
  28. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/nifti.ts +0 -0
  29. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/streams.test.ts +0 -0
  30. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/streams.ts +0 -0
  31. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/tiff.test.ts +0 -0
  32. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/tiff.ts +0 -0
  33. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/tsv.test.ts +0 -0
  34. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/files/tsv.ts +0 -0
  35. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/issues/datasetIssues.test.ts +0 -0
  36. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/issues/datasetIssues.ts +0 -0
  37. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/issues/list.test.ts +0 -0
  38. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/issues/list.ts +0 -0
  39. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/main.ts +0 -0
  40. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/applyRules.test.ts +0 -0
  41. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/applyRules.ts +0 -0
  42. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/context.test.ts +0 -0
  43. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/context.ts +0 -0
  44. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/entities.test.ts +0 -0
  45. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/entities.ts +0 -0
  46. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/expressionLanguage.test.ts +0 -0
  47. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/expressionLanguage.ts +0 -0
  48. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/fixtures.test.ts +0 -0
  49. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/modalities.ts +0 -0
  50. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/tables.test.ts +0 -0
  51. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/tables.ts +0 -0
  52. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/walk.test.ts +0 -0
  53. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/schema/walk.ts +0 -0
  54. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/setup/loadSchema.test.ts +0 -0
  55. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/setup/loadSchema.ts +0 -0
  56. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/setup/options.test.ts +0 -0
  57. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/setup/options.ts +0 -0
  58. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/setup/requestPermissions.ts +0 -0
  59. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/summary/collectSubjectMetadata.ts +0 -0
  60. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/summary/summary.test.ts +0 -0
  61. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/summary/summary.ts +0 -0
  62. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/README.md +0 -0
  63. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/bom-utf16.tsv +0 -0
  64. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/bom-utf8.json +0 -0
  65. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/generate-filenames.ts +0 -0
  66. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/local/bids_examples.test.ts +0 -0
  67. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/local/common.ts +0 -0
  68. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/local/derivatives.test.ts +0 -0
  69. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/local/empty_files.test.ts +0 -0
  70. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/local/hed-integration.test.ts +0 -0
  71. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/local/valid_dataset.test.ts +0 -0
  72. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/local/valid_filenames.test.ts +0 -0
  73. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/local/valid_headers.test.ts +0 -0
  74. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/nullReadBytes.ts +0 -0
  75. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/regression.test.ts +0 -0
  76. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/schema-expression-language.test.ts +0 -0
  77. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/simple-dataset.ts +0 -0
  78. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/tests/utils.ts +0 -0
  79. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/types/check.ts +0 -0
  80. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/types/columns.test.ts +0 -0
  81. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/types/columns.ts +0 -0
  82. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/types/filetree.ts +0 -0
  83. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/types/issues.ts +0 -0
  84. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/types/schema.ts +0 -0
  85. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/types/validation-result.ts +0 -0
  86. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/utils/errors.ts +0 -0
  87. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/utils/logger.test.ts +0 -0
  88. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/utils/logger.ts +0 -0
  89. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/utils/memoize.ts +0 -0
  90. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/utils/objectPathHandler.ts +0 -0
  91. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/utils/output.ts +0 -0
  92. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/bids.test.ts +0 -0
  93. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/bids.ts +0 -0
  94. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/citation.test.ts +0 -0
  95. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/citation.ts +0 -0
  96. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/filenameIdentify.test.ts +0 -0
  97. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/filenameIdentify.ts +0 -0
  98. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/filenameValidate.test.ts +0 -0
  99. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/filenameValidate.ts +0 -0
  100. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/hed.ts +0 -0
  101. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/internal/emptyFile.ts +0 -0
  102. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/internal/unusedFile.ts +0 -0
  103. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/json.ts +0 -0
  104. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/validators/validateFiles.test.ts +0 -0
  105. {bids_validator_deno-2.0.7 → bids_validator_deno-2.0.8}/src/version.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bids-validator-deno
3
- Version: 2.0.7
3
+ Version: 2.0.8
4
4
  Summary: Typescript implementation of the BIDS validator
5
5
  Keywords: BIDS,BIDS validator
6
6
  Author: bids-standard developers
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bids/validator",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
4
4
  "exports": {
5
5
  ".": "./src/bids-validator.ts",
6
6
  "./main": "./src/main.ts",
@@ -18,7 +18,7 @@ keywords = [
18
18
  "BIDS validator",
19
19
  ]
20
20
  dynamic = []
21
- version = "2.0.7"
21
+ version = "2.0.8"
22
22
 
23
23
  [project.license]
24
24
  text = "MIT"
@@ -1,4 +1,5 @@
1
1
  import { assert, assertEquals, assertThrows } from '@std/assert'
2
+ import type { BIDSFile } from '../types/filetree.ts'
2
3
  import { pathsToTree } from './filetree.ts'
3
4
  import { walkBack } from './inheritance.ts'
4
5
 
@@ -47,4 +48,28 @@ Deno.test('walkback inheritance tests', async (t) => {
47
48
  ])
48
49
  },
49
50
  )
51
+ await t.step(
52
+ 'Passing targetEntities enables multiple matches',
53
+ async () => {
54
+ const rootFileTree = pathsToTree([
55
+ '/space-talairach_electrodes.tsv',
56
+ '/space-talairach_electrodes.json',
57
+ '/sub-01/ieeg/sub-01_task-rest_ieeg.edf',
58
+ '/sub-01/ieeg/sub-01_task-rest_ieeg.json',
59
+ '/sub-01/ieeg/sub-01_space-anat_electrodes.tsv',
60
+ '/sub-01/ieeg/sub-01_space-anat_electrodes.json',
61
+ '/sub-01/ieeg/sub-01_space-MNI_electrodes.tsv',
62
+ '/sub-01/ieeg/sub-01_space-MNI_electrodes.json',
63
+ ])
64
+ const dataFile = rootFileTree.get('sub-01/ieeg/sub-01_task-rest_ieeg.edf') as BIDSFile
65
+ const electrodes = walkBack(dataFile, true, ['.tsv'], 'electrodes', ['space'])
66
+ const localElectrodes: BIDSFile[] = electrodes.next().value
67
+ assertEquals(localElectrodes.map((f) => f.path), [
68
+ '/sub-01/ieeg/sub-01_space-anat_electrodes.tsv',
69
+ '/sub-01/ieeg/sub-01_space-MNI_electrodes.tsv',
70
+ ])
71
+ const rootElectrodes: BIDSFile = electrodes.next().value
72
+ assertEquals(rootElectrodes.path, '/space-talairach_electrodes.tsv')
73
+ },
74
+ )
50
75
  })
@@ -0,0 +1,80 @@
1
+ import type { BIDSFile, FileTree } from '../types/filetree.ts'
2
+ import { readEntities } from '../schema/entities.ts'
3
+
4
+
5
+ type Ret<T> = T extends [string, ...string[]] ? (BIDSFile | BIDSFile[]) : BIDSFile
6
+
7
+ /** Find associated files in order of proximity to a source file.
8
+ *
9
+ * This function implements the BIDS Inheritance Principle.
10
+ *
11
+ * @param {BIDSFile} source
12
+ * The source file to start the search from.
13
+ * @param {boolean} [inherit=true]
14
+ * If true, search up the file tree for associated files.
15
+ * If false, the associated file must be found in the same directory.
16
+ * @param {string[]} [targetExtensions='.json']
17
+ * The extensions of associated files.
18
+ * @param {string} [targetSuffix]
19
+ * The suffix of associated files. If not provided, it defaults to the suffix of the source file.
20
+ * @param {string[]} [targetEntities]
21
+ * Additional entities permitted in associated files.
22
+ * A non-empty value implies that multiple values may be returned.
23
+ * By default, associated files must have a subset of the entities in the source file.
24
+ *
25
+ * @returns {Generator<BIDSFile | BIDSFile[]>}
26
+ * A generator that yields associated files or arrays of files.
27
+ */
28
+ export function* walkBack<T extends string[]>(
29
+ source: BIDSFile,
30
+ inherit: boolean = true,
31
+ targetExtensions: string[] = ['.json'],
32
+ targetSuffix?: string,
33
+ targetEntities?: T,
34
+ ): Generator<Ret<T>> {
35
+ const sourceParts = readEntities(source.name)
36
+
37
+ targetSuffix = targetSuffix || sourceParts.suffix
38
+
39
+ let fileTree: FileTree | undefined = source.parent
40
+ while (fileTree) {
41
+ const candidates = fileTree.files.filter((file) => {
42
+ const { suffix, extension, entities } = readEntities(file.name)
43
+ return (
44
+ targetExtensions.includes(extension) &&
45
+ suffix === targetSuffix &&
46
+ Object.keys(entities).every((entity) =>
47
+ entities[entity] === sourceParts.entities[entity] || targetEntities?.includes(entity)
48
+ )
49
+ )
50
+ })
51
+ if (candidates.length > 1) {
52
+ const exactMatch = candidates.find((file) => {
53
+ const { entities } = readEntities(file.name)
54
+ return Object.keys(sourceParts.entities).every((entity) =>
55
+ entities[entity] === sourceParts.entities[entity]
56
+ )
57
+ })
58
+ if (exactMatch) {
59
+ exactMatch.viewed = true
60
+ yield exactMatch
61
+ } else if (targetEntities?.length) {
62
+ candidates.forEach((file) => (file.viewed = true))
63
+ yield candidates as Ret<T>
64
+ } else {
65
+ const paths = candidates.map((x) => x.path).sort()
66
+ throw {
67
+ code: 'MULTIPLE_INHERITABLE_FILES',
68
+ location: paths[0],
69
+ affects: source.path,
70
+ issueMessage: `Candidate files: ${paths}`,
71
+ }
72
+ }
73
+ } else if (candidates.length === 1) {
74
+ candidates[0].viewed = true
75
+ yield candidates[0]
76
+ }
77
+ if (!inherit) break
78
+ fileTree = fileTree.parent
79
+ }
80
+ }
@@ -1,39 +1,25 @@
1
- import type {
2
- Aslcontext,
3
- Associations,
4
- Bval,
5
- Bvec,
6
- Channels,
7
- Coordsystem,
8
- Events,
9
- M0Scan,
10
- Magnitude,
11
- Magnitude1,
12
- } from '@bids/schema/context'
1
+ import type { Aslcontext, Associations, Bval, Bvec, Channels, Events } from '@bids/schema/context'
13
2
  import type { Schema as MetaSchema } from '@bids/schema/metaschema'
14
3
 
15
- import type { BIDSFile, FileTree } from '../types/filetree.ts'
4
+ import type { BIDSFile } from '../types/filetree.ts'
16
5
  import type { BIDSContext } from './context.ts'
17
- import type { DatasetIssues } from '../issues/datasetIssues.ts'
18
- import type { readEntities } from './entities.ts'
19
6
  import { loadTSV } from '../files/tsv.ts'
20
7
  import { parseBvalBvec } from '../files/dwi.ts'
21
8
  import { walkBack } from '../files/inheritance.ts'
22
9
  import { evalCheck } from './applyRules.ts'
23
10
  import { expressionFunctions } from './expressionLanguage.ts'
24
11
 
25
- // type AssociationsLookup = Record<keyof ContextAssociations, { extensions: string[], inherit: boolean, load: ... }
12
+ function defaultAssociation(file: BIDSFile, _options: any): Promise<{ path: string }> {
13
+ return Promise.resolve({ path: file.path })
14
+ }
26
15
 
27
16
  /**
28
- * This object describes associated files for data files in a bids dataset
29
- * For any given datafile we iterate over every key/value in this object.
30
- * For each entry we see if any files in the datafiles directory have:
31
- * - a suffix that matches the key
32
- * - an extension in the entry's extension array.
33
- * - that all the files entities and their values match those of the datafile
34
- * If the entry allows for inheritance we recurse up the filetree looking for other applicable files.
35
- * The load functions are incomplete, some associations need to read data from a file so they're
36
- * returning promises for now.
17
+ * This object describes lookup functions for files associated to data files in a bids dataset.
18
+ * For any given data file we iterate over the associations defined schema.meta.associations.
19
+ * If the selectors match the data file, we attempt to find an associated file,
20
+ * and use the given function to load the data from that file.
21
+ *
22
+ * Many associations only consist of a path; this object is for more complex associations.
37
23
  */
38
24
  const associationLookup = {
39
25
  events: async (file: BIDSFile, options: { maxRows: number }): Promise<Events> => {
@@ -60,15 +46,6 @@ const associationLookup = {
60
46
  volume_type: columns.get('volume_type') || [],
61
47
  }
62
48
  },
63
- m0scan: (file: BIDSFile, options: any): Promise<M0Scan> => {
64
- return Promise.resolve({ path: file.path })
65
- },
66
- magnitude: (file: BIDSFile, options: any): Promise<Magnitude> => {
67
- return Promise.resolve({ path: file.path })
68
- },
69
- magnitude1: (file: BIDSFile, options: any): Promise<Magnitude1> => {
70
- return Promise.resolve({ path: file.path })
71
- },
72
49
  bval: async (file: BIDSFile, options: any): Promise<Bval> => {
73
50
  const contents = await file.text()
74
51
  const rows = parseBvalBvec(contents)
@@ -106,9 +83,6 @@ const associationLookup = {
106
83
  sampling_frequency: columns.get('sampling_frequency'),
107
84
  }
108
85
  },
109
- coordsystem: (file: BIDSFile, options: any): Promise<Coordsystem> => {
110
- return Promise.resolve({ path: file.path })
111
- },
112
86
  }
113
87
 
114
88
  export async function buildAssociations(
@@ -117,16 +91,22 @@ export async function buildAssociations(
117
91
  const associations: Associations = {}
118
92
 
119
93
  const schema: MetaSchema = context.dataset.schema as MetaSchema
94
+ // Augment rule type with an entities field that should be present in BIDS 1.10.1+
95
+ type ruleType = MetaSchema['meta']['associations'][keyof MetaSchema['meta']['associations']]
96
+ type AugmentedRuleType = ruleType & {
97
+ target: ruleType['target'] & { entities?: string[] }
98
+ }
120
99
 
121
100
  Object.assign(context, expressionFunctions)
122
101
  // @ts-expect-error
123
102
  context.exists.bind(context)
124
103
 
125
- for (const [key, rule] of Object.entries(schema.meta.associations)) {
104
+ for (const key of Object.keys(schema.meta.associations)) {
105
+ const rule = schema.meta.associations[key] as AugmentedRuleType
126
106
  if (!rule.selectors!.every((x) => evalCheck(x, context))) {
127
107
  continue
128
108
  }
129
- let file
109
+ let file: BIDSFile | BIDSFile[]
130
110
  let extension: string[] = []
131
111
  if (typeof rule.target.extension === 'string') {
132
112
  extension = [rule.target.extension]
@@ -134,7 +114,16 @@ export async function buildAssociations(
134
114
  extension = rule.target.extension
135
115
  }
136
116
  try {
137
- file = walkBack(context.file, rule.inherit, extension, rule.target.suffix).next().value
117
+ file = walkBack(
118
+ context.file,
119
+ rule.inherit,
120
+ extension,
121
+ rule.target.suffix,
122
+ rule.target?.entities ?? [],
123
+ ).next().value
124
+ if (Array.isArray(file)) {
125
+ file = file[0]
126
+ }
138
127
  } catch (error) {
139
128
  if (
140
129
  error && typeof error === 'object' && 'code' in error &&
@@ -150,7 +139,7 @@ export async function buildAssociations(
150
139
 
151
140
  if (file) {
152
141
  // @ts-expect-error
153
- const load = associationLookup[key]
142
+ const load = associationLookup[key] ?? defaultAssociation
154
143
  // @ts-expect-error
155
144
  associations[key] = await load(file, { maxRows: context.dataset.options?.maxRows }).catch(
156
145
  (error: any) => {
@@ -1,51 +0,0 @@
1
- import type { BIDSFile, FileTree } from '../types/filetree.ts'
2
- import type { Context } from '@bids/schema'
3
- import { readEntities } from '../schema/entities.ts'
4
-
5
- export function* walkBack(
6
- source: BIDSFile,
7
- inherit: boolean = true,
8
- targetExtensions: string[] = ['.json'],
9
- targetSuffix?: string,
10
- ): Generator<BIDSFile> {
11
- const sourceParts = readEntities(source.name)
12
-
13
- targetSuffix = targetSuffix || sourceParts.suffix
14
-
15
- let fileTree: FileTree | undefined = source.parent
16
- while (fileTree) {
17
- const candidates = fileTree.files.filter((file) => {
18
- const { suffix, extension, entities } = readEntities(file.name)
19
- return (
20
- targetExtensions.includes(extension) &&
21
- suffix === targetSuffix &&
22
- Object.keys(entities).every((entity) => entities[entity] === sourceParts.entities[entity])
23
- )
24
- })
25
- if (candidates.length > 1) {
26
- const exactMatch = candidates.find((file) => {
27
- const { suffix, extension, entities } = readEntities(file.name)
28
- return Object.keys(sourceParts.entities).every((entity) =>
29
- entities[entity] === sourceParts.entities[entity]
30
- )
31
- })
32
- if (exactMatch) {
33
- exactMatch.viewed = true
34
- yield exactMatch
35
- } else {
36
- const paths = candidates.map((x) => x.path).sort()
37
- throw {
38
- code: 'MULTIPLE_INHERITABLE_FILES',
39
- location: paths[0],
40
- affects: source.path,
41
- issueMessage: `Candidate files: ${paths}`,
42
- }
43
- }
44
- } else if (candidates.length === 1) {
45
- candidates[0].viewed = true
46
- yield candidates[0]
47
- }
48
- if (!inherit) break
49
- fileTree = fileTree.parent
50
- }
51
- }