@openneuro/server 4.20.4 → 4.20.6-alpha.2

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.
Files changed (185) hide show
  1. package/package.json +4 -6
  2. package/src/__mocks__/{config.js → config.ts} +5 -5
  3. package/src/app.ts +32 -31
  4. package/src/cache/item.ts +6 -7
  5. package/src/cache/types.ts +8 -8
  6. package/src/{config.js → config.ts} +6 -6
  7. package/src/datalad/__tests__/changelog.spec.ts +83 -0
  8. package/src/datalad/__tests__/dataset.spec.ts +109 -0
  9. package/src/datalad/__tests__/description.spec.ts +141 -0
  10. package/src/datalad/__tests__/files.spec.ts +77 -0
  11. package/src/datalad/__tests__/pagination.spec.ts +136 -0
  12. package/src/datalad/__tests__/{snapshots.spec.js → snapshots.spec.ts} +17 -17
  13. package/src/datalad/{analytics.js → analytics.ts} +4 -4
  14. package/src/datalad/{changelog.js → changelog.ts} +17 -14
  15. package/src/datalad/{dataset.js → dataset.ts} +95 -93
  16. package/src/datalad/{description.js → description.ts} +37 -37
  17. package/src/datalad/draft.ts +38 -0
  18. package/src/datalad/files.ts +26 -20
  19. package/src/datalad/{pagination.js → pagination.ts} +47 -47
  20. package/src/datalad/{readme.js → readme.ts} +13 -11
  21. package/src/datalad/{reexporter.js → reexporter.ts} +4 -4
  22. package/src/datalad/{snapshots.js → snapshots.ts} +56 -62
  23. package/src/datalad/{upload.js → upload.ts} +7 -5
  24. package/src/elasticsearch/elastic-client.ts +11 -0
  25. package/src/elasticsearch/reindex-dataset.ts +7 -7
  26. package/src/graphql/__tests__/__snapshots__/permissions.spec.ts.snap +5 -0
  27. package/src/graphql/__tests__/{comment.spec.js → comment.spec.ts} +17 -17
  28. package/src/graphql/__tests__/permissions.spec.ts +113 -0
  29. package/src/graphql/{permissions.js → permissions.ts} +14 -14
  30. package/src/graphql/resolvers/__tests__/brainlife.spec.ts +11 -11
  31. package/src/graphql/resolvers/__tests__/{dataset-search.spec.js → dataset-search.spec.ts} +25 -23
  32. package/src/graphql/resolvers/__tests__/dataset.spec.ts +175 -0
  33. package/src/graphql/resolvers/__tests__/derivatives.spec.ts +19 -19
  34. package/src/graphql/resolvers/__tests__/importRemoteDataset.spec.ts +20 -20
  35. package/src/graphql/resolvers/__tests__/permssions.spec.ts +35 -0
  36. package/src/graphql/resolvers/__tests__/snapshots.spec.ts +59 -0
  37. package/src/graphql/resolvers/__tests__/user.spec.ts +18 -0
  38. package/src/graphql/resolvers/brainlife.ts +4 -4
  39. package/src/graphql/resolvers/cache.ts +4 -4
  40. package/src/graphql/resolvers/{comment.js → comment.ts} +16 -16
  41. package/src/graphql/resolvers/{dataset-search.js → dataset-search.ts} +45 -43
  42. package/src/graphql/resolvers/{dataset.js → dataset.ts} +38 -52
  43. package/src/graphql/resolvers/datasetType.ts +3 -3
  44. package/src/graphql/resolvers/derivatives.ts +11 -11
  45. package/src/graphql/resolvers/description.ts +18 -0
  46. package/src/graphql/resolvers/{draft.js → draft.ts} +13 -13
  47. package/src/graphql/resolvers/{flaggedFiles.js → flaggedFiles.ts} +4 -4
  48. package/src/graphql/resolvers/{follow.js → follow.ts} +1 -1
  49. package/src/graphql/resolvers/git.ts +3 -3
  50. package/src/graphql/resolvers/history.ts +13 -0
  51. package/src/graphql/resolvers/importRemoteDataset.ts +12 -11
  52. package/src/graphql/resolvers/index.ts +25 -0
  53. package/src/graphql/resolvers/{issues.js → issues.ts} +9 -9
  54. package/src/graphql/resolvers/metadata.ts +8 -8
  55. package/src/graphql/resolvers/{mutation.js → mutation.ts} +26 -26
  56. package/src/graphql/resolvers/{newsletter.js → newsletter.ts} +2 -2
  57. package/src/graphql/resolvers/permissions.ts +15 -21
  58. package/src/graphql/resolvers/publish.ts +17 -0
  59. package/src/graphql/resolvers/query.ts +21 -0
  60. package/src/graphql/resolvers/{readme.js → readme.ts} +3 -3
  61. package/src/graphql/resolvers/{reexporter.js → reexporter.ts} +2 -2
  62. package/src/graphql/resolvers/relation.ts +5 -5
  63. package/src/graphql/resolvers/{reset.js → reset.ts} +2 -2
  64. package/src/graphql/resolvers/reviewer.ts +4 -4
  65. package/src/graphql/resolvers/{snapshots.js → snapshots.ts} +49 -49
  66. package/src/graphql/resolvers/{stars.js → stars.ts} +1 -1
  67. package/src/graphql/resolvers/summary.ts +3 -3
  68. package/src/graphql/resolvers/{upload.js → upload.ts} +5 -5
  69. package/src/graphql/resolvers/{user.js → user.ts} +16 -18
  70. package/src/graphql/resolvers/{validation.js → validation.ts} +12 -14
  71. package/src/graphql/{schema.js → schema.ts} +4 -6
  72. package/src/graphql/utils/{file.js → file.ts} +2 -2
  73. package/src/handlers/{comments.js → comments.ts} +11 -11
  74. package/src/handlers/{config.js → config.ts} +1 -1
  75. package/src/handlers/{datalad.js → datalad.ts} +22 -22
  76. package/src/handlers/{doi.js → doi.ts} +6 -6
  77. package/src/handlers/reviewer.ts +6 -6
  78. package/src/handlers/{sitemap.js → sitemap.ts} +19 -19
  79. package/src/handlers/stars.ts +11 -10
  80. package/src/handlers/{subscriptions.js → subscriptions.ts} +17 -16
  81. package/src/handlers/{users.js → users.ts} +3 -3
  82. package/src/libs/__tests__/apikey.spec.ts +25 -0
  83. package/src/libs/__tests__/datalad-service.spec.ts +27 -0
  84. package/src/libs/__tests__/{dataset.spec.js → dataset.spec.ts} +9 -9
  85. package/src/libs/{apikey.js → apikey.ts} +5 -5
  86. package/src/libs/authentication/__tests__/jwt.spec.ts +59 -0
  87. package/src/libs/authentication/{crypto.js → crypto.ts} +16 -16
  88. package/src/libs/authentication/google.ts +18 -0
  89. package/src/libs/authentication/jwt.ts +40 -33
  90. package/src/libs/authentication/{orcid.js → orcid.ts} +11 -11
  91. package/src/libs/authentication/{passport.js → passport.ts} +45 -30
  92. package/src/libs/authentication/{states.js → states.ts} +17 -20
  93. package/src/libs/{counter.js → counter.ts} +1 -1
  94. package/src/libs/{datalad-service.js → datalad-service.ts} +4 -4
  95. package/src/libs/dataset.ts +9 -0
  96. package/src/libs/doi/__tests__/__snapshots__/doi.spec.ts.snap +17 -0
  97. package/src/libs/doi/__tests__/doi.spec.ts +25 -0
  98. package/src/libs/doi/__tests__/normalize.spec.ts +19 -19
  99. package/src/libs/doi/{index.js → index.ts} +27 -21
  100. package/src/libs/doi/normalize.ts +2 -2
  101. package/src/libs/email/__tests__/index.spec.ts +14 -14
  102. package/src/libs/email/index.ts +4 -4
  103. package/src/libs/email/templates/__tests__/comment-created.spec.ts +12 -12
  104. package/src/libs/email/templates/__tests__/dataset-deleted.spec.ts +6 -6
  105. package/src/libs/email/templates/__tests__/owner-unsubscribed.spec.ts +6 -6
  106. package/src/libs/email/templates/__tests__/snapshot-created.spec.ts +9 -9
  107. package/src/libs/email/templates/__tests__/snapshot-reminder.spec.ts +7 -7
  108. package/src/libs/email/templates/comment-created.ts +2 -1
  109. package/src/libs/email/templates/dataset-deleted.ts +2 -1
  110. package/src/libs/email/templates/dataset-import-failed.ts +2 -1
  111. package/src/libs/email/templates/dataset-imported.ts +2 -1
  112. package/src/libs/email/templates/owner-unsubscribed.ts +2 -1
  113. package/src/libs/email/templates/snapshot-created.ts +2 -1
  114. package/src/libs/email/templates/snapshot-reminder.ts +2 -1
  115. package/src/libs/{notifications.js → notifications.ts} +100 -113
  116. package/src/libs/{orcid.js → orcid.ts} +20 -20
  117. package/src/libs/{redis.js → redis.ts} +6 -6
  118. package/src/models/__tests__/ingestDataset.spec.ts +15 -15
  119. package/src/models/analytics.ts +2 -2
  120. package/src/models/badAnnexObject.ts +6 -6
  121. package/src/models/comment.ts +10 -10
  122. package/src/models/counter.ts +2 -2
  123. package/src/models/dataset.ts +16 -16
  124. package/src/models/deletion.ts +3 -3
  125. package/src/models/deprecatedSnapshot.ts +2 -2
  126. package/src/models/doi.ts +2 -2
  127. package/src/models/file.ts +2 -2
  128. package/src/models/ingestDataset.ts +4 -4
  129. package/src/models/issue.ts +2 -2
  130. package/src/models/key.ts +2 -2
  131. package/src/models/mailgunIdentifier.ts +2 -2
  132. package/src/models/metadata.ts +3 -3
  133. package/src/models/newsletter.ts +3 -3
  134. package/src/models/notification.ts +2 -2
  135. package/src/models/permission.ts +4 -4
  136. package/src/models/reviewer.ts +7 -7
  137. package/src/models/snapshot.ts +2 -2
  138. package/src/models/stars.ts +6 -6
  139. package/src/models/subscription.ts +2 -2
  140. package/src/models/summary.ts +2 -2
  141. package/src/models/upload.ts +3 -3
  142. package/src/models/user.ts +4 -4
  143. package/src/{routes.js → routes.ts} +62 -62
  144. package/src/server.ts +9 -9
  145. package/src/utils/__tests__/datasetOrSnapshot.spec.ts +25 -25
  146. package/src/utils/__tests__/validateUrl.spec.ts +10 -10
  147. package/src/utils/datasetOrSnapshot.ts +2 -2
  148. package/src/utils/validateUrl.ts +1 -1
  149. package/src/datalad/__tests__/changelog.spec.js +0 -82
  150. package/src/datalad/__tests__/dataset.spec.js +0 -109
  151. package/src/datalad/__tests__/description.spec.js +0 -137
  152. package/src/datalad/__tests__/files.spec.js +0 -75
  153. package/src/datalad/__tests__/pagination.spec.js +0 -136
  154. package/src/datalad/draft.js +0 -37
  155. package/src/elasticsearch/elastic-client.js +0 -11
  156. package/src/graphql/__tests__/permissions.spec.js +0 -107
  157. package/src/graphql/pubsub.js +0 -5
  158. package/src/graphql/resolvers/__tests__/dataset.spec.js +0 -175
  159. package/src/graphql/resolvers/__tests__/permssions.spec.js +0 -34
  160. package/src/graphql/resolvers/__tests__/snapshots.spec.js +0 -58
  161. package/src/graphql/resolvers/__tests__/user.spec.js +0 -17
  162. package/src/graphql/resolvers/description.js +0 -29
  163. package/src/graphql/resolvers/history.js +0 -11
  164. package/src/graphql/resolvers/index.js +0 -25
  165. package/src/graphql/resolvers/publish.js +0 -17
  166. package/src/graphql/resolvers/query.js +0 -21
  167. package/src/graphql/resolvers/subscriptions.js +0 -81
  168. package/src/graphql/utils/publish-draft-update.js +0 -13
  169. package/src/libs/__tests__/apikey.spec.js +0 -24
  170. package/src/libs/__tests__/datalad-service.spec.js +0 -26
  171. package/src/libs/authentication/__tests__/jwt.spec.js +0 -23
  172. package/src/libs/authentication/globus.js +0 -11
  173. package/src/libs/authentication/google.js +0 -19
  174. package/src/libs/bidsId.js +0 -68
  175. package/src/libs/dataset.js +0 -9
  176. package/src/libs/doi/__tests__/doi.spec.js +0 -24
  177. package/src/libs/redis-pubsub.js +0 -5
  178. package/src/libs/request.js +0 -155
  179. package/src/libs/scitran.js +0 -25
  180. package/src/libs/subscription-server.js +0 -20
  181. package/src/libs/testing-utils.js +0 -17
  182. package/src/persistent/datasets/.gitignore +0 -3
  183. package/src/persistent/temp/.gitignore +0 -3
  184. /package/src/libs/__mocks__/{notifications.js → notifications.ts} +0 -0
  185. /package/src/libs/authentication/{verifyUser.js → verifyUser.ts} +0 -0
@@ -1,28 +1,28 @@
1
1
  // dependencies ------------------------------------
2
2
 
3
- import express from 'express'
4
- import * as users from './handlers/users'
5
- import * as datalad from './handlers/datalad'
6
- import * as comments from './handlers/comments'
7
- import { clientConfig } from './handlers/config.js'
8
- import * as subscriptions from './handlers/subscriptions'
9
- import verifyUser from './libs/authentication/verifyUser.js'
10
- import * as google from './libs/authentication/google.js'
11
- import * as orcid from './libs/authentication/orcid.js'
12
- import * as jwt from './libs/authentication/jwt'
13
- import * as auth from './libs/authentication/states.js'
14
- import * as doi from './handlers/doi'
15
- import { sitemapHandler } from './handlers/sitemap.js'
16
- import { reviewerHandler } from './handlers/reviewer'
3
+ import express from "express"
4
+ import * as users from "./handlers/users"
5
+ import * as datalad from "./handlers/datalad"
6
+ import * as comments from "./handlers/comments"
7
+ import { clientConfig } from "./handlers/config"
8
+ import * as subscriptions from "./handlers/subscriptions"
9
+ import verifyUser from "./libs/authentication/verifyUser"
10
+ import * as google from "./libs/authentication/google"
11
+ import * as orcid from "./libs/authentication/orcid"
12
+ import * as jwt from "./libs/authentication/jwt"
13
+ import * as auth from "./libs/authentication/states"
14
+ import * as doi from "./handlers/doi"
15
+ import { sitemapHandler } from "./handlers/sitemap"
16
+ import { reviewerHandler } from "./handlers/reviewer"
17
17
 
18
18
  const noCache = (req, res, next) => {
19
- res.setHeader('Surrogate-Control', 'no-store')
19
+ res.setHeader("Surrogate-Control", "no-store")
20
20
  res.setHeader(
21
- 'Cache-Control',
22
- 'no-store, no-cache, must-revalidate, proxy-revalidate',
21
+ "Cache-Control",
22
+ "no-store, no-cache, must-revalidate, proxy-revalidate",
23
23
  )
24
- res.setHeader('Pragma', 'no-cache')
25
- res.setHeader('Expires', '0')
24
+ res.setHeader("Pragma", "no-cache")
25
+ res.setHeader("Expires", "0")
26
26
 
27
27
  next()
28
28
  }
@@ -30,22 +30,22 @@ const noCache = (req, res, next) => {
30
30
  const routes = [
31
31
  // Health check --------------------------------
32
32
  {
33
- method: 'get',
34
- url: '/',
33
+ method: "get",
34
+ url: "/",
35
35
  handler: (req, res) => {
36
36
  res.sendStatus(200)
37
37
  },
38
38
  },
39
39
  // React config --------------------------------
40
40
  {
41
- method: 'get',
42
- url: '/config.js',
41
+ method: "get",
42
+ url: "/config.js",
43
43
  handler: clientConfig,
44
44
  },
45
45
  // users ---------------------------------------
46
46
  {
47
- method: 'get',
48
- url: '/users/self',
47
+ method: "get",
48
+ url: "/users/self",
49
49
  middleware: [noCache, jwt.authenticate, auth.authenticated],
50
50
  handler: verifyUser,
51
51
  },
@@ -53,78 +53,78 @@ const routes = [
53
53
  // comments --------------------------------------
54
54
 
55
55
  {
56
- method: 'post',
57
- url: '/comments/reply/:commentId/:userId',
56
+ method: "post",
57
+ url: "/comments/reply/:commentId/:userId",
58
58
  handler: comments.reply,
59
59
  },
60
60
 
61
61
  // subscriptions ----------------------------------------
62
62
 
63
63
  {
64
- method: 'get',
65
- url: '/subscriptions/:datasetId',
64
+ method: "get",
65
+ url: "/subscriptions/:datasetId",
66
66
  handler: subscriptions.getSubscriptions,
67
67
  },
68
68
  {
69
- method: 'get',
70
- url: '/subscriptions/:datasetId/:userId',
69
+ method: "get",
70
+ url: "/subscriptions/:datasetId/:userId",
71
71
  middleware: [noCache],
72
72
  handler: subscriptions.checkUserSubscription,
73
73
  },
74
74
  {
75
- method: 'post',
76
- url: '/subscriptions/:datasetId',
75
+ method: "post",
76
+ url: "/subscriptions/:datasetId",
77
77
  middleware: [jwt.authenticate, auth.authenticated],
78
78
  handler: subscriptions.create,
79
79
  },
80
80
  {
81
- method: 'delete',
82
- url: '/subscriptions/:datasetId/:userId',
81
+ method: "delete",
82
+ url: "/subscriptions/:datasetId/:userId",
83
83
  middleware: [jwt.authenticate, auth.authenticated],
84
84
  handler: subscriptions.deleteSubscription,
85
85
  },
86
86
  {
87
- method: 'delete',
88
- url: '/subscriptions/:datasetId',
87
+ method: "delete",
88
+ url: "/subscriptions/:datasetId",
89
89
  middleware: [jwt.authenticate, auth.authenticated],
90
90
  handler: subscriptions.deleteAll,
91
91
  },
92
92
 
93
93
  // dataset doi ----------------------------------------
94
94
  {
95
- method: 'post',
96
- url: '/doi/:datasetId/:snapshotId',
95
+ method: "post",
96
+ url: "/doi/:datasetId/:snapshotId",
97
97
  middleware: [jwt.authenticate, auth.authenticated],
98
98
  handler: doi.createSnapshotDoi,
99
99
  },
100
100
  {
101
- method: 'get',
102
- url: '/doi/:datasetId/:snapshotId',
101
+ method: "get",
102
+ url: "/doi/:datasetId/:snapshotId",
103
103
  handler: doi.getDoi,
104
104
  },
105
105
 
106
106
  // generate CLI API keys ------------------------------
107
107
  {
108
- method: 'post',
109
- url: '/keygen',
108
+ method: "post",
109
+ url: "/keygen",
110
110
  middleware: [noCache, jwt.authenticate, auth.authenticated],
111
111
  handler: users.createAPIKey,
112
112
  },
113
113
 
114
114
  // file routes
115
115
  {
116
- method: 'get',
117
- url: '/datasets/:datasetId/files/:filename',
116
+ method: "get",
117
+ url: "/datasets/:datasetId/files/:filename",
118
118
  handler: datalad.getFile,
119
119
  },
120
120
  {
121
- method: 'get',
122
- url: '/datasets/:datasetId/snapshots/:snapshotId/files/:filename',
121
+ method: "get",
122
+ url: "/datasets/:datasetId/snapshots/:snapshotId/files/:filename",
123
123
  handler: datalad.getFile,
124
124
  },
125
125
  {
126
- method: 'get',
127
- url: '/datasets/:datasetId/objects/:key',
126
+ method: "get",
127
+ url: "/datasets/:datasetId/objects/:key",
128
128
  handler: datalad.getObject,
129
129
  },
130
130
 
@@ -132,42 +132,42 @@ const routes = [
132
132
 
133
133
  // google
134
134
  {
135
- method: 'get',
136
- url: '/auth/google',
135
+ method: "get",
136
+ url: "/auth/google",
137
137
  middleware: [noCache],
138
138
  handler: google.requestAuth,
139
139
  },
140
140
  {
141
- method: 'get',
142
- url: '/auth/google/callback',
141
+ method: "get",
142
+ url: "/auth/google/callback",
143
143
  middleware: [noCache, google.authCallback],
144
144
  handler: jwt.authSuccessHandler,
145
145
  },
146
146
 
147
147
  // orcid
148
148
  {
149
- method: 'get',
150
- url: '/auth/orcid',
149
+ method: "get",
150
+ url: "/auth/orcid",
151
151
  middleware: [noCache],
152
152
  handler: orcid.requestAuth,
153
153
  },
154
154
  {
155
- method: 'get',
156
- url: '/auth/orcid/callback',
155
+ method: "get",
156
+ url: "/auth/orcid/callback",
157
157
  middleware: [noCache, orcid.authCallback],
158
158
  handler: jwt.authSuccessHandler,
159
159
  },
160
160
  // Anonymous reviewer access
161
161
  {
162
- method: 'get',
163
- url: '/reviewer/:token',
162
+ method: "get",
163
+ url: "/reviewer/:token",
164
164
  middleware: [noCache],
165
165
  handler: reviewerHandler,
166
166
  },
167
167
  // sitemap
168
168
  {
169
- method: 'get',
170
- url: '/sitemap',
169
+ method: "get",
170
+ url: "/sitemap",
171
171
  handler: sitemapHandler,
172
172
  },
173
173
  ]
@@ -177,7 +177,7 @@ const routes = [
177
177
  const router = express.Router()
178
178
 
179
179
  for (const route of routes) {
180
- const arr = route.hasOwnProperty('middleware') ? route.middleware : []
180
+ const arr = route.hasOwnProperty("middleware") ? route.middleware : []
181
181
  arr.unshift(route.url)
182
182
  arr.push(route.handler)
183
183
  router[route.method](...arr)
package/src/server.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  /** Needs to run before the other imports in Node */
2
- import apm from 'elastic-apm-node'
2
+ import apm from "elastic-apm-node"
3
3
  apm.start({
4
- serviceName: 'openneuro-server',
5
- cloudProvider: 'none',
4
+ serviceName: "openneuro-server",
5
+ cloudProvider: "none",
6
6
  })
7
7
 
8
- import { createServer } from 'http'
9
- import mongoose from 'mongoose'
10
- import { connect as redisConnect } from './libs/redis'
11
- import config from './config'
12
- import { expressApolloSetup } from './app'
8
+ import { createServer } from "http"
9
+ import mongoose from "mongoose"
10
+ import { connect as redisConnect } from "./libs/redis"
11
+ import config from "./config"
12
+ import { expressApolloSetup } from "./app"
13
13
 
14
14
  const redisConnectionSetup = async () => {
15
15
  try {
@@ -31,7 +31,7 @@ void redisConnectionSetup().then(async () => {
31
31
  const server = createServer(app)
32
32
  server.listen(config.port, () => {
33
33
  // eslint-disable-next-line no-console
34
- console.log('Server is listening on port ' + config.port)
34
+ console.log("Server is listening on port " + config.port)
35
35
  // Setup GraphQL subscription transport
36
36
  //subscriptionServerFactory(server)
37
37
  })
@@ -1,53 +1,53 @@
1
- import { vi } from 'vitest'
1
+ import { vi } from "vitest"
2
2
  import {
3
3
  datasetOrSnapshot,
4
4
  getDatasetFromSnapshotId,
5
- } from '../datasetOrSnapshot'
5
+ } from "../datasetOrSnapshot"
6
6
 
7
- vi.mock('ioredis')
7
+ vi.mock("ioredis")
8
8
 
9
- describe('datasetOrSnapshot()', () => {
10
- it('resolves a dataset object correctly', () => {
9
+ describe("datasetOrSnapshot()", () => {
10
+ it("resolves a dataset object correctly", () => {
11
11
  const dataset = {
12
- id: 'ds000001',
13
- revision: 'abcfdeg',
12
+ id: "ds000001",
13
+ revision: "abcfdeg",
14
14
  modified: new Date(),
15
15
  draft: {
16
- id: 'abcfdeg',
16
+ id: "abcfdeg",
17
17
  },
18
18
  }
19
19
  expect(datasetOrSnapshot(dataset)).toEqual({
20
- datasetId: 'ds000001',
21
- revision: 'abcfdeg',
20
+ datasetId: "ds000001",
21
+ revision: "abcfdeg",
22
22
  })
23
23
  })
24
- it('resolves snapshot objects correctly', () => {
24
+ it("resolves snapshot objects correctly", () => {
25
25
  const snapshot = {
26
- id: 'ds000001:1.0.0',
27
- tag: '1.0.0',
28
- hexsha: 'abcfdeg',
26
+ id: "ds000001:1.0.0",
27
+ tag: "1.0.0",
28
+ hexsha: "abcfdeg",
29
29
  modified: new Date(),
30
- files: [{ id: '1234', filename: 'dataset_description.json' }],
30
+ files: [{ id: "1234", filename: "dataset_description.json" }],
31
31
  }
32
32
  expect(datasetOrSnapshot(snapshot)).toEqual({
33
- datasetId: 'ds000001',
34
- revision: 'abcfdeg',
33
+ datasetId: "ds000001",
34
+ revision: "abcfdeg",
35
35
  })
36
36
  })
37
- it('resolves the snapshot tag only corner case', () => {
37
+ it("resolves the snapshot tag only corner case", () => {
38
38
  const snapshot = {
39
- id: 'ds000002:1.0.1',
40
- tag: '1.0.1',
39
+ id: "ds000002:1.0.1",
40
+ tag: "1.0.1",
41
41
  modified: new Date(),
42
42
  }
43
43
  expect(datasetOrSnapshot(snapshot)).toEqual({
44
- datasetId: 'ds000002',
45
- revision: '1.0.1',
44
+ datasetId: "ds000002",
45
+ revision: "1.0.1",
46
46
  })
47
47
  })
48
- describe('getDatasetFromSnapshotId', () => {
49
- it('extracts the datasetId correctly', () => {
50
- expect(getDatasetFromSnapshotId('ds000001:1.0.0')).toBe('ds000001')
48
+ describe("getDatasetFromSnapshotId", () => {
49
+ it("extracts the datasetId correctly", () => {
50
+ expect(getDatasetFromSnapshotId("ds000001:1.0.0")).toBe("ds000001")
51
51
  })
52
52
  })
53
53
  })
@@ -1,16 +1,16 @@
1
- import { vi } from 'vitest'
2
- import { validateUrl } from '../validateUrl'
1
+ import { vi } from "vitest"
2
+ import { validateUrl } from "../validateUrl"
3
3
 
4
- vi.mock('ioredis')
4
+ vi.mock("ioredis")
5
5
 
6
- describe('validateUrl', () => {
7
- it('returns true for a regular HTTPS url', () => {
8
- expect(validateUrl('https://openneuro.org')).toBe(true)
6
+ describe("validateUrl", () => {
7
+ it("returns true for a regular HTTPS url", () => {
8
+ expect(validateUrl("https://openneuro.org")).toBe(true)
9
9
  })
10
- it('returns false for a regular HTTP url', () => {
11
- expect(validateUrl('http://openneuro.org')).toBe(false)
10
+ it("returns false for a regular HTTP url", () => {
11
+ expect(validateUrl("http://openneuro.org")).toBe(false)
12
12
  })
13
- it('returns false for something that is not really a URL', () => {
14
- expect(validateUrl('openneuro.org/robots.txt')).toBe(false)
13
+ it("returns false for something that is not really a URL", () => {
14
+ expect(validateUrl("openneuro.org/robots.txt")).toBe(false)
15
15
  })
16
16
  })
@@ -23,7 +23,7 @@ export type DatasetOrSnapshot = HasId | HasSnapshotId
23
23
  export function datasetOrSnapshot(
24
24
  obj: DatasetOrSnapshot,
25
25
  ): DatasetRevisionReference {
26
- if ('tag' in obj) {
26
+ if ("tag" in obj) {
27
27
  return {
28
28
  datasetId: getDatasetFromSnapshotId(obj.id),
29
29
  revision: obj.hexsha || obj.tag,
@@ -38,5 +38,5 @@ export function datasetOrSnapshot(
38
38
  * @returns {string} Dataset id portion 'ds000001'
39
39
  */
40
40
  export function getDatasetFromSnapshotId(snapshotId: string): string {
41
- return snapshotId.split(':')[0]
41
+ return snapshotId.split(":")[0]
42
42
  }
@@ -6,7 +6,7 @@
6
6
  export function validateUrl(value: string): boolean {
7
7
  try {
8
8
  const url = new URL(value)
9
- return url.protocol === 'https:'
9
+ return url.protocol === "https:"
10
10
  } catch (err) {
11
11
  return false
12
12
  }
@@ -1,82 +0,0 @@
1
- import * as changelog from '../changelog.js'
2
-
3
- vi.mock('ioredis')
4
- vi.mock('../../config.js')
5
-
6
- describe('changelog editing tools', () => {
7
- describe('findVersion()', () => {
8
- it('finds the version bounds for a single entry', () => {
9
- const newChanges = ['1.0.0 2019-01-01', ' - Initial version']
10
- expect(changelog.findVersion(newChanges, '1.0.0')).toEqual([0, 2])
11
- })
12
- it('returns an empty array when no matching version is found', () => {
13
- const newChanges = ['1.0.0 2019-01-01', ' - Initial version']
14
- expect(changelog.findVersion(newChanges, '1.0.1')).toEqual([])
15
- })
16
- it('returns the correct offset for a change in the middle of others', () => {
17
- const newChanges = [
18
- '2.0.0 2019-02-02',
19
- ' - New derivatives',
20
- '1.1.0 2019-02-01',
21
- ' - Added subjects',
22
- ' - Fixed metadata',
23
- '1.0.0 2019-01-01',
24
- ' - Initial version',
25
- ]
26
- expect(changelog.findVersion(newChanges, '1.1.0')).toEqual([2, 3])
27
- })
28
- it('works with fuzzy data', () => {
29
- const newChanges = ['I', 'am', 'a', 'banana']
30
- expect(changelog.findVersion(newChanges, '1.0.0')).toEqual([])
31
- })
32
- })
33
- describe('spliceChangelog()', () => {
34
- it('splices in changes to an existing changelog', () => {
35
- const original = '1.0.0 2019-01-01\n - Initial version\n'
36
- const changes = ['Some new change', 'Another new change']
37
- const tag = '1.0.0'
38
- expect(
39
- changelog.spliceChangelog(original, tag, '2019-02-01', changes),
40
- ).toEqual(
41
- '1.0.0 2019-02-01\n - Some new change\n - Another new change\n',
42
- )
43
- })
44
- it('splices correctly when no matching version is found', () => {
45
- const original = '1.0.0 2019-01-01\n - Initial version\n'
46
- const changes = ['Some new change']
47
- const tag = '1.0.1'
48
- expect(
49
- changelog.spliceChangelog(original, tag, '2019-02-01', changes),
50
- ).toEqual(
51
- '1.0.1 2019-02-01\n - Some new change\n1.0.0 2019-01-01\n - Initial version\n',
52
- )
53
- })
54
- it('handles fuzzy data', () => {
55
- const original = 'abc 123 not a changelog\nnope'
56
- const changes = ['Fixed up data']
57
- const tag = '1.0.0'
58
- expect(
59
- changelog.spliceChangelog(original, tag, '2019-02-01', changes),
60
- ).toEqual(
61
- '1.0.0 2019-02-01\n - Fixed up data\nabc 123 not a changelog\nnope\n',
62
- )
63
- })
64
- it('works with legacy versions', () => {
65
- const original = '00001 1999-12-31\n - Partying'
66
- const changes = ['Bringing dataset into the present day']
67
- const tag = '1.0.0'
68
- expect(
69
- changelog.spliceChangelog(original, tag, '2019-02-01', changes),
70
- ).toEqual(
71
- '1.0.0 2019-02-01\n - Bringing dataset into the present day\n00001 1999-12-31\n - Partying\n',
72
- )
73
- })
74
- it('works if no CHANGES are provided', () => {
75
- expect(
76
- changelog.spliceChangelog('', '1.0.0', '2019-03-04', [
77
- 'Initial snapshot',
78
- ]),
79
- ).toEqual('1.0.0 2019-03-04\n - Initial snapshot\n')
80
- })
81
- })
82
- })
@@ -1,109 +0,0 @@
1
- import { vi } from 'vitest'
2
- import request from 'superagent'
3
- import { createDataset, datasetsFilter, testBlacklist } from '../dataset.js'
4
- import { getDatasetWorker } from '../../libs/datalad-service'
5
- import { connect } from 'mongoose'
6
-
7
- // Mock requests to Datalad service
8
- vi.mock('superagent')
9
- vi.mock('ioredis')
10
- vi.mock('../../libs/redis.js')
11
- vi.mock('../../config.js')
12
- vi.mock('../../libs/notifications.js')
13
-
14
- describe('dataset model operations', () => {
15
- describe('createDataset()', () => {
16
- beforeAll(() => {
17
- // Setup MongoDB with mongodb-memory-server
18
- connect(globalThis.__MONGO_URI__)
19
- })
20
- it('resolves to dataset id string', async () => {
21
- const user = { id: '1234' }
22
- const { id: dsId } = await createDataset(user.id, user, {
23
- affirmedDefaced: true,
24
- affirmedConsent: true,
25
- })
26
- expect(dsId).toHaveLength(8)
27
- expect(dsId.slice(0, 2)).toBe('ds')
28
- })
29
- it('posts to the DataLad /datasets/{dsId} endpoint', async () => {
30
- const user = { id: '1234' }
31
- // Reset call count for request.post
32
- request.post.mockClear()
33
- const { id: dsId } = await createDataset(user.id, user, {
34
- affirmedDefaced: true,
35
- affirmedConsent: true,
36
- })
37
- expect(request.post).toHaveBeenCalledTimes(1)
38
- expect(request.post).toHaveBeenCalledWith(
39
- expect.stringContaining(`${getDatasetWorker(dsId)}/datasets/`),
40
- )
41
- })
42
- })
43
- describe('datasetsFilter()', () => {
44
- describe('filterBy: {all: true} ', () => {
45
- it('returns the specified match for regular users', () => {
46
- const testMatch = { test: 'match' }
47
- expect(
48
- datasetsFilter({
49
- userId: '1234',
50
- admin: false,
51
- filterBy: { all: true },
52
- })(testMatch)[0].$match,
53
- ).toBe(testMatch)
54
- })
55
- it('excludes match argument for admins', () => {
56
- const testMatch = { test: 'match' }
57
- expect(
58
- datasetsFilter({
59
- userId: '5678',
60
- admin: true,
61
- filterBy: { all: true },
62
- })(testMatch),
63
- ).not.toBe(testMatch)
64
- })
65
- })
66
- describe('filterBy: {invalid: true}', () => {
67
- it('returns the correct number of stages', () => {
68
- expect(
69
- datasetsFilter({ filterBy: { invalid: true } })({}),
70
- ).toHaveLength(4)
71
- })
72
- })
73
- describe('filterBy: {invalid: true, public: true}', () => {
74
- it('returns the same number of stages as invalid: true', () => {
75
- expect(
76
- datasetsFilter({ filterBy: { invalid: true, public: true } })({}),
77
- ).toHaveLength(4)
78
- })
79
- it('returns one less stage for admins with all', () => {
80
- expect(
81
- datasetsFilter({
82
- admin: true,
83
- filterBy: { invalid: true, public: true, all: true },
84
- })({}),
85
- ).toHaveLength(3)
86
- })
87
- })
88
- describe('testBlacklist', () => {
89
- it('returns false for .bidsignore', () => {
90
- expect(testBlacklist('', '.bidsignore')).toBe(false)
91
- })
92
- it('returns true for .git paths', () => {
93
- expect(testBlacklist('.git', 'HEAD')).toBe(true)
94
- })
95
- it('returns true for root level .DS_Store files', () => {
96
- expect(testBlacklist('', '.DS_Store')).toBe(true)
97
- })
98
- it('returns true for nested .DS_Store files', () => {
99
- expect(testBlacklist('sub-01/anat/', '.DS_Store')).toBe(true)
100
- })
101
- // https://github.com/OpenNeuroOrg/openneuro/issues/2519
102
- it('skips ._ prefixed files created by macOS', () => {
103
- expect(testBlacklist('', '._.DS_Store')).toBe(true)
104
- expect(testBlacklist('stimuli/', '._1002.png')).toBe(true)
105
- expect(testBlacklist('stimuli/', 'test._1002.png')).toBe(false)
106
- })
107
- })
108
- })
109
- })