@openneuro/server 4.7.0 → 4.7.2-alpha.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openneuro/server",
3
- "version": "4.7.0",
3
+ "version": "4.7.2-alpha.0",
4
4
  "description": "Core service for the OpenNeuro platform.",
5
5
  "license": "MIT",
6
6
  "main": "src/server.js",
@@ -18,7 +18,7 @@
18
18
  "dependencies": {
19
19
  "@apollo/client": "3.4.17",
20
20
  "@elastic/elasticsearch": "7.15.0",
21
- "@openneuro/search": "^4.7.0",
21
+ "@openneuro/search": "^4.7.2-alpha.0",
22
22
  "@passport-next/passport-google-oauth2": "^1.0.0",
23
23
  "@sentry/node": "^4.5.3",
24
24
  "apollo-server": "2.25.3",
@@ -105,5 +105,5 @@
105
105
  "publishConfig": {
106
106
  "access": "public"
107
107
  },
108
- "gitHead": "74336af513bf3128af43ad3c55e2127b3a85915b"
108
+ "gitHead": "1530c13f60e66a8d68129aecdaf41806db635fcf"
109
109
  }
package/src/config.js CHANGED
@@ -64,6 +64,9 @@ const config = {
64
64
  elasticsearch: {
65
65
  connection: process.env.ELASTICSEARCH_CONNECTION,
66
66
  },
67
+ github: {
68
+ token: process.env.DATALAD_GITHUB_TOKEN,
69
+ },
67
70
  }
68
71
 
69
72
  export default config
@@ -0,0 +1,33 @@
1
+ import { githubDerivativeQuery, derivativeObject } from '../derivatives'
2
+
3
+ describe('GraphQL derivatives', () => {
4
+ describe('githubDerivativeQuery()', () => {
5
+ it('constructs a correct URL', () => {
6
+ expect(githubDerivativeQuery('ds000102', 'mriqc').toString()).toEqual(
7
+ 'https://api.github.com/repos/OpenNeuroDerivatives/ds000102-mriqc',
8
+ )
9
+ })
10
+ })
11
+ describe('derivativeObject()', () => {
12
+ it('returns expected values for mriqc', () => {
13
+ expect(derivativeObject('ds000102', 'mriqc')).toEqual({
14
+ dataladUrl: new URL(
15
+ 'https://github.com/OpenNeuroDerivatives/ds000102-mriqc.git',
16
+ ),
17
+ local: false,
18
+ name: 'ds000102-mriqc',
19
+ s3Url: new URL('s3://openneuro-derivatives/mriqc/ds000102-mriqc'),
20
+ })
21
+ })
22
+ it('returns expected values for fmriprep', () => {
23
+ expect(derivativeObject('ds000102', 'fmriprep')).toEqual({
24
+ dataladUrl: new URL(
25
+ 'https://github.com/OpenNeuroDerivatives/ds000102-fmriprep.git',
26
+ ),
27
+ local: false,
28
+ name: 'ds000102-fmriprep',
29
+ s3Url: new URL('s3://openneuro-derivatives/fmriprep/ds000102-fmriprep'),
30
+ })
31
+ })
32
+ })
33
+ })
@@ -21,6 +21,7 @@ import { getDatasetWorker } from '../../libs/datalad-service.js'
21
21
  import { getDraftHead } from '../../datalad/dataset.js'
22
22
  import { getFileName } from '../../datalad/files.js'
23
23
  import { onBrainlife } from './brainlife'
24
+ import { derivatives } from './derivatives'
24
25
  import semver from 'semver'
25
26
 
26
27
  export const dataset = async (obj, { id }, { user, userInfo }) => {
@@ -304,6 +305,7 @@ const Dataset = {
304
305
  following,
305
306
  starred,
306
307
  onBrainlife,
308
+ derivatives,
307
309
  metadata,
308
310
  history,
309
311
  worker,
@@ -0,0 +1,97 @@
1
+ import fetch from 'node-fetch'
2
+ import {
3
+ DatasetOrSnapshot,
4
+ getDatasetFromSnapshotId,
5
+ } from '../../utils/datasetOrSnapshot'
6
+ import config from '../../config'
7
+
8
+ const S3_BUCKET = 'openneuro-derivatives'
9
+ const GITHUB_ORGANIZATION = 'OpenNeuroDerivatives'
10
+
11
+ // Available derivatives at this time
12
+ type GitHubDerivative = 'mriqc' | 'fmriprep'
13
+
14
+ /**
15
+ * Test for a derivative on GitHub via API
16
+ * @param datasetId
17
+ * @param derivative String identifying the kind of derivative
18
+ */
19
+ export const githubDerivativeQuery = (
20
+ datasetId: string,
21
+ derivative: GitHubDerivative,
22
+ ): URL => {
23
+ const url = new URL(
24
+ `https://api.github.com/repos/${GITHUB_ORGANIZATION}/${datasetId}-${derivative}`,
25
+ )
26
+ return url
27
+ }
28
+
29
+ export const githubDerivative = async (
30
+ datasetId: string,
31
+ derivative: GitHubDerivative,
32
+ ): Promise<boolean> => {
33
+ try {
34
+ const url = githubDerivativeQuery(datasetId, derivative)
35
+ const res = await fetch(url.toString(), {
36
+ headers: {
37
+ Authorization: `token ${config.github.token}`,
38
+ },
39
+ })
40
+ if (res.status === 200) {
41
+ const body = await res.json()
42
+ // Verify we aren't displaying a hidden repo
43
+ if (!body.private) {
44
+ return true
45
+ }
46
+ }
47
+ return false
48
+ } catch (err) {
49
+ return false
50
+ }
51
+ }
52
+
53
+ interface DatasetDerivatives {
54
+ name: string
55
+ local: boolean
56
+ s3Url: URL
57
+ dataladUrl: URL
58
+ }
59
+
60
+ export const derivativeObject = (
61
+ datasetId: string,
62
+ derivative: GitHubDerivative,
63
+ ): DatasetDerivatives => {
64
+ const name = `${datasetId}-${derivative}`
65
+ return {
66
+ name,
67
+ // Always false to identify OpenNeuro hosted derivatives later
68
+ local: false,
69
+ s3Url: new URL(name, `s3://${S3_BUCKET}/${derivative}/`),
70
+ dataladUrl: new URL(
71
+ `${name}.git`,
72
+ `https://github.com/${GITHUB_ORGANIZATION}/`,
73
+ ),
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Derivative resolver, returns an array of the available derivative dataset sources
79
+ */
80
+ export const derivatives = async (
81
+ dataset: DatasetOrSnapshot,
82
+ ): Promise<Array<DatasetDerivatives>> => {
83
+ let datasetId
84
+ if ('tag' in dataset) {
85
+ datasetId = getDatasetFromSnapshotId(dataset.id)
86
+ } else {
87
+ datasetId = dataset.id
88
+ }
89
+ const available: Array<DatasetDerivatives> = []
90
+ if (await githubDerivative(datasetId, 'mriqc')) {
91
+ available.push(derivativeObject(datasetId, 'mriqc'))
92
+ }
93
+ if (await githubDerivative(datasetId, 'fmriprep')) {
94
+ available.push(derivativeObject(datasetId, 'fmriprep'))
95
+ }
96
+ return available
97
+ }
@@ -384,6 +384,8 @@ export const typeDefs = `
384
384
  publishDate: DateTime
385
385
  # Is the dataset available for analysis on Brainlife?
386
386
  onBrainlife: Boolean @cacheControl(maxAge: 10080, scope: PUBLIC)
387
+ # Available derivatives of this dataset
388
+ derivatives: [DatasetDerivatives] @cacheControl(maxAge: 3600, scope: PUBLIC)
387
389
  # Dataset Metadata
388
390
  metadata: Metadata
389
391
  # Return the version history for a dataset (git log)
@@ -394,6 +396,17 @@ export const typeDefs = `
394
396
  reviewers: [DatasetReviewer]
395
397
  }
396
398
 
399
+ type DatasetDerivatives {
400
+ # Remote reference to display
401
+ name: String
402
+ # Is this an OpenNeuro derivative?
403
+ local: Boolean
404
+ # S3-like URL if available
405
+ s3Url: String
406
+ # DataLad GitHub URL if available
407
+ dataladUrl: String
408
+ }
409
+
397
410
  type DatasetCommit {
398
411
  # Git commit hash
399
412
  id: ID!