@openneuro/server 5.0.0 → 5.1.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.
Files changed (98) hide show
  1. package/package.json +8 -5
  2. package/src/app.ts +2 -4
  3. package/src/cache/__tests__/tree.spec.ts +2 -0
  4. package/src/cache/tree.ts +4 -0
  5. package/src/cache/types.ts +1 -0
  6. package/src/datalad/__tests__/contributors.spec.ts +1 -1
  7. package/src/datalad/__tests__/dataRetentionNotifications.spec.ts +11 -11
  8. package/src/datalad/__tests__/files.spec.ts +31 -1
  9. package/src/datalad/__tests__/snapshots.spec.ts +4 -4
  10. package/src/datalad/contributors.ts +2 -2
  11. package/src/datalad/dataRetentionNotifications.ts +5 -5
  12. package/src/datalad/dataset.ts +9 -5
  13. package/src/datalad/description.ts +2 -2
  14. package/src/datalad/draft.ts +8 -3
  15. package/src/datalad/files.ts +71 -12
  16. package/src/datalad/readme.ts +2 -2
  17. package/src/datalad/snapshots.ts +19 -14
  18. package/src/elasticsearch/elastic-client.ts +11 -6
  19. package/src/elasticsearch/reindex-dataset.ts +8 -4
  20. package/src/graphql/__tests__/comment.spec.ts +3 -2
  21. package/src/graphql/__tests__/schema.spec.ts +28 -0
  22. package/src/graphql/builder.ts +42 -0
  23. package/src/graphql/resolvers/__tests__/dataset.spec.ts +6 -119
  24. package/src/graphql/resolvers/__tests__/importRemoteDataset.spec.ts +2 -1
  25. package/src/graphql/resolvers/__tests__/permssions.spec.ts +3 -2
  26. package/src/graphql/resolvers/__tests__/user.spec.ts +39 -11
  27. package/src/graphql/resolvers/brainInitiative.ts +4 -3
  28. package/src/graphql/resolvers/cache.ts +7 -6
  29. package/src/graphql/resolvers/comment.ts +35 -19
  30. package/src/graphql/resolvers/dataset-search.ts +7 -6
  31. package/src/graphql/resolvers/dataset.ts +77 -45
  32. package/src/graphql/resolvers/datasetEvents.ts +18 -16
  33. package/src/graphql/resolvers/description.ts +2 -1
  34. package/src/graphql/resolvers/draft.ts +14 -3
  35. package/src/graphql/resolvers/fileCheck.ts +5 -4
  36. package/src/graphql/resolvers/flaggedFiles.ts +2 -1
  37. package/src/graphql/resolvers/follow.ts +2 -1
  38. package/src/graphql/resolvers/git.ts +2 -1
  39. package/src/graphql/resolvers/gitEvents.ts +2 -1
  40. package/src/graphql/resolvers/history.ts +3 -1
  41. package/src/graphql/resolvers/holdDeletion.ts +1 -1
  42. package/src/graphql/resolvers/importRemoteDataset.ts +3 -2
  43. package/src/graphql/resolvers/issues.ts +2 -1
  44. package/src/graphql/resolvers/metadata.ts +3 -2
  45. package/src/graphql/resolvers/permissions.ts +26 -6
  46. package/src/graphql/resolvers/publish.ts +2 -1
  47. package/src/graphql/resolvers/readme.ts +2 -1
  48. package/src/graphql/resolvers/reexporter.ts +2 -1
  49. package/src/graphql/resolvers/relation.ts +3 -2
  50. package/src/graphql/resolvers/reset.ts +2 -1
  51. package/src/graphql/resolvers/reviewer.ts +14 -6
  52. package/src/graphql/resolvers/snapshots.ts +42 -10
  53. package/src/graphql/resolvers/stars.ts +2 -1
  54. package/src/graphql/resolvers/upload.ts +3 -2
  55. package/src/graphql/resolvers/user.ts +44 -32
  56. package/src/graphql/resolvers/validation.ts +6 -5
  57. package/src/graphql/resolvers/worker.ts +2 -1
  58. package/src/graphql/schema/analytics.ts +12 -0
  59. package/src/graphql/schema/comment.ts +30 -0
  60. package/src/graphql/schema/dataset-events.ts +91 -0
  61. package/src/graphql/schema/dataset-search.ts +32 -0
  62. package/src/graphql/schema/dataset.ts +167 -0
  63. package/src/graphql/schema/description.ts +44 -0
  64. package/src/graphql/schema/draft.ts +80 -0
  65. package/src/graphql/schema/enums.ts +55 -0
  66. package/src/graphql/schema/files.ts +44 -0
  67. package/src/graphql/schema/inputs.ts +231 -0
  68. package/src/graphql/schema/metadata.ts +86 -0
  69. package/src/graphql/schema/misc.ts +154 -0
  70. package/src/graphql/schema/mutation.ts +549 -0
  71. package/src/graphql/schema/pagination.ts +12 -0
  72. package/src/graphql/schema/permissions.ts +21 -0
  73. package/src/graphql/schema/query.ts +119 -0
  74. package/src/graphql/schema/refs.ts +23 -0
  75. package/src/graphql/schema/reviewer.ts +11 -0
  76. package/src/graphql/schema/scalars.ts +9 -0
  77. package/src/graphql/schema/snapshot.ts +111 -0
  78. package/src/graphql/schema/upload.ts +13 -0
  79. package/src/graphql/schema/user.ts +61 -0
  80. package/src/graphql/schema/validation.ts +70 -0
  81. package/src/graphql/schema/worker.ts +16 -0
  82. package/src/graphql/schema.ts +29 -1114
  83. package/src/handlers/subscriptions.ts +1 -1
  84. package/src/libs/apikey.ts +1 -1
  85. package/src/libs/authentication/crypto.ts +14 -9
  86. package/src/libs/notifications.ts +1 -1
  87. package/src/libs/presign.ts +32 -20
  88. package/src/libs/redis.ts +12 -2
  89. package/src/models/comment.ts +2 -4
  90. package/src/models/counter.ts +2 -2
  91. package/src/models/ingestDataset.ts +1 -2
  92. package/src/models/notification.ts +0 -2
  93. package/src/models/subscription.ts +0 -1
  94. package/src/models/user.ts +1 -2
  95. package/src/models/userMigration.ts +1 -1
  96. package/src/models/userNotificationStatus.ts +0 -1
  97. package/src/utils/__tests__/snapshots.spec.ts +120 -0
  98. package/src/utils/snapshots.ts +12 -0
@@ -0,0 +1,55 @@
1
+ import { builder } from "../builder"
2
+
3
+ export const SortOrdering = builder.enumType("SortOrdering", {
4
+ values: ["ascending", "descending"] as const,
5
+ })
6
+
7
+ export const UserProvider = builder.enumType("UserProvider", {
8
+ description: "Which provider a user login comes from",
9
+ values: ["google", "orcid"] as const,
10
+ })
11
+
12
+ export const AnalyticTypes = builder.enumType("AnalyticTypes", {
13
+ values: ["downloads", "views"] as const,
14
+ })
15
+
16
+ export const ResponseStatusType = builder.enumType("ResponseStatusType", {
17
+ values: ["PENDING", "ACCEPTED", "DENIED"] as const,
18
+ })
19
+
20
+ export const NotificationStatusType = builder.enumType(
21
+ "NotificationStatusType",
22
+ {
23
+ values: ["UNREAD", "SAVED", "ARCHIVED"] as const,
24
+ },
25
+ )
26
+
27
+ export const Severity = builder.enumType("Severity", {
28
+ values: ["error", "warning"] as const,
29
+ })
30
+
31
+ export const RelatedObjectRelation = builder.enumType(
32
+ "RelatedObjectRelation",
33
+ {
34
+ description: "RelatedObject nature of relationship",
35
+ values: ["sameAs", "derivative", "source"] as const,
36
+ },
37
+ )
38
+
39
+ export const RelatedObjectKind = builder.enumType("RelatedObjectKind", {
40
+ description: "RelatedObject kind of target object",
41
+ values: ["Dataset", "Article"] as const,
42
+ })
43
+
44
+ export const SearchSortOption = builder.enumType("SearchSortOption", {
45
+ description: "Sort options for advanced dataset search",
46
+ values: [
47
+ "relevance",
48
+ "newest",
49
+ "oldest",
50
+ "activity",
51
+ "name_asc",
52
+ "name_desc",
53
+ "last_updated",
54
+ ] as const,
55
+ })
@@ -0,0 +1,44 @@
1
+ import { builder } from "../builder"
2
+ import { Severity } from "./enums"
3
+
4
+ export const DatasetFile = builder.simpleObject("DatasetFile", {
5
+ description: "File metadata and link to contents",
6
+ fields: (t) => ({
7
+ id: t.id({ nullable: false }),
8
+ filename: t.string({ nullable: false }),
9
+ size: t.field({ type: "BigInt" }),
10
+ annexed: t.boolean(),
11
+ urls: t.stringList({ nullable: { list: true, items: true } }),
12
+ directory: t.boolean(),
13
+ }),
14
+ })
15
+
16
+ export const ValidationIssueFile = builder.simpleObject("ValidationIssueFile", {
17
+ fields: (t) => ({
18
+ name: t.string(),
19
+ path: t.string(),
20
+ key: t.string({ nullable: false }),
21
+ code: t.int(),
22
+ file: t.field({ type: ValidationIssueFileDetail }),
23
+ evidence: t.string(),
24
+ line: t.int(),
25
+ character: t.int(),
26
+ severity: t.field({
27
+ type: Severity,
28
+ nullable: false,
29
+ }),
30
+ reason: t.string(),
31
+ helpUrl: t.string(),
32
+ }),
33
+ })
34
+
35
+ export const ValidationIssueFileDetail = builder.simpleObject(
36
+ "ValidationIssueFileDetail",
37
+ {
38
+ fields: (t) => ({
39
+ name: t.string(),
40
+ path: t.string(),
41
+ relativePath: t.string(),
42
+ }),
43
+ },
44
+ )
@@ -0,0 +1,231 @@
1
+ import { builder } from "../builder"
2
+ import { SearchSortOption, Severity, SortOrdering } from "./enums"
3
+
4
+ export const UserSortInput = builder.inputType("UserSortInput", {
5
+ fields: (t) => ({
6
+ field: t.string({ required: true }),
7
+ order: t.field({ type: SortOrdering, defaultValue: "ascending" }),
8
+ }),
9
+ })
10
+
11
+ export const DatasetSort = builder.inputType("DatasetSort", {
12
+ fields: (t) => ({
13
+ created: t.field({ type: SortOrdering }),
14
+ name: t.field({ type: SortOrdering }),
15
+ uploader: t.field({ type: SortOrdering }),
16
+ stars: t.field({ type: SortOrdering }),
17
+ downloads: t.field({ type: SortOrdering }),
18
+ views: t.field({ type: SortOrdering }),
19
+ subscriptions: t.field({ type: SortOrdering }),
20
+ publishDate: t.field({ type: SortOrdering }),
21
+ }),
22
+ })
23
+
24
+ export const DatasetFilter = builder.inputType("DatasetFilter", {
25
+ fields: (t) => ({
26
+ public: t.boolean({
27
+ description: "Limit to datasets available publicly",
28
+ }),
29
+ shared: t.boolean({
30
+ description: "Return only datasets that are shared with the user",
31
+ }),
32
+ invalid: t.boolean({
33
+ description: "Return only datasets with an invalid Draft",
34
+ }),
35
+ starred: t.boolean({
36
+ description: "Return only datasets starred by the query user",
37
+ }),
38
+ all: t.boolean({
39
+ description:
40
+ "Return all datasets, ignores any other constraints but not sorts",
41
+ }),
42
+ }),
43
+ })
44
+
45
+ export const DeleteFile = builder.inputType("DeleteFile", {
46
+ fields: (t) => ({
47
+ path: t.string({ required: true }),
48
+ filename: t.string(),
49
+ }),
50
+ })
51
+
52
+ export const SummaryPetInput = builder.inputType("SummaryPetInput", {
53
+ fields: (t) => ({
54
+ BodyPart: t.stringList(),
55
+ ScannerManufacturer: t.stringList(),
56
+ ScannerManufacturersModelName: t.stringList(),
57
+ TracerName: t.stringList(),
58
+ TracerRadionuclide: t.stringList(),
59
+ }),
60
+ })
61
+
62
+ export const ValidatorMetadataInput = builder.inputType(
63
+ "ValidatorMetadataInput",
64
+ {
65
+ fields: (t) => ({
66
+ validator: t.string(),
67
+ version: t.string(),
68
+ }),
69
+ },
70
+ )
71
+
72
+ export const SubjectMetadataInput = builder.inputType(
73
+ "SubjectMetadataInput",
74
+ {
75
+ fields: (t) => ({
76
+ participantId: t.string({ required: true }),
77
+ age: t.float(),
78
+ sex: t.string(),
79
+ group: t.string(),
80
+ }),
81
+ },
82
+ )
83
+
84
+ export const SummaryInput = builder.inputType("SummaryInput", {
85
+ fields: (t) => ({
86
+ id: t.id({ required: true }),
87
+ datasetId: t.id({ required: true }),
88
+ modalities: t.stringList(),
89
+ secondaryModalities: t.stringList(),
90
+ dataTypes: t.stringList(),
91
+ sessions: t.stringList(),
92
+ subjects: t.stringList(),
93
+ subjectMetadata: t.field({ type: [SubjectMetadataInput] }),
94
+ tasks: t.stringList(),
95
+ size: t.field({ type: "BigInt", required: true }),
96
+ totalFiles: t.int({ required: true }),
97
+ dataProcessed: t.boolean(),
98
+ pet: t.field({ type: SummaryPetInput }),
99
+ validatorMetadata: t.field({ type: ValidatorMetadataInput }),
100
+ schemaVersion: t.string(),
101
+ }),
102
+ })
103
+
104
+ export const ValidatorIssueInput = builder.inputType("ValidatorIssueInput", {
105
+ fields: (t) => ({
106
+ code: t.string({ required: true }),
107
+ subCode: t.string(),
108
+ location: t.string(),
109
+ severity: t.field({ type: Severity }),
110
+ rule: t.string(),
111
+ issueMessage: t.string(),
112
+ affects: t.string(),
113
+ line: t.int(),
114
+ }),
115
+ })
116
+
117
+ export const ValidatorCodeMessageInput = builder.inputType(
118
+ "ValidatorCodeMessageInput",
119
+ {
120
+ fields: (t) => ({
121
+ code: t.string({ required: true }),
122
+ message: t.string({ required: true }),
123
+ }),
124
+ },
125
+ )
126
+
127
+ export const ValidatorInput = builder.inputType("ValidatorInput", {
128
+ fields: (t) => ({
129
+ id: t.id({ required: true }),
130
+ datasetId: t.id({ required: true }),
131
+ issues: t.field({ type: [ValidatorIssueInput], required: true }),
132
+ codeMessages: t.field({
133
+ type: [ValidatorCodeMessageInput],
134
+ required: true,
135
+ }),
136
+ validatorMetadata: t.field({
137
+ type: ValidatorMetadataInput,
138
+ required: true,
139
+ }),
140
+ }),
141
+ })
142
+
143
+ export const MetadataInput = builder.inputType("MetadataInput", {
144
+ fields: (t) => ({
145
+ datasetId: t.id({ required: true }),
146
+ datasetUrl: t.string(),
147
+ datasetName: t.string(),
148
+ firstSnapshotCreatedAt: t.field({ type: "DateTime" }),
149
+ latestSnapshotCreatedAt: t.field({ type: "DateTime" }),
150
+ dxStatus: t.string(),
151
+ tasksCompleted: t.stringList(),
152
+ trialCount: t.int(),
153
+ studyDesign: t.string(),
154
+ studyDomain: t.string(),
155
+ studyLongitudinal: t.string(),
156
+ dataProcessed: t.boolean(),
157
+ species: t.string(),
158
+ associatedPaperDOI: t.string(),
159
+ openneuroPaperDOI: t.string(),
160
+ seniorAuthor: t.string(),
161
+ adminUsers: t.stringList(),
162
+ ages: t.floatList(),
163
+ modalities: t.stringList(),
164
+ grantFunderName: t.string(),
165
+ grantIdentifier: t.string(),
166
+ affirmedDefaced: t.boolean(),
167
+ affirmedConsent: t.boolean(),
168
+ }),
169
+ })
170
+
171
+ export const AnnexFsckInput = builder.inputType("AnnexFsckInput", {
172
+ fields: (t) => ({
173
+ command: t.string(),
174
+ errorMessages: t.stringList(),
175
+ file: t.string(),
176
+ key: t.string(),
177
+ note: t.string(),
178
+ success: t.boolean(),
179
+ dead: t.stringList(),
180
+ missing: t.stringList(),
181
+ untrusted: t.stringList(),
182
+ input: t.stringList(),
183
+ }),
184
+ })
185
+
186
+ export const ContributorInput = builder.inputType("ContributorInput", {
187
+ fields: (t) => ({
188
+ name: t.string(),
189
+ givenName: t.string(),
190
+ familyName: t.string(),
191
+ orcid: t.string(),
192
+ contributorType: t.string(),
193
+ order: t.int(),
194
+ }),
195
+ })
196
+
197
+ export const DatasetSearchInput = builder.inputType("DatasetSearchInput", {
198
+ description: "Search input for advanced dataset search",
199
+ fields: (t) => ({
200
+ keywords: t.stringList(),
201
+ modality: t.string(),
202
+ ageRange: t.field({
203
+ type: ["Int"],
204
+ required: { list: false, items: false },
205
+ }),
206
+ subjectCountRange: t.field({
207
+ type: ["Int"],
208
+ required: { list: false, items: false },
209
+ }),
210
+ diagnosis: t.string(),
211
+ tasks: t.stringList(),
212
+ authors: t.stringList(),
213
+ sex: t.string(),
214
+ dateRange: t.string(),
215
+ species: t.string(),
216
+ studyStructure: t.string(),
217
+ studyDomains: t.stringList(),
218
+ bidsDatasetType: t.string(),
219
+ brainInitiative: t.boolean(),
220
+ bodyParts: t.stringList(),
221
+ scannerManufacturers: t.stringList(),
222
+ scannerManufacturersModelNames: t.stringList(),
223
+ tracerNames: t.stringList(),
224
+ tracerRadionuclides: t.stringList(),
225
+ sortBy: t.field({ type: SearchSortOption }),
226
+ userId: t.string({
227
+ description: "Filter datasets by a specific user's permissions",
228
+ }),
229
+ publicOnly: t.boolean({ description: "Filter to only public datasets" }),
230
+ }),
231
+ })
@@ -0,0 +1,86 @@
1
+ import { builder } from "../builder"
2
+
3
+ export const SubjectMetadata = builder.simpleObject("SubjectMetadata", {
4
+ fields: (t) => ({
5
+ participantId: t.string({ nullable: false }),
6
+ age: t.float(),
7
+ sex: t.string(),
8
+ group: t.string(),
9
+ }),
10
+ })
11
+
12
+ export const SummaryPetFields = builder.simpleObject("SummaryPetFields", {
13
+ fields: (t) => ({
14
+ BodyPart: t.stringList({ nullable: { list: true, items: true } }),
15
+ ScannerManufacturer: t.stringList({
16
+ nullable: { list: true, items: true },
17
+ }),
18
+ ScannerManufacturersModelName: t.stringList({
19
+ nullable: { list: true, items: true },
20
+ }),
21
+ TracerName: t.stringList({ nullable: { list: true, items: true } }),
22
+ TracerRadionuclide: t.stringList({ nullable: { list: true, items: true } }),
23
+ }),
24
+ })
25
+
26
+ export const ValidatorMetadata = builder.simpleObject("ValidatorMetadata", {
27
+ description: "BIDS Validator metadata",
28
+ fields: (t) => ({
29
+ validator: t.string(),
30
+ version: t.string(),
31
+ }),
32
+ })
33
+
34
+ export const Summary = builder.simpleObject("Summary", {
35
+ description: "Validator summary from bids-validator",
36
+ fields: (t) => ({
37
+ id: t.id({ nullable: false }),
38
+ modalities: t.stringList({ nullable: { list: true, items: true } }),
39
+ primaryModality: t.string(),
40
+ secondaryModalities: t.stringList({
41
+ nullable: { list: true, items: true },
42
+ }),
43
+ sessions: t.stringList({ nullable: { list: true, items: true } }),
44
+ subjects: t.stringList({ nullable: { list: true, items: true } }),
45
+ subjectMetadata: t.field({
46
+ type: [SubjectMetadata],
47
+ nullable: { list: true, items: true },
48
+ }),
49
+ tasks: t.stringList({ nullable: { list: true, items: true } }),
50
+ size: t.field({ type: "BigInt", nullable: false }),
51
+ totalFiles: t.int({ nullable: false }),
52
+ dataProcessed: t.boolean(),
53
+ pet: t.field({ type: SummaryPetFields }),
54
+ schemaVersion: t.string(),
55
+ validatorMetadata: t.field({ type: ValidatorMetadata }),
56
+ }),
57
+ })
58
+
59
+ export const Metadata = builder.simpleObject("Metadata", {
60
+ description: "Dataset Metadata",
61
+ fields: (t) => ({
62
+ datasetId: t.id({ nullable: false }),
63
+ datasetUrl: t.string(),
64
+ datasetName: t.string(),
65
+ firstSnapshotCreatedAt: t.field({ type: "DateTime" }),
66
+ latestSnapshotCreatedAt: t.field({ type: "DateTime" }),
67
+ dxStatus: t.string(),
68
+ tasksCompleted: t.stringList({ nullable: { list: true, items: true } }),
69
+ trialCount: t.int(),
70
+ studyDesign: t.string(),
71
+ studyDomain: t.string(),
72
+ studyLongitudinal: t.string(),
73
+ dataProcessed: t.boolean(),
74
+ species: t.string(),
75
+ associatedPaperDOI: t.string(),
76
+ openneuroPaperDOI: t.string(),
77
+ seniorAuthor: t.string(),
78
+ adminUsers: t.stringList({ nullable: { list: true, items: true } }),
79
+ ages: t.floatList({ nullable: { list: true, items: true } }),
80
+ modalities: t.stringList({ nullable: { list: true, items: true } }),
81
+ grantFunderName: t.string(),
82
+ grantIdentifier: t.string(),
83
+ affirmedDefaced: t.boolean(),
84
+ affirmedConsent: t.boolean(),
85
+ }),
86
+ })
@@ -0,0 +1,154 @@
1
+ import { builder } from "../builder"
2
+ import { UserRef } from "./refs"
3
+ import {
4
+ NotificationStatusType,
5
+ RelatedObjectKind,
6
+ RelatedObjectRelation,
7
+ } from "./enums"
8
+
9
+ export const RepoMetadata = builder.simpleObject("RepoMetadata", {
10
+ description: "Info needed to access git repositories directly",
11
+ fields: (t) => ({
12
+ token: t.string(),
13
+ endpoint: t.int(),
14
+ }),
15
+ })
16
+
17
+ export const FlaggedFile = builder.simpleObject("FlaggedFile", {
18
+ description: "An annexed file that has been flagged for removal.",
19
+ fields: (t) => ({
20
+ datasetId: t.string(),
21
+ snapshot: t.string(),
22
+ filepath: t.string(),
23
+ annexKey: t.string(),
24
+ removed: t.boolean(),
25
+ remover: t.field({ type: UserRef }),
26
+ flagged: t.boolean(),
27
+ flagger: t.field({ type: UserRef }),
28
+ createdAt: t.field({ type: "DateTime" }),
29
+ }),
30
+ })
31
+
32
+ export const AnnexFsck = builder.simpleObject("AnnexFsck", {
33
+ fields: (t) => ({
34
+ command: t.string(),
35
+ errorMessages: t.stringList({ nullable: { list: true, items: true } }),
36
+ file: t.string(),
37
+ key: t.string(),
38
+ note: t.string(),
39
+ success: t.boolean(),
40
+ }),
41
+ })
42
+
43
+ export const FileCheck = builder.simpleObject("FileCheck", {
44
+ fields: (t) => ({
45
+ datasetId: t.string({ nullable: false }),
46
+ hexsha: t.string({ nullable: false }),
47
+ refs: t.stringList({ nullable: { list: false, items: false } }),
48
+ annexFsck: t.field({
49
+ type: [AnnexFsck],
50
+ nullable: { list: true, items: false },
51
+ }),
52
+ remote: t.string(),
53
+ }),
54
+ })
55
+
56
+ export const UserNotificationStatus = builder.simpleObject(
57
+ "UserNotificationStatus",
58
+ {
59
+ description: "User's notification status",
60
+ fields: (t) => ({
61
+ status: t.field({
62
+ type: NotificationStatusType,
63
+ nullable: false,
64
+ }),
65
+ }),
66
+ },
67
+ )
68
+
69
+ export const DiffFiles = builder.simpleObject("DiffFiles", {
70
+ fields: (t) => ({
71
+ status: t.string(),
72
+ mode: t.int(),
73
+ old: t.string(),
74
+ new: t.string(),
75
+ binary: t.boolean(),
76
+ }),
77
+ })
78
+
79
+ export const DatasetCommit = builder.simpleObject("DatasetCommit", {
80
+ fields: (t) => ({
81
+ id: t.id({ nullable: false }),
82
+ date: t.field({ type: "DateTime" }),
83
+ authorName: t.string(),
84
+ authorEmail: t.string(),
85
+ message: t.string(),
86
+ references: t.string(),
87
+ }),
88
+ })
89
+
90
+ export const Follower = builder.simpleObject("Follower", {
91
+ description: "Dataset Followers",
92
+ fields: (t) => ({
93
+ userId: t.string(),
94
+ datasetId: t.string(),
95
+ }),
96
+ })
97
+
98
+ export const FollowDatasetResponse = builder.simpleObject(
99
+ "FollowDatasetResponse",
100
+ {
101
+ fields: (t) => ({
102
+ following: t.boolean(),
103
+ newFollower: t.field({ type: Follower }),
104
+ }),
105
+ },
106
+ )
107
+
108
+ export const Star = builder.simpleObject("Star", {
109
+ description: "Dataset Stars",
110
+ directives: { cacheControl: { maxAge: 300 } },
111
+ fields: (t) => ({
112
+ userId: t.string(),
113
+ datasetId: t.string(),
114
+ }),
115
+ })
116
+
117
+ export const StarDatasetResponse = builder.simpleObject(
118
+ "StarDatasetResponse",
119
+ {
120
+ fields: (t) => ({
121
+ starred: t.boolean(),
122
+ newStar: t.field({ type: Star }),
123
+ }),
124
+ },
125
+ )
126
+
127
+ export const RelatedObject = builder.simpleObject("RelatedObject", {
128
+ description: "DOI for an external object",
129
+ fields: (t) => ({
130
+ id: t.id({ nullable: false }),
131
+ relation: t.field({ type: RelatedObjectRelation, nullable: false }),
132
+ kind: t.field({ type: RelatedObjectKind, nullable: false }),
133
+ description: t.string(),
134
+ }),
135
+ })
136
+
137
+ export const DeprecatedSnapshot = builder.simpleObject("DeprecatedSnapshot", {
138
+ description: "Set on snapshots that have been deprecated",
139
+ fields: (t) => ({
140
+ id: t.id({ nullable: false }),
141
+ user: t.string(),
142
+ reason: t.string(),
143
+ timestamp: t.field({ type: "Date" }),
144
+ }),
145
+ })
146
+
147
+ export const DatasetDerivatives = builder.simpleObject("DatasetDerivatives", {
148
+ fields: (t) => ({
149
+ name: t.string(),
150
+ local: t.boolean(),
151
+ s3Url: t.string(),
152
+ dataladUrl: t.string(),
153
+ }),
154
+ })