carddb 0.3.0 → 0.3.10

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,80 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'carddb'
5
+
6
+ client = CardDB::Client.new(secret_key: ENV.fetch('CARDDB_SECRET_KEY'))
7
+ publisher_id = ENV.fetch('CARDDB_PUBLISHER_ID')
8
+ game_key = ENV.fetch('CARDDB_GAME_KEY', 'example-tcg')
9
+
10
+ game = client.games.get_by_key(publisher_id: publisher_id, game_key: game_key, cache: false) ||
11
+ client.games.create(
12
+ input: {
13
+ publisherId: publisher_id,
14
+ key: game_key,
15
+ name: 'Example TCG',
16
+ visibility: 'PRIVATE'
17
+ }
18
+ )
19
+
20
+ client.import_formats.create(
21
+ input: {
22
+ gameId: game.id,
23
+ key: 'ci-json',
24
+ name: 'CI JSON',
25
+ config: { schemaVersion: 1 }
26
+ }
27
+ )
28
+
29
+ advanced_payload = {
30
+ datasets: [
31
+ {
32
+ name: 'cards',
33
+ schema: {
34
+ identifier: { type: 'STRING', isIdentifier: true },
35
+ name: { type: 'STRING', required: true }
36
+ },
37
+ records: [{ identifier: 'CARD-001', name: 'Example Card' }]
38
+ }
39
+ ]
40
+ }
41
+
42
+ preview = client.imports.preview_game(input: { gameId: game.id, data: advanced_payload })
43
+ raise "Import preview blocked: #{preview.warnings.map(&:message).join(', ')}" unless preview.can_proceed?
44
+
45
+ import_job = client.imports.run_game(
46
+ input: {
47
+ gameId: game.id,
48
+ data: advanced_payload,
49
+ options: { mode: 'CREATE', onConflict: 'UPDATE' }
50
+ }
51
+ )
52
+ completed_import = client.imports.wait_for_game_job(import_job.id)
53
+ raise completed_import.error_message unless completed_import.completed?
54
+
55
+ dataset = client.datasets.get_by_key(game_id: game.id, dataset_key: 'cards')
56
+ raise 'cards dataset was not created' unless dataset
57
+
58
+ upsert = client.records.upsert_batch(
59
+ input: {
60
+ datasetId: dataset.id,
61
+ records: [{ identifier: 'CARD-002', name: 'Second Example Card' }],
62
+ options: { mode: 'STRICT', onConflict: 'UPDATE', dryRun: true }
63
+ }
64
+ )
65
+
66
+ raise "Upsert validation failed: #{upsert.dry_run_result.errors.map(&:index).join(', ')}" if upsert.dry_run_result&.errors&.any?
67
+
68
+ delete_preview = client.records.delete_batch(
69
+ input: {
70
+ datasetId: dataset.id,
71
+ reconcileIdentifiers: %w[CARD-001 CARD-002],
72
+ dryRun: true
73
+ }
74
+ )
75
+ puts "Would delete #{delete_preview.matched_count} records"
76
+
77
+ export_job = client.exports.run(input: { datasetId: dataset.id, format: 'JSON' })
78
+ export_result = client.exports.wait_for_job(export_job.id)
79
+ export_with_fresh_url = client.exports.refresh_url(id: export_result.id)
80
+ puts export_with_fresh_url.download_url
data/lib/carddb/batch.rb CHANGED
@@ -52,6 +52,13 @@ module CardDB
52
52
  BatchProxy.new(self, :records)
53
53
  end
54
54
 
55
+ # Access the Decks resource for batching
56
+ #
57
+ # @return [BatchProxy]
58
+ def decks
59
+ BatchProxy.new(self, :decks)
60
+ end
61
+
55
62
  # Add an operation to the batch
56
63
  #
57
64
  # @param resource [Symbol] The resource type
@@ -120,6 +127,8 @@ module CardDB
120
127
  build_dataset_query(op, index)
121
128
  when :records
122
129
  build_record_query(op, index)
130
+ when :decks
131
+ build_deck_query(op, index)
123
132
  else
124
133
  raise ArgumentError, "Unknown resource: #{op[:resource]}"
125
134
  end
@@ -201,6 +210,27 @@ module CardDB
201
210
  end
202
211
  end
203
212
 
213
+ def build_deck_query(op, index)
214
+ case op[:method]
215
+ when :fetch
216
+ var_name = "deckId#{index}"
217
+ query = "#{op[:alias]}: fetchDeck(id: $#{var_name}) { #{deck_fields} }"
218
+ [query, { var_name => op[:args][0] }, { var_name => 'UUID' }]
219
+ when :get
220
+ if op[:kwargs][:external_ref]
221
+ var_name = "deckExternalRef#{index}"
222
+ query = "#{op[:alias]}: deckByExternalRef(externalRef: $#{var_name}) { #{deck_fields} }"
223
+ [query, { var_name => op[:kwargs][:external_ref] }, { var_name => 'String' }]
224
+ else
225
+ var_name = "deckId#{index}"
226
+ query = "#{op[:alias]}: deck(id: $#{var_name}) { #{deck_fields} }"
227
+ [query, { var_name => op[:args][0] }, { var_name => 'UUID' }]
228
+ end
229
+ else
230
+ raise ArgumentError, "Unsupported batch method for decks: #{op[:method]}"
231
+ end
232
+ end
233
+
204
234
  def build_variable_definitions(variables)
205
235
  return '' if variables.empty?
206
236
 
@@ -231,6 +261,8 @@ module CardDB
231
261
  Dataset.new(result, client: @client)
232
262
  when :records
233
263
  Record.new(result, client: @client)
264
+ when :decks
265
+ Deck.new(result, client: @client)
234
266
  else
235
267
  result
236
268
  end
@@ -263,6 +295,23 @@ module CardDB
263
295
  def record_fields
264
296
  'id datasetId data createdAt updatedAt dataset { id key name gameId publisherId }'
265
297
  end
298
+
299
+ def deck_fields
300
+ [
301
+ 'id ownerType ownerAccountId ownerApiApplicationId environment',
302
+ 'createdByAccountId createdByApiApplicationId accountId apiApplicationId',
303
+ 'gameId game { id key name publisher { id name slug } }',
304
+ 'slug identifier title description formatKey visibility accessMode',
305
+ 'discoverability state archivedAt deletedAt unpublishedAt',
306
+ 'externalRefApiApplicationId externalRef externalSubjectRef',
307
+ 'rulesetId sourceUrl metadata',
308
+ 'entries { id datasetId recordId identifier quantity section sortOrder annotations display }',
309
+ 'sectionDefinitions { key label description order default aliases minCards maxCards excludedFromDeckSize legalCardTypes metadata }',
310
+ 'latestPublishedVersion { id deckId versionNumber slug identifier title description formatKey visibility state publishedAt }',
311
+ 'publishedAt draftRevision draftUpdatedAt draftUpdatedByAccountId draftUpdatedByApiApplicationId',
312
+ 'hasUnpublishedChanges createdAt updatedAt'
313
+ ].join(' ')
314
+ end
266
315
  end
267
316
 
268
317
  # Proxy class for batching operations on a specific resource
@@ -279,8 +328,8 @@ module CardDB
279
328
  end
280
329
 
281
330
  # Proxy get calls to the batch
282
- def get(**kwargs)
283
- @batch.add_operation(resource: @resource, method: :get, kwargs: kwargs)
331
+ def get(*args, **kwargs)
332
+ @batch.add_operation(resource: @resource, method: :get, args: args, kwargs: kwargs)
284
333
  nil # Return nil since we're batching
285
334
  end
286
335
  end
data/lib/carddb/client.rb CHANGED
@@ -98,6 +98,34 @@ module CardDB
98
98
  @records ||= Resources::Records.new(self, connection, config)
99
99
  end
100
100
 
101
+ # Access the Import Formats resource
102
+ #
103
+ # @return [Resources::ImportFormats]
104
+ def import_formats
105
+ @import_formats ||= Resources::ImportFormats.new(self, connection, config)
106
+ end
107
+
108
+ # Access the Imports resource
109
+ #
110
+ # @return [Resources::Imports]
111
+ def imports
112
+ @imports ||= Resources::Imports.new(self, connection, config)
113
+ end
114
+
115
+ # Access the Exports resource
116
+ #
117
+ # @return [Resources::Exports]
118
+ def exports
119
+ @exports ||= Resources::Exports.new(self, connection, config)
120
+ end
121
+
122
+ # Access the Files resource
123
+ #
124
+ # @return [Resources::Files]
125
+ def files
126
+ @files ||= Resources::Files.new(self, connection, config)
127
+ end
128
+
101
129
  # Access the Decks resource
102
130
  #
103
131
  # @return [Resources::Decks]