carddb 0.2.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.
@@ -0,0 +1,658 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CardDB
4
+ # Builds GraphQL queries for the CardDB API.
5
+ # rubocop:disable Metrics/ModuleLength
6
+ module QueryBuilder
7
+ # rubocop:disable Metrics/ClassLength
8
+ class << self
9
+ # Builds a searchPublishers query
10
+ def search_publishers(search: nil, first: nil, after: nil)
11
+ args = build_args({
12
+ search: search,
13
+ first: first,
14
+ after: after
15
+ })
16
+
17
+ <<~GRAPHQL
18
+ query SearchPublishers#{args[:definition]} {
19
+ searchPublishers#{args[:call]} {
20
+ #{publisher_connection_fields}
21
+ }
22
+ }
23
+ GRAPHQL
24
+ end
25
+
26
+ # Builds a fetchPublisher query (by id or slug)
27
+ def fetch_publisher_by_id
28
+ <<~GRAPHQL
29
+ query FetchPublisher($id: UUID!) {
30
+ fetchPublisher(id: $id) {
31
+ #{publisher_fields}
32
+ }
33
+ }
34
+ GRAPHQL
35
+ end
36
+
37
+ # Builds a fetchPublisher query by slug
38
+ def fetch_publisher_by_slug
39
+ <<~GRAPHQL
40
+ query FetchPublisher($slug: String!) {
41
+ fetchPublisher(slug: $slug) {
42
+ #{publisher_fields}
43
+ }
44
+ }
45
+ GRAPHQL
46
+ end
47
+
48
+ # Builds a fetchPublishers query
49
+ def fetch_publishers
50
+ <<~GRAPHQL
51
+ query FetchPublishers($slugs: [String!]!) {
52
+ fetchPublishers(slugs: $slugs) {
53
+ #{publisher_fields}
54
+ }
55
+ }
56
+ GRAPHQL
57
+ end
58
+
59
+ # Builds a searchGames query
60
+ def search_games(publisher_slug: nil, search: nil, first: nil, after: nil)
61
+ args = build_args({
62
+ publisherSlug: publisher_slug,
63
+ search: search,
64
+ first: first,
65
+ after: after
66
+ })
67
+
68
+ <<~GRAPHQL
69
+ query SearchGames#{args[:definition]} {
70
+ searchGames#{args[:call]} {
71
+ #{game_connection_fields}
72
+ }
73
+ }
74
+ GRAPHQL
75
+ end
76
+
77
+ # Builds a fetchGame query by id
78
+ def fetch_game_by_id
79
+ <<~GRAPHQL
80
+ query FetchGame($id: UUID!) {
81
+ fetchGame(id: $id) {
82
+ #{game_fields}
83
+ }
84
+ }
85
+ GRAPHQL
86
+ end
87
+
88
+ # Builds a fetchGame query by publisher slug and game key
89
+ def fetch_game_by_keys
90
+ <<~GRAPHQL
91
+ query FetchGame($publisherSlug: String!, $gameKey: String!) {
92
+ fetchGame(publisherSlug: $publisherSlug, gameKey: $gameKey) {
93
+ #{game_fields}
94
+ }
95
+ }
96
+ GRAPHQL
97
+ end
98
+
99
+ # Builds a fetchGames batch query
100
+ def fetch_games
101
+ <<~GRAPHQL
102
+ query FetchGames($ids: [UUID!]!) {
103
+ fetchGames(ids: $ids) {
104
+ #{game_fields}
105
+ }
106
+ }
107
+ GRAPHQL
108
+ end
109
+
110
+ # Builds a searchDatasets query
111
+ def search_datasets(publisher_slug: nil, game_key: nil, search: nil, purpose: nil, first: nil, after: nil)
112
+ args = build_args({
113
+ publisherSlug: publisher_slug,
114
+ gameKey: game_key,
115
+ search: search,
116
+ purpose: purpose,
117
+ first: first,
118
+ after: after
119
+ })
120
+
121
+ <<~GRAPHQL
122
+ query SearchDatasets#{args[:definition]} {
123
+ searchDatasets#{args[:call]} {
124
+ #{dataset_connection_fields}
125
+ }
126
+ }
127
+ GRAPHQL
128
+ end
129
+
130
+ # Builds a fetchDataset query by id
131
+ def fetch_dataset_by_id
132
+ <<~GRAPHQL
133
+ query FetchDataset($id: UUID!) {
134
+ fetchDataset(id: $id) {
135
+ #{dataset_fields}
136
+ #{schema_fields}
137
+ }
138
+ }
139
+ GRAPHQL
140
+ end
141
+
142
+ # Builds a fetchDataset query by keys (includes schema)
143
+ def fetch_dataset_by_keys
144
+ <<~GRAPHQL
145
+ query FetchDataset($publisherSlug: String!, $gameKey: String!, $datasetKey: String!) {
146
+ fetchDataset(publisherSlug: $publisherSlug, gameKey: $gameKey, datasetKey: $datasetKey) {
147
+ #{dataset_fields}
148
+ #{schema_fields}
149
+ }
150
+ }
151
+ GRAPHQL
152
+ end
153
+
154
+ # Builds a fetchDatasets batch query
155
+ def fetch_datasets
156
+ <<~GRAPHQL
157
+ query FetchDatasets($ids: [UUID!]!) {
158
+ fetchDatasets(ids: $ids) {
159
+ #{dataset_fields}
160
+ }
161
+ }
162
+ GRAPHQL
163
+ end
164
+
165
+ # Builds a searchRecords query
166
+ def search_records(
167
+ publisher_slug:,
168
+ game_key:,
169
+ dataset_key:,
170
+ filter: nil,
171
+ search: nil,
172
+ order_by: nil,
173
+ resolve_links: nil,
174
+ first: nil,
175
+ after: nil,
176
+ validate_schema: nil
177
+ )
178
+ args = build_args(
179
+ {
180
+ publisherSlug: publisher_slug,
181
+ gameKey: game_key,
182
+ datasetKey: dataset_key,
183
+ filter: filter,
184
+ search: search,
185
+ orderBy: order_by,
186
+ resolveLinks: resolve_links,
187
+ first: first,
188
+ after: after,
189
+ validateSchema: validate_schema
190
+ },
191
+ required: %i[publisherSlug gameKey datasetKey]
192
+ )
193
+
194
+ <<~GRAPHQL
195
+ query SearchRecords#{args[:definition]} {
196
+ searchRecords#{args[:call]} {
197
+ #{record_connection_fields(include_resolved_links: resolve_links&.any?)}
198
+ }
199
+ }
200
+ GRAPHQL
201
+ end
202
+
203
+ # Builds a fetchRecordByIdentifier query
204
+ def fetch_record_by_identifier
205
+ <<~GRAPHQL
206
+ query FetchRecordByIdentifier($publisherSlug: String!, $gameKey: String!, $datasetKey: String!, $identifier: String!) {
207
+ fetchRecordByIdentifier(publisherSlug: $publisherSlug, gameKey: $gameKey, datasetKey: $datasetKey, identifier: $identifier) {
208
+ #{record_fields}
209
+ }
210
+ }
211
+ GRAPHQL
212
+ end
213
+
214
+ # Builds a fetchRecordsByIdentifier query
215
+ def fetch_records_by_identifier
216
+ <<~GRAPHQL
217
+ query FetchRecordsByIdentifier($publisherSlug: String!, $gameKey: String!, $datasetKey: String!, $identifiers: [String!]!) {
218
+ fetchRecordsByIdentifier(publisherSlug: $publisherSlug, gameKey: $gameKey, datasetKey: $datasetKey, identifiers: $identifiers) {
219
+ #{record_fields}
220
+ }
221
+ }
222
+ GRAPHQL
223
+ end
224
+
225
+ # Builds a fetchRecord query
226
+ def fetch_record
227
+ <<~GRAPHQL
228
+ query FetchRecord($id: UUID!) {
229
+ fetchRecord(id: $id) {
230
+ #{record_fields}
231
+ }
232
+ }
233
+ GRAPHQL
234
+ end
235
+
236
+ # Builds a fetchRecords query
237
+ def fetch_records
238
+ <<~GRAPHQL
239
+ query FetchRecords($ids: [UUID!]!) {
240
+ fetchRecords(ids: $ids) {
241
+ #{record_fields}
242
+ }
243
+ }
244
+ GRAPHQL
245
+ end
246
+
247
+ # Builds a myDecks query
248
+ def list_my_decks(first: nil, after: nil)
249
+ args = build_args({ first: first, after: after })
250
+
251
+ <<~GRAPHQL
252
+ query MyDecks#{args[:definition]} {
253
+ myDecks#{args[:call]} {
254
+ #{deck_connection_fields}
255
+ }
256
+ }
257
+ GRAPHQL
258
+ end
259
+
260
+ # Builds a fetchDeck query
261
+ def fetch_deck
262
+ <<~GRAPHQL
263
+ query FetchDeck($id: UUID!) {
264
+ fetchDeck(id: $id) {
265
+ #{deck_fields}
266
+ }
267
+ }
268
+ GRAPHQL
269
+ end
270
+
271
+ # Builds a fetchDeckByExternalRef query
272
+ def fetch_deck_by_external_ref
273
+ <<~GRAPHQL
274
+ query FetchDeckByExternalRef($externalRef: String!) {
275
+ fetchDeckByExternalRef(externalRef: $externalRef) {
276
+ #{deck_fields}
277
+ }
278
+ }
279
+ GRAPHQL
280
+ end
281
+
282
+ # Builds a deckCreate mutation
283
+ def create_deck
284
+ <<~GRAPHQL
285
+ mutation DeckCreate($input: DeckCreateInput!) {
286
+ deckCreate(input: $input) {
287
+ #{deck_fields}
288
+ }
289
+ }
290
+ GRAPHQL
291
+ end
292
+
293
+ # Builds a deckUpdate mutation
294
+ def update_deck
295
+ <<~GRAPHQL
296
+ mutation DeckUpdate($id: UUID!, $input: DeckUpdateInput!) {
297
+ deckUpdate(id: $id, input: $input) {
298
+ #{deck_fields}
299
+ }
300
+ }
301
+ GRAPHQL
302
+ end
303
+
304
+ # Builds a deckDelete mutation
305
+ def delete_deck
306
+ <<~GRAPHQL
307
+ mutation DeckDelete($id: UUID!) {
308
+ deckDelete(id: $id)
309
+ }
310
+ GRAPHQL
311
+ end
312
+
313
+ # Builds a fetchMe query
314
+ def fetch_me
315
+ <<~GRAPHQL
316
+ query FetchMe {
317
+ fetchMe {
318
+ application {
319
+ id
320
+ name
321
+ description
322
+ environment
323
+ apiKeyPrefix
324
+ allowedOrigins
325
+ allowedIps
326
+ createdAt
327
+ updatedAt
328
+ lastUsedAt
329
+ }
330
+ account {
331
+ id
332
+ displayName
333
+ createdAt
334
+ }
335
+ }
336
+ }
337
+ GRAPHQL
338
+ end
339
+
340
+ private
341
+
342
+ def build_args(params, required: [])
343
+ # Filter out nil values
344
+ params = params.compact
345
+
346
+ return { definition: '', call: '' } if params.empty?
347
+
348
+ # Map Ruby types to GraphQL types (base types, without !)
349
+ type_map = {
350
+ publisherSlug: 'String',
351
+ gameKey: 'String',
352
+ datasetKey: 'String',
353
+ search: 'String',
354
+ orderBy: 'String',
355
+ filter: 'JSON',
356
+ resolveLinks: '[String!]',
357
+ first: 'Int',
358
+ after: 'String',
359
+ externalRef: 'String',
360
+ validateSchema: 'Boolean',
361
+ purpose: 'DatasetPurpose',
362
+ id: 'UUID!',
363
+ ids: '[UUID!]!'
364
+ }
365
+
366
+ definitions = params.keys.map do |k|
367
+ base_type = type_map[k] || 'String'
368
+ # Add ! for required fields (unless already has !)
369
+ type = required.include?(k) && !base_type.end_with?('!') ? "#{base_type}!" : base_type
370
+ "$#{k}: #{type}"
371
+ end
372
+ calls = params.keys.map { |k| "#{k}: $#{k}" }
373
+
374
+ {
375
+ definition: "(#{definitions.join(', ')})",
376
+ call: "(#{calls.join(', ')})"
377
+ }
378
+ end
379
+
380
+ def publisher_fields
381
+ <<~FIELDS
382
+ id
383
+ name
384
+ slug
385
+ status
386
+ description
387
+ website
388
+ createdAt
389
+ updatedAt
390
+ logoFile {
391
+ id
392
+ url
393
+ }
394
+ bannerFile {
395
+ id
396
+ url
397
+ }
398
+ FIELDS
399
+ end
400
+
401
+ def publisher_connection_fields
402
+ <<~FIELDS
403
+ totalCount
404
+ pageInfo {
405
+ hasNextPage
406
+ hasPreviousPage
407
+ startCursor
408
+ endCursor
409
+ }
410
+ edges {
411
+ cursor
412
+ node {
413
+ #{publisher_fields}
414
+ }
415
+ }
416
+ FIELDS
417
+ end
418
+
419
+ def game_fields
420
+ <<~FIELDS
421
+ id
422
+ publisherId
423
+ key
424
+ name
425
+ description
426
+ website
427
+ visibility
428
+ isArchived
429
+ createdAt
430
+ updatedAt
431
+ publisher {
432
+ id
433
+ name
434
+ slug
435
+ }
436
+ logoFile {
437
+ id
438
+ url
439
+ }
440
+ coverFile {
441
+ id
442
+ url
443
+ }
444
+ FIELDS
445
+ end
446
+
447
+ def game_connection_fields
448
+ <<~FIELDS
449
+ totalCount
450
+ pageInfo {
451
+ hasNextPage
452
+ hasPreviousPage
453
+ startCursor
454
+ endCursor
455
+ }
456
+ edges {
457
+ cursor
458
+ node {
459
+ #{game_fields}
460
+ }
461
+ }
462
+ FIELDS
463
+ end
464
+
465
+ def dataset_fields
466
+ <<~FIELDS
467
+ id
468
+ publisherId
469
+ gameId
470
+ key
471
+ name
472
+ description
473
+ purpose
474
+ visibility
475
+ isArchived
476
+ createdAt
477
+ updatedAt
478
+ publisher {
479
+ id
480
+ name
481
+ slug
482
+ }
483
+ game {
484
+ id
485
+ key
486
+ name
487
+ }
488
+ FIELDS
489
+ end
490
+
491
+ def schema_fields
492
+ <<~FIELDS
493
+ schema {
494
+ fields {
495
+ key
496
+ label
497
+ description
498
+ type
499
+ isRequired
500
+ filterable
501
+ searchable
502
+ isIdentifier
503
+ itemType
504
+ displayFormat
505
+ semanticType
506
+ allowedValues
507
+ nestedFields {
508
+ key
509
+ label
510
+ description
511
+ type
512
+ isRequired
513
+ filterable
514
+ searchable
515
+ itemType
516
+ semanticType
517
+ }
518
+ }
519
+ filterableFields
520
+ searchableFields
521
+ linkFields {
522
+ key
523
+ label
524
+ targetDatasetKey
525
+ targetDatasetName
526
+ targetDatasetId
527
+ }
528
+ }
529
+ FIELDS
530
+ end
531
+
532
+ def dataset_connection_fields
533
+ <<~FIELDS
534
+ totalCount
535
+ pageInfo {
536
+ hasNextPage
537
+ hasPreviousPage
538
+ startCursor
539
+ endCursor
540
+ }
541
+ edges {
542
+ cursor
543
+ node {
544
+ #{dataset_fields}
545
+ }
546
+ }
547
+ FIELDS
548
+ end
549
+
550
+ def record_fields
551
+ <<~FIELDS
552
+ id
553
+ datasetId
554
+ data
555
+ createdAt
556
+ updatedAt
557
+ dataset {
558
+ id
559
+ key
560
+ name
561
+ gameId
562
+ publisherId
563
+ }
564
+ FIELDS
565
+ end
566
+
567
+ def record_connection_fields(include_resolved_links: false)
568
+ resolved_links_field = if include_resolved_links
569
+ <<~FIELDS
570
+ resolvedLinks {
571
+ field
572
+ linkFieldKey
573
+ values
574
+ records {
575
+ id
576
+ datasetId
577
+ data
578
+ }
579
+ }
580
+ FIELDS
581
+ else
582
+ ''
583
+ end
584
+
585
+ <<~FIELDS
586
+ totalCount
587
+ pageInfo {
588
+ hasNextPage
589
+ hasPreviousPage
590
+ startCursor
591
+ endCursor
592
+ }
593
+ edges {
594
+ cursor
595
+ node {
596
+ #{record_fields}
597
+ #{resolved_links_field}
598
+ }
599
+ }
600
+ FIELDS
601
+ end
602
+
603
+ def deck_fields
604
+ <<~FIELDS
605
+ id
606
+ accountId
607
+ apiApplicationId
608
+ gameId
609
+ title
610
+ description
611
+ formatKey
612
+ visibility
613
+ externalRef
614
+ sourceUrl
615
+ metadata
616
+ createdAt
617
+ updatedAt
618
+ game {
619
+ #{game_fields}
620
+ }
621
+ entries {
622
+ id
623
+ datasetId
624
+ recordId
625
+ identifier
626
+ quantity
627
+ section
628
+ sortOrder
629
+ annotations
630
+ record {
631
+ #{record_fields}
632
+ }
633
+ }
634
+ FIELDS
635
+ end
636
+
637
+ def deck_connection_fields
638
+ <<~FIELDS
639
+ totalCount
640
+ pageInfo {
641
+ hasNextPage
642
+ hasPreviousPage
643
+ startCursor
644
+ endCursor
645
+ }
646
+ edges {
647
+ cursor
648
+ node {
649
+ #{deck_fields}
650
+ }
651
+ }
652
+ FIELDS
653
+ end
654
+ end
655
+ # rubocop:enable Metrics/ClassLength
656
+ end
657
+ # rubocop:enable Metrics/ModuleLength
658
+ end