carddb 0.2.2 → 0.3.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.
@@ -3,11 +3,12 @@
3
3
  module CardDB
4
4
  module Resources
5
5
  # Decks resource for hosted decks and external deck hydration.
6
+ # rubocop:disable Metrics/ClassLength
6
7
  class Decks < Base
7
8
  # List decks owned by the current account or API application.
8
- def list_mine(first: nil, after: nil, cache: nil)
9
- query = QueryBuilder.list_my_decks(first: first, after: after)
10
- variables = build_variables(first: first, after: after)
9
+ def list_mine(first: nil, after: nil, include_archived: nil, cache: nil)
10
+ query = QueryBuilder.list_my_decks(first: first, after: after, include_archived: include_archived)
11
+ variables = build_variables(first: first, after: after, includeArchived: include_archived)
11
12
  key = cache_key('decks', 'list_mine', **variables)
12
13
 
13
14
  data = with_cache(key, resource: :decks, cache: cache) do
@@ -17,7 +18,65 @@ module CardDB
17
18
  Collection.new(
18
19
  data['myDecks'],
19
20
  item_class: Deck,
20
- next_page_loader: ->(cursor) { list_mine(first: first, after: cursor, cache: cache) },
21
+ next_page_loader: lambda { |cursor|
22
+ list_mine(first: first, after: cursor, include_archived: include_archived, cache: cache)
23
+ },
24
+ client: client
25
+ )
26
+ end
27
+
28
+ # List decks owned by the current account or OAuth grant.
29
+ def list_viewer(filter: nil, first: nil, after: nil, cache: nil)
30
+ query = QueryBuilder.viewer_decks(filter: filter, first: first, after: after)
31
+ variables = build_variables(filter: filter, first: first, after: after)
32
+ key = cache_key('decks', 'list_viewer', **variables)
33
+
34
+ data = with_cache(key, resource: :decks, cache: cache) do
35
+ connection.execute(query, variables)
36
+ end
37
+
38
+ Collection.new(
39
+ data['viewerDecks'],
40
+ item_class: Deck,
41
+ next_page_loader: ->(cursor) { list_viewer(filter: filter, first: first, after: cursor, cache: cache) },
42
+ client: client
43
+ )
44
+ end
45
+
46
+ # List app-owned decks for the current secret-key API application.
47
+ def list_app(filter: nil, first: nil, after: nil, cache: nil)
48
+ config.require_secret_credential!('decks.list_app')
49
+
50
+ query = QueryBuilder.app_decks(filter: filter, first: first, after: after)
51
+ variables = build_variables(filter: filter, first: first, after: after)
52
+ key = cache_key('decks', 'list_app', **variables)
53
+
54
+ data = with_cache(key, resource: :decks, cache: cache) do
55
+ connection.execute(query, variables)
56
+ end
57
+
58
+ Collection.new(
59
+ data['appDecks'],
60
+ item_class: Deck,
61
+ next_page_loader: ->(cursor) { list_app(filter: filter, first: first, after: cursor, cache: cache) },
62
+ client: client
63
+ )
64
+ end
65
+
66
+ # List published live decks eligible for public discovery.
67
+ def list_public(filter: nil, first: nil, after: nil, cache: nil)
68
+ query = QueryBuilder.public_decks(filter: filter, first: first, after: after)
69
+ variables = build_variables(filter: filter, first: first, after: after)
70
+ key = cache_key('decks', 'list_public', **variables)
71
+
72
+ data = with_cache(key, resource: :decks, cache: cache) do
73
+ connection.execute(query, variables)
74
+ end
75
+
76
+ Collection.new(
77
+ data['publicDecks'],
78
+ item_class: Deck,
79
+ next_page_loader: ->(cursor) { list_public(filter: filter, first: first, after: cursor, cache: cache) },
21
80
  client: client
22
81
  )
23
82
  end
@@ -31,6 +90,15 @@ module CardDB
31
90
  end
32
91
  end
33
92
 
93
+ # Fetch by UUID using the ownership-aware deck API.
94
+ def get(id, cache: nil)
95
+ key = cache_key('decks', 'get', id: id)
96
+ with_cache(key, resource: :decks, cache: cache) do
97
+ data = connection.execute(QueryBuilder.deck, { id: id })
98
+ data['deck'] ? Deck.new(data['deck'], client: client) : nil
99
+ end
100
+ end
101
+
34
102
  # Fetch one deck owned by the current account or API application.
35
103
  def fetch_mine(id, cache: nil)
36
104
  key = cache_key('decks', 'fetch_mine', id: id)
@@ -56,6 +124,22 @@ module CardDB
56
124
  end
57
125
  end
58
126
 
127
+ # Fetch by slug using the ownership-aware deckBySlug API.
128
+ def get_by_slug(slug:, publisher_slug: nil, game_key: nil, cache: nil)
129
+ resolved_publisher = resolve_publisher(publisher_slug)
130
+ resolved_game = resolve_game(game_key)
131
+ validate_access!(resolved_publisher, resolved_game)
132
+
133
+ key = cache_key('decks', 'get_by_slug', publisher_slug: resolved_publisher, game_key: resolved_game, slug: slug)
134
+ with_cache(key, resource: :decks, cache: cache) do
135
+ data = connection.execute(
136
+ QueryBuilder.deck_by_slug,
137
+ { publisherSlug: resolved_publisher, gameKey: resolved_game, slug: slug }
138
+ )
139
+ data['deckBySlug'] ? Deck.new(data['deckBySlug'], client: client) : nil
140
+ end
141
+ end
142
+
59
143
  # Fetch a hosted deck by external reference for the current API application.
60
144
  def fetch_by_external_ref(external_ref:, cache: nil)
61
145
  key = cache_key('decks', 'fetch_by_external_ref', external_ref: external_ref)
@@ -65,6 +149,15 @@ module CardDB
65
149
  end
66
150
  end
67
151
 
152
+ # Fetch by external reference using the ownership-aware deckByExternalRef API.
153
+ def get_by_external_ref(external_ref:, cache: nil)
154
+ key = cache_key('decks', 'get_by_external_ref', external_ref: external_ref)
155
+ with_cache(key, resource: :decks, cache: cache) do
156
+ data = connection.execute(QueryBuilder.deck_by_external_ref, { externalRef: external_ref })
157
+ data['deckByExternalRef'] ? Deck.new(data['deckByExternalRef'], client: client) : nil
158
+ end
159
+ end
160
+
68
161
  # Fetch one immutable published deck version.
69
162
  def fetch_version(id, cache: nil)
70
163
  key = cache_key('decks', 'fetch_version', id: id)
@@ -101,6 +194,96 @@ module CardDB
101
194
  end
102
195
  end
103
196
 
197
+ # Fetch published embed data using a revocable embed token.
198
+ def embed(token:, cache: nil)
199
+ key = cache_key('decks', 'embed', token: token)
200
+ with_cache(key, resource: :decks, cache: cache) do
201
+ data = connection.execute(QueryBuilder.deck_embed, { token: token })
202
+ data['deckEmbed'] ? Deck.new(data['deckEmbed'], client: client) : nil
203
+ end
204
+ end
205
+
206
+ # Fetch token-authorized published data using an exchanged access token.
207
+ def access(token:, cache: nil)
208
+ key = cache_key('decks', 'access', token: token)
209
+ with_cache(key, resource: :decks, cache: cache) do
210
+ data = connection.execute(QueryBuilder.deck_access, { token: token })
211
+ data['deckAccess'] ? Deck.new(data['deckAccess'], client: client) : nil
212
+ end
213
+ end
214
+
215
+ def draft_diff(id:, cache: nil)
216
+ key = cache_key('decks', 'draft_diff', id: id)
217
+ with_cache(key, resource: :decks, cache: cache) do
218
+ data = connection.execute(QueryBuilder.deck_draft_diff, { id: id })
219
+ DeckDiff.new(data['deckDraftDiff'], client: client)
220
+ end
221
+ end
222
+
223
+ def version_diff(from_version_id:, to_version_id:, cache: nil)
224
+ variables = { fromVersionId: from_version_id, toVersionId: to_version_id }
225
+ key = cache_key('decks', 'version_diff', **variables)
226
+ with_cache(key, resource: :decks, cache: cache) do
227
+ data = connection.execute(QueryBuilder.deck_version_diff, variables)
228
+ DeckDiff.new(data['deckVersionDiff'], client: client)
229
+ end
230
+ end
231
+
232
+ def validate(id:, input: nil, cache: nil)
233
+ variables = build_variables(id: id, input: input)
234
+ key = cache_key('decks', 'validate', **variables)
235
+ with_cache(key, resource: :decks, cache: cache) do
236
+ data = connection.execute(QueryBuilder.deck_validate, variables)
237
+ DeckValidation.new(data['deckValidate'], client: client)
238
+ end
239
+ end
240
+
241
+ def hydrate_deck_entries(input:, cache: nil)
242
+ key = cache_key('decks', 'hydrate_deck_entries', input: input)
243
+ with_cache(key, resource: :decks, cache: cache) do
244
+ data = connection.execute(QueryBuilder.deck_hydrate_entries, { input: input })
245
+ DeckHydrateEntriesPayload.new(data['deckHydrateEntries'], client: client)
246
+ end
247
+ end
248
+
249
+ def export_deck(id:, format: 'SIMPLE_TEXT', cache: nil)
250
+ variables = { id: id, format: format }
251
+ key = cache_key('decks', 'export_deck', **variables)
252
+ with_cache(key, resource: :decks, cache: cache) do
253
+ data = connection.execute(QueryBuilder.deck_export, variables)
254
+ DeckExportPayload.new(data['deckExport'], client: client)
255
+ end
256
+ end
257
+
258
+ def section_definitions(
259
+ publisher_slug: nil,
260
+ game_key: nil,
261
+ game_id: nil,
262
+ ruleset_key: nil,
263
+ ruleset_version_id: nil,
264
+ cache: nil
265
+ )
266
+ query = QueryBuilder.deck_section_definitions(
267
+ publisher_slug: publisher_slug,
268
+ game_key: game_key,
269
+ game_id: game_id,
270
+ ruleset_key: ruleset_key,
271
+ ruleset_version_id: ruleset_version_id
272
+ )
273
+ variables = build_variables(
274
+ publisherSlug: publisher_slug,
275
+ gameKey: game_key,
276
+ gameId: game_id,
277
+ rulesetKey: ruleset_key,
278
+ rulesetVersionId: ruleset_version_id
279
+ )
280
+ key = cache_key('decks', 'section_definitions', **variables)
281
+ with_cache(key, resource: :decks, cache: cache) do
282
+ data = connection.execute(query, variables)
283
+ (data['deckSectionDefinitions'] || []).map { |definition| DeckSectionDefinition.new(definition, client: client) }
284
+ end
285
+ end
286
+
104
287
  # List collaborators for a deck.
105
288
  def collaborators(deck_id:, cache: nil)
106
289
  key = cache_key('decks', 'collaborators', deck_id: deck_id)
@@ -119,6 +302,44 @@ module CardDB
119
302
  end
120
303
  end
121
304
 
305
+ def embed_tokens(deck_id:, cache: nil)
306
+ key = cache_key('decks', 'embed_tokens', deck_id: deck_id)
307
+ with_cache(key, resource: :decks, cache: cache) do
308
+ data = connection.execute(QueryBuilder.deck_embed_tokens, { deckId: deck_id })
309
+ (data['deckEmbedTokens'] || []).map { |token| DeckEmbedToken.new(token, client: client) }
310
+ end
311
+ end
312
+
313
+ def access_token_issuers(deck_id:, cache: nil)
314
+ key = cache_key('decks', 'access_token_issuers', deck_id: deck_id)
315
+ with_cache(key, resource: :decks, cache: cache) do
316
+ data = connection.execute(QueryBuilder.deck_access_token_issuers, { deckId: deck_id })
317
+ (data['deckAccessTokenIssuers'] || []).map { |issuer| DeckAccessTokenIssuer.new(issuer, client: client) }
318
+ end
319
+ end
320
+
321
+ def api_application_accesses(deck_id:, include_revoked: nil, cache: nil)
322
+ variables = build_variables(deckId: deck_id, includeRevoked: include_revoked)
323
+ key = cache_key('decks', 'api_application_accesses', **variables)
324
+ with_cache(key, resource: :decks, cache: cache) do
325
+ data = connection.execute(QueryBuilder.deck_api_application_accesses, variables)
326
+ (data['deckApiApplicationAccesses'] || []).map do |access|
327
+ DeckAPIApplicationAccess.new(access, client: client)
328
+ end
329
+ end
330
+ end
331
+
332
+ def my_api_application_accesses(application_id: nil, cache: nil)
333
+ variables = build_variables(applicationId: application_id)
334
+ key = cache_key('decks', 'my_api_application_accesses', **variables)
335
+ with_cache(key, resource: :decks, cache: cache) do
336
+ data = connection.execute(QueryBuilder.my_deck_api_application_accesses, variables)
337
+ (data['myDeckApiApplicationAccesses'] || []).map do |access|
338
+ DeckAPIApplicationAccess.new(access, client: client)
339
+ end
340
+ end
341
+ end
342
+
122
343
  # Create a hosted deck.
123
344
  def create(input:)
124
345
  data = connection.execute(QueryBuilder.create_deck, { input: input })
@@ -131,10 +352,154 @@ module CardDB
131
352
  Deck.new(data['deckUpdate'], client: client)
132
353
  end
133
354
 
355
+ # Update deck-level metadata without mutating entries.
356
+ def update_metadata(id:, input:)
357
+ update(id: id, input: input)
358
+ end
359
+
360
+ def upsert_by_external_ref(input:)
361
+ config.require_secret_credential!('decks.upsert_by_external_ref')
362
+
363
+ data = connection.execute(QueryBuilder.upsert_deck_by_external_ref, { input: input })
364
+ DeckUpsertByExternalRefPayload.new(data['deckUpsertByExternalRef'], client: client)
365
+ end
366
+
367
+ def claim(id:, input:)
368
+ data = connection.execute(QueryBuilder.claim_deck, { id: id, input: input })
369
+ DeckOwnershipTransferPayload.new(data['deckClaim'], client: client)
370
+ end
371
+
372
+ def transfer_ownership(id:, input:)
373
+ data = connection.execute(QueryBuilder.transfer_deck_ownership, { id: id, input: input })
374
+ DeckOwnershipTransferPayload.new(data['deckTransferOwnership'], client: client)
375
+ end
376
+
377
+ def copy(id:, input:)
378
+ data = connection.execute(QueryBuilder.copy_deck, { id: id, input: input })
379
+ DeckCopyPayload.new(data['deckCopy'], client: client)
380
+ end
381
+
382
+ def add_entry(input:)
383
+ data = connection.execute(QueryBuilder.add_deck_entry, { input: input })
384
+ DeckEntryMutationPayload.new(data['deckEntryAdd'], client: client)
385
+ end
386
+
387
+ def update_entry(id:, input:)
388
+ data = connection.execute(QueryBuilder.update_deck_entry, { id: id, input: input })
389
+ DeckEntryMutationPayload.new(data['deckEntryUpdate'], client: client)
390
+ end
391
+
392
+ def remove_entry(id:, expected_draft_revision:)
393
+ data = connection.execute(
394
+ QueryBuilder.remove_deck_entry,
395
+ { id: id, expectedDraftRevision: expected_draft_revision }
396
+ )
397
+ DeckEntryMutationPayload.new(data['deckEntryRemove'], client: client)
398
+ end
399
+
400
+ def reorder_entries(deck_id:, input:)
401
+ data = connection.execute(QueryBuilder.reorder_deck_entries, { deckId: deck_id, input: input })
402
+ DeckEntryReorderPayload.new(data['deckEntryReorder'], client: client)
403
+ end
404
+
405
+ def replace_entries(deck_id:, input:)
406
+ data = connection.execute(QueryBuilder.replace_deck_entries, { deckId: deck_id, input: input })
407
+ DeckEntriesReplacePayload.new(data['deckEntriesReplace'], client: client)
408
+ end
409
+
410
+ # Import a decklist into an existing deck or dry-run resolution.
411
+ def import_deck(input:)
412
+ data = connection.execute(QueryBuilder.import_deck, { input: input })
413
+ DeckImportPayload.new(data['deckImport'], client: client)
414
+ end
415
+
416
+ def import_formats(game_id:, include_archived: nil, first: nil, after: nil, cache: nil)
417
+ query = QueryBuilder.deck_import_formats(
418
+ game_id: game_id,
419
+ include_archived: include_archived,
420
+ first: first,
421
+ after: after
422
+ )
423
+ variables = build_variables(gameId: game_id, includeArchived: include_archived, first: first, after: after)
424
+ key = cache_key('decks', 'import_formats', **variables)
425
+
426
+ data = with_cache(key, resource: :decks, cache: cache) do
427
+ connection.execute(query, variables)
428
+ end
429
+
430
+ Collection.new(
431
+ data['deckImportFormats'],
432
+ item_class: DeckImportFormatDefinition,
433
+ next_page_loader: lambda { |cursor|
434
+ import_formats(
435
+ game_id: game_id,
436
+ include_archived: include_archived,
437
+ first: first,
438
+ after: cursor,
439
+ cache: cache
440
+ )
441
+ },
442
+ client: client
443
+ )
444
+ end
445
+
446
+ def fetch_import_format(id, cache: nil)
447
+ key = cache_key('decks', 'fetch_import_format', id: id)
448
+ with_cache(key, resource: :decks, cache: cache) do
449
+ data = connection.execute(QueryBuilder.deck_import_format, { id: id })
450
+ data['deckImportFormat'] ? DeckImportFormatDefinition.new(data['deckImportFormat'], client: client) : nil
451
+ end
452
+ end
453
+
454
+ def test_import_format(input:)
455
+ data = connection.execute(QueryBuilder.deck_import_format_test, { input: input })
456
+ DeckImportFormatTestPayload.new(data['deckImportFormatTest'], client: client)
457
+ end
458
+
459
+ def create_import_format(input:)
460
+ data = connection.execute(QueryBuilder.create_deck_import_format, { input: input })
461
+ DeckImportFormatDefinition.new(data['deckImportFormatCreate'], client: client)
462
+ end
463
+
464
+ def update_import_format(id:, input:)
465
+ data = connection.execute(QueryBuilder.update_deck_import_format, { id: id, input: input })
466
+ DeckImportFormatDefinition.new(data['deckImportFormatUpdate'], client: client)
467
+ end
468
+
469
+ def archive_import_format(id:)
470
+ data = connection.execute(QueryBuilder.archive_deck_import_format, { id: id })
471
+ DeckImportFormatDefinition.new(data['deckImportFormatArchive'], client: client)
472
+ end
473
+
474
+ def unarchive_import_format(id:)
475
+ data = connection.execute(QueryBuilder.unarchive_deck_import_format, { id: id })
476
+ DeckImportFormatDefinition.new(data['deckImportFormatUnarchive'], client: client)
477
+ end
478
+
134
479
  # Publish the current draft as an immutable deck version.
135
- def publish(id:, input: {})
480
+ def publish(id:, input:)
136
481
  data = connection.execute(QueryBuilder.publish_deck, { id: id, input: input })
137
- DeckVersion.new(data['deckPublish'], client: client)
482
+ DeckPublishPayload.new(data['deckPublish'], client: client)
483
+ end
484
+
485
+ def remove_invalid_entries(id:, input:)
486
+ data = connection.execute(QueryBuilder.remove_invalid_deck_entries, { id: id, input: input })
487
+ Deck.new(data['deckRemoveInvalidEntries'], client: client)
488
+ end
489
+
490
+ def archive(id:)
491
+ data = connection.execute(QueryBuilder.archive_deck, { id: id })
492
+ Deck.new(data['deckArchive'], client: client)
493
+ end
494
+
495
+ def restore(id:)
496
+ data = connection.execute(QueryBuilder.restore_deck, { id: id })
497
+ Deck.new(data['deckRestore'], client: client)
498
+ end
499
+
500
+ def unpublish(id:)
501
+ data = connection.execute(QueryBuilder.unpublish_deck, { id: id })
502
+ Deck.new(data['deckUnpublish'], client: client)
138
503
  end
139
504
 
140
505
  # Create or update a deck collaborator.
@@ -171,6 +536,66 @@ module CardDB
171
536
  end
172
537
  # rubocop:enable Naming/PredicateMethod
173
538
 
539
+ def create_embed_token(input:)
540
+ data = connection.execute(QueryBuilder.create_deck_embed_token, { input: input })
541
+ DeckEmbedTokenCreatePayload.new(data['deckEmbedTokenCreate'], client: client)
542
+ end
543
+
544
+ # rubocop:disable Naming/PredicateMethod
545
+ def revoke_embed_token(id:)
546
+ data = connection.execute(QueryBuilder.revoke_deck_embed_token, { id: id })
547
+ !!data['deckEmbedTokenRevoke']
548
+ end
549
+ # rubocop:enable Naming/PredicateMethod
550
+
551
+ def create_access_token_issuer(input:)
552
+ data = connection.execute(QueryBuilder.create_deck_access_token_issuer, { input: input })
553
+ DeckAccessTokenIssuer.new(data['deckAccessTokenIssuerCreate'], client: client)
554
+ end
555
+
556
+ # rubocop:disable Naming/PredicateMethod
557
+ def revoke_access_token_issuer(id:)
558
+ data = connection.execute(QueryBuilder.revoke_deck_access_token_issuer, { id: id })
559
+ !!data['deckAccessTokenIssuerRevoke']
560
+ end
561
+ # rubocop:enable Naming/PredicateMethod
562
+
563
+ def revoke_access_token_issuer_signing_key(id:)
564
+ data = connection.execute(QueryBuilder.revoke_deck_access_token_issuer_signing_key, { id: id })
565
+ DeckAccessTokenIssuer.new(data['deckAccessTokenIssuerSigningKeyRevoke'], client: client)
566
+ end
567
+
568
+ def grant_api_application_access(input:)
569
+ data = connection.execute(QueryBuilder.grant_deck_api_application_access, { input: input })
570
+ DeckAPIApplicationAccess.new(data['deckApiApplicationAccessGrant'], client: client)
571
+ end
572
+
573
+ # rubocop:disable Naming/PredicateMethod
574
+ def revoke_api_application_access(deck_id:, api_application_id:)
575
+ data = connection.execute(
576
+ QueryBuilder.revoke_deck_api_application_access,
577
+ { deckId: deck_id, apiApplicationId: api_application_id }
578
+ )
579
+ !!data['deckApiApplicationAccessRevoke']
580
+ end
581
+ # rubocop:enable Naming/PredicateMethod
582
+
583
+ def exchange_access_token(input:)
584
+ config.require_secret_credential!('decks.exchange_access_token')
585
+
586
+ data = connection.execute(QueryBuilder.exchange_deck_access_token, { input: input })
587
+ DeckAccessTokenExchangePayload.new(data['deckAccessTokenExchange'], client: client)
588
+ end
589
+
590
+ # rubocop:disable Naming/PredicateMethod
591
+ def revoke_access_token(id:)
592
+ config.require_secret_credential!('decks.revoke_access_token')
593
+
594
+ data = connection.execute(QueryBuilder.revoke_deck_access_token, { id: id })
595
+ !!data['deckAccessTokenRevoke']
596
+ end
597
+ # rubocop:enable Naming/PredicateMethod
598
+
174
599
  # Delete a hosted deck.
175
600
  # rubocop:disable Naming/PredicateMethod
176
601
  def delete(id:)
@@ -240,5 +665,6 @@ module CardDB
240
665
  record.record_data&.values&.find { |value| remaining[value.to_s] }
241
666
  end
242
667
  end
668
+ # rubocop:enable Metrics/ClassLength
243
669
  end
244
670
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CardDB
4
- VERSION = '0.2.2'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carddb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - CardDB Team