carddb 0.4.2 → 0.4.5
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.
- checksums.yaml +4 -4
- data/.rspec_status +142 -139
- data/README.md +15 -21
- data/lib/carddb/batch.rb +40 -6
- data/lib/carddb/collection.rb +9 -109
- data/lib/carddb/deck_tokens.rb +76 -61
- data/lib/carddb/query_builder.rb +31 -189
- data/lib/carddb/resources/decks.rb +94 -115
- data/lib/carddb/version.rb +1 -1
- metadata +1 -1
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
3
5
|
module CardDB
|
|
4
6
|
module Resources
|
|
5
7
|
# Decks resource for hosted decks and external deck hydration.
|
|
6
8
|
# rubocop:disable Metrics/ClassLength
|
|
7
9
|
class Decks < Base
|
|
10
|
+
JSON_OBJECT_INPUT_KEYS = %w[metadata annotations].freeze
|
|
11
|
+
|
|
8
12
|
# List decks owned by the current account or API application.
|
|
9
13
|
def list_mine(first: nil, after: nil, include_archived: nil, cache: nil)
|
|
10
14
|
query = QueryBuilder.list_my_decks(first: first, after: after, include_archived: include_archived)
|
|
@@ -91,14 +95,23 @@ module CardDB
|
|
|
91
95
|
end
|
|
92
96
|
|
|
93
97
|
# Fetch by UUID using the ownership-aware deck API.
|
|
94
|
-
def get(id, cache: nil)
|
|
95
|
-
|
|
98
|
+
def get(id, read_state:, version: nil, cache: nil)
|
|
99
|
+
variables = build_variables(id: id, readState: read_state, version: version)
|
|
100
|
+
key = cache_key('decks', 'get', **variables)
|
|
96
101
|
with_cache(key, resource: :decks, cache: cache) do
|
|
97
|
-
data = connection.execute(QueryBuilder.deck,
|
|
102
|
+
data = connection.execute(QueryBuilder.deck, variables)
|
|
98
103
|
data['deck'] ? Deck.new(data['deck'], client: client) : nil
|
|
99
104
|
end
|
|
100
105
|
end
|
|
101
106
|
|
|
107
|
+
def get_draft(id, cache: nil)
|
|
108
|
+
get(id, read_state: 'DRAFT', cache: cache)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def get_published(id, version: nil, cache: nil)
|
|
112
|
+
get(id, read_state: 'PUBLISHED', version: version, cache: cache)
|
|
113
|
+
end
|
|
114
|
+
|
|
102
115
|
# Fetch one deck owned by the current account or API application.
|
|
103
116
|
def fetch_mine(id, cache: nil)
|
|
104
117
|
key = cache_key('decks', 'fetch_mine', id: id)
|
|
@@ -150,14 +163,23 @@ module CardDB
|
|
|
150
163
|
end
|
|
151
164
|
|
|
152
165
|
# Fetch by external reference using the ownership-aware deckByExternalRef API.
|
|
153
|
-
def get_by_external_ref(external_ref:, cache: nil)
|
|
154
|
-
|
|
166
|
+
def get_by_external_ref(external_ref:, read_state:, version: nil, cache: nil)
|
|
167
|
+
variables = build_variables(externalRef: external_ref, readState: read_state, version: version)
|
|
168
|
+
key = cache_key('decks', 'get_by_external_ref', **variables)
|
|
155
169
|
with_cache(key, resource: :decks, cache: cache) do
|
|
156
|
-
data = connection.execute(QueryBuilder.deck_by_external_ref,
|
|
170
|
+
data = connection.execute(QueryBuilder.deck_by_external_ref, variables)
|
|
157
171
|
data['deckByExternalRef'] ? Deck.new(data['deckByExternalRef'], client: client) : nil
|
|
158
172
|
end
|
|
159
173
|
end
|
|
160
174
|
|
|
175
|
+
def get_draft_by_external_ref(external_ref:, cache: nil)
|
|
176
|
+
get_by_external_ref(external_ref: external_ref, read_state: 'DRAFT', cache: cache)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def get_published_by_external_ref(external_ref:, version: nil, cache: nil)
|
|
180
|
+
get_by_external_ref(external_ref: external_ref, read_state: 'PUBLISHED', version: version, cache: cache)
|
|
181
|
+
end
|
|
182
|
+
|
|
161
183
|
# Fetch one immutable published deck version.
|
|
162
184
|
def fetch_version(id, cache: nil)
|
|
163
185
|
key = cache_key('decks', 'fetch_version', id: id)
|
|
@@ -185,33 +207,6 @@ module CardDB
|
|
|
185
207
|
)
|
|
186
208
|
end
|
|
187
209
|
|
|
188
|
-
# Fetch current draft data using a revocable preview token.
|
|
189
|
-
def preview(token:, cache: nil)
|
|
190
|
-
key = cache_key('decks', 'preview', token: token)
|
|
191
|
-
with_cache(key, resource: :decks, cache: cache) do
|
|
192
|
-
data = connection.execute(QueryBuilder.deck_preview, { token: token })
|
|
193
|
-
data['deckPreview'] ? Deck.new(data['deckPreview'], client: client) : nil
|
|
194
|
-
end
|
|
195
|
-
end
|
|
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
210
|
def draft_diff(id:, cache: nil)
|
|
216
211
|
key = cache_key('decks', 'draft_diff', id: id)
|
|
217
212
|
with_cache(key, resource: :decks, cache: cache) do
|
|
@@ -239,9 +234,10 @@ module CardDB
|
|
|
239
234
|
end
|
|
240
235
|
|
|
241
236
|
def hydrate_deck_entries(input:, cache: nil)
|
|
242
|
-
|
|
237
|
+
normalized_input = normalize_deck_json_input(input)
|
|
238
|
+
key = cache_key('decks', 'hydrate_deck_entries', input: normalized_input)
|
|
243
239
|
with_cache(key, resource: :decks, cache: cache) do
|
|
244
|
-
data = connection.execute(QueryBuilder.deck_hydrate_entries, { input:
|
|
240
|
+
data = connection.execute(QueryBuilder.deck_hydrate_entries, { input: normalized_input })
|
|
245
241
|
DeckHydrateEntriesPayload.new(data['deckHydrateEntries'], client: client)
|
|
246
242
|
end
|
|
247
243
|
end
|
|
@@ -293,31 +289,6 @@ module CardDB
|
|
|
293
289
|
end
|
|
294
290
|
end
|
|
295
291
|
|
|
296
|
-
# List draft preview tokens for a deck.
|
|
297
|
-
def preview_tokens(deck_id:, cache: nil)
|
|
298
|
-
key = cache_key('decks', 'preview_tokens', deck_id: deck_id)
|
|
299
|
-
with_cache(key, resource: :decks, cache: cache) do
|
|
300
|
-
data = connection.execute(QueryBuilder.deck_preview_tokens, { deckId: deck_id })
|
|
301
|
-
(data['deckPreviewTokens'] || []).map { |token| DeckPreviewToken.new(token, client: client) }
|
|
302
|
-
end
|
|
303
|
-
end
|
|
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
292
|
def api_application_accesses(deck_id:, include_revoked: nil, cache: nil)
|
|
322
293
|
variables = build_variables(deckId: deck_id, includeRevoked: include_revoked)
|
|
323
294
|
key = cache_key('decks', 'api_application_accesses', **variables)
|
|
@@ -342,13 +313,13 @@ module CardDB
|
|
|
342
313
|
|
|
343
314
|
# Create a hosted deck.
|
|
344
315
|
def create(input:)
|
|
345
|
-
data = connection.execute(QueryBuilder.create_deck, { input: input })
|
|
316
|
+
data = connection.execute(QueryBuilder.create_deck, { input: normalize_deck_json_input(input) })
|
|
346
317
|
Deck.new(data['deckCreate'], client: client)
|
|
347
318
|
end
|
|
348
319
|
|
|
349
320
|
# Update a hosted deck.
|
|
350
321
|
def update(id:, input:)
|
|
351
|
-
data = connection.execute(QueryBuilder.update_deck, { id: id, input: input })
|
|
322
|
+
data = connection.execute(QueryBuilder.update_deck, { id: id, input: normalize_deck_json_input(input) })
|
|
352
323
|
Deck.new(data['deckUpdate'], client: client)
|
|
353
324
|
end
|
|
354
325
|
|
|
@@ -360,7 +331,7 @@ module CardDB
|
|
|
360
331
|
def upsert_by_external_ref(input:)
|
|
361
332
|
config.require_secret_credential!('decks.upsert_by_external_ref')
|
|
362
333
|
|
|
363
|
-
data = connection.execute(QueryBuilder.upsert_deck_by_external_ref, { input: input })
|
|
334
|
+
data = connection.execute(QueryBuilder.upsert_deck_by_external_ref, { input: normalize_deck_json_input(input) })
|
|
364
335
|
DeckUpsertByExternalRefPayload.new(data['deckUpsertByExternalRef'], client: client)
|
|
365
336
|
end
|
|
366
337
|
|
|
@@ -380,12 +351,12 @@ module CardDB
|
|
|
380
351
|
end
|
|
381
352
|
|
|
382
353
|
def add_entry(input:)
|
|
383
|
-
data = connection.execute(QueryBuilder.add_deck_entry, { input: input })
|
|
354
|
+
data = connection.execute(QueryBuilder.add_deck_entry, { input: normalize_deck_json_input(input) })
|
|
384
355
|
DeckEntryMutationPayload.new(data['deckEntryAdd'], client: client)
|
|
385
356
|
end
|
|
386
357
|
|
|
387
358
|
def update_entry(id:, input:)
|
|
388
|
-
data = connection.execute(QueryBuilder.update_deck_entry, { id: id, input: input })
|
|
359
|
+
data = connection.execute(QueryBuilder.update_deck_entry, { id: id, input: normalize_deck_json_input(input) })
|
|
389
360
|
DeckEntryMutationPayload.new(data['deckEntryUpdate'], client: client)
|
|
390
361
|
end
|
|
391
362
|
|
|
@@ -403,7 +374,7 @@ module CardDB
|
|
|
403
374
|
end
|
|
404
375
|
|
|
405
376
|
def replace_entries(deck_id:, input:)
|
|
406
|
-
data = connection.execute(QueryBuilder.replace_deck_entries, { deckId: deck_id, input: input })
|
|
377
|
+
data = connection.execute(QueryBuilder.replace_deck_entries, { deckId: deck_id, input: normalize_deck_json_input(input) })
|
|
407
378
|
DeckEntriesReplacePayload.new(data['deckEntriesReplace'], client: client)
|
|
408
379
|
end
|
|
409
380
|
|
|
@@ -522,47 +493,27 @@ module CardDB
|
|
|
522
493
|
end
|
|
523
494
|
# rubocop:enable Naming/PredicateMethod
|
|
524
495
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
data = connection.execute(QueryBuilder.create_deck_preview_token, { input: input })
|
|
528
|
-
DeckPreviewTokenCreatePayload.new(data['deckPreviewTokenCreate'], client: client)
|
|
529
|
-
end
|
|
496
|
+
def create_token_issuer(input:)
|
|
497
|
+
config.require_secret_credential!('decks.create_token_issuer')
|
|
530
498
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
def revoke_preview_token(id:)
|
|
534
|
-
data = connection.execute(QueryBuilder.revoke_deck_preview_token, { id: id })
|
|
535
|
-
!!data['deckPreviewTokenRevoke']
|
|
536
|
-
end
|
|
537
|
-
# rubocop:enable Naming/PredicateMethod
|
|
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)
|
|
499
|
+
data = connection.execute(QueryBuilder.create_deck_token_issuer, { input: input })
|
|
500
|
+
DeckTokenIssuer.new(data['deckTokenIssuerCreate'], client: client)
|
|
542
501
|
end
|
|
543
502
|
|
|
544
503
|
# rubocop:disable Naming/PredicateMethod
|
|
545
|
-
def
|
|
546
|
-
|
|
547
|
-
!!data['deckEmbedTokenRevoke']
|
|
548
|
-
end
|
|
549
|
-
# rubocop:enable Naming/PredicateMethod
|
|
504
|
+
def revoke_token_issuer(id:)
|
|
505
|
+
config.require_secret_credential!('decks.revoke_token_issuer')
|
|
550
506
|
|
|
551
|
-
|
|
552
|
-
data
|
|
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']
|
|
507
|
+
data = connection.execute(QueryBuilder.revoke_deck_token_issuer, { id: id })
|
|
508
|
+
!!data['deckTokenIssuerRevoke']
|
|
560
509
|
end
|
|
561
510
|
# rubocop:enable Naming/PredicateMethod
|
|
562
511
|
|
|
563
|
-
def
|
|
564
|
-
|
|
565
|
-
|
|
512
|
+
def revoke_token_issuer_signing_key(id:)
|
|
513
|
+
config.require_secret_credential!('decks.revoke_token_issuer_signing_key')
|
|
514
|
+
|
|
515
|
+
data = connection.execute(QueryBuilder.revoke_deck_token_issuer_signing_key, { id: id })
|
|
516
|
+
DeckTokenIssuer.new(data['deckTokenIssuerSigningKeyRevoke'], client: client)
|
|
566
517
|
end
|
|
567
518
|
|
|
568
519
|
def grant_api_application_access(input:)
|
|
@@ -580,27 +531,19 @@ module CardDB
|
|
|
580
531
|
end
|
|
581
532
|
# rubocop:enable Naming/PredicateMethod
|
|
582
533
|
|
|
583
|
-
def
|
|
584
|
-
config.require_secret_credential!('decks.
|
|
534
|
+
def exchange_token(input:)
|
|
535
|
+
config.require_secret_credential!('decks.exchange_token')
|
|
585
536
|
|
|
586
|
-
data = connection.execute(QueryBuilder.
|
|
587
|
-
|
|
588
|
-
end
|
|
589
|
-
|
|
590
|
-
# Exchange the current secret API application credential for an app-owned deck session token.
|
|
591
|
-
def exchange_session_token(input:)
|
|
592
|
-
config.require_secret_credential!('decks.exchange_session_token')
|
|
593
|
-
|
|
594
|
-
data = connection.execute(QueryBuilder.exchange_deck_session_token, { input: input })
|
|
595
|
-
DeckSessionTokenExchangePayload.new(data['deckSessionTokenExchange'], client: client)
|
|
537
|
+
data = connection.execute(QueryBuilder.exchange_deck_token, { input: input })
|
|
538
|
+
DeckTokenExchangePayload.new(data['deckTokenExchange'], client: client)
|
|
596
539
|
end
|
|
597
540
|
|
|
598
541
|
# rubocop:disable Naming/PredicateMethod
|
|
599
|
-
def
|
|
600
|
-
config.require_secret_credential!('decks.
|
|
542
|
+
def revoke_token(id:)
|
|
543
|
+
config.require_secret_credential!('decks.revoke_token')
|
|
601
544
|
|
|
602
|
-
data = connection.execute(QueryBuilder.
|
|
603
|
-
!!data['
|
|
545
|
+
data = connection.execute(QueryBuilder.revoke_deck_token, { id: id })
|
|
546
|
+
!!data['deckTokenRevoke']
|
|
604
547
|
end
|
|
605
548
|
# rubocop:enable Naming/PredicateMethod
|
|
606
549
|
|
|
@@ -650,6 +593,42 @@ module CardDB
|
|
|
650
593
|
|
|
651
594
|
private
|
|
652
595
|
|
|
596
|
+
def normalize_deck_json_input(input)
|
|
597
|
+
normalize_deck_json_value(input, path: 'input')
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
def normalize_deck_json_value(value, path:)
|
|
601
|
+
return value unless value.is_a?(Hash)
|
|
602
|
+
|
|
603
|
+
value.each_with_object({}) do |(key, child), normalized|
|
|
604
|
+
key_name = key.to_s
|
|
605
|
+
child_path = "#{path}.#{key_name}"
|
|
606
|
+
|
|
607
|
+
normalized[key] = if JSON_OBJECT_INPUT_KEYS.include?(key_name)
|
|
608
|
+
normalize_json_object(child, child_path)
|
|
609
|
+
elsif key_name == 'entries' && child.is_a?(Array)
|
|
610
|
+
child.each_with_index.map do |entry, index|
|
|
611
|
+
normalize_deck_json_value(entry, path: "#{child_path}[#{index}]")
|
|
612
|
+
end
|
|
613
|
+
else
|
|
614
|
+
child
|
|
615
|
+
end
|
|
616
|
+
end
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
def normalize_json_object(value, path)
|
|
620
|
+
return value if value.nil? || value.is_a?(Hash)
|
|
621
|
+
|
|
622
|
+
if value.is_a?(String)
|
|
623
|
+
parsed = JSON.parse(value)
|
|
624
|
+
return parsed if parsed.is_a?(Hash)
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
raise ValidationError, "#{path} must be a JSON object"
|
|
628
|
+
rescue JSON::ParserError
|
|
629
|
+
raise ValidationError, "#{path} must be a JSON object"
|
|
630
|
+
end
|
|
631
|
+
|
|
653
632
|
def entry_identifier(entry)
|
|
654
633
|
entry[:identifier] || entry['identifier'] || raise(ArgumentError, 'entry identifier is required')
|
|
655
634
|
end
|
data/lib/carddb/version.rb
CHANGED