cc-cli 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +12 -0
  5. data/Guardfile +24 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +186 -0
  8. data/Rakefile +1 -0
  9. data/bin/cc-cli +5 -0
  10. data/cc-cli.gemspec +28 -0
  11. data/circle.yml +11 -0
  12. data/config/config.yml +31 -0
  13. data/lib/cc/api/explorer.rb +175 -0
  14. data/lib/cc/api/explorer/version.rb +7 -0
  15. data/lib/cc/api/http/http_requestor.rb +50 -0
  16. data/lib/cc/api/parser/arguments_mapper.rb +44 -0
  17. data/lib/cc/api/parser/arguments_parser.rb +65 -0
  18. data/lib/cc/api/parser/json_parser.rb +38 -0
  19. data/lib/cc/api/presentor/presentor.rb +47 -0
  20. data/lib/cc/api/util/config_reader.rb +38 -0
  21. data/lib/cc/api/util/key_chains_getter.rb +80 -0
  22. data/spec/dummy_data/catalog_categories.json +1 -0
  23. data/spec/dummy_data/catalog_product_types.json +1 -0
  24. data/spec/dummy_data/catalog_products.json +1 -0
  25. data/spec/dummy_data/catalog_stores.json +1 -0
  26. data/spec/dummy_data/lattice_offers.json +1 -0
  27. data/spec/dummy_data/lattice_products.json +1 -0
  28. data/spec/dummy_data/lattice_stores.json +1 -0
  29. data/spec/dummy_data/store_products.json +1 -0
  30. data/spec/explorer_spec.rb +238 -0
  31. data/spec/http/http_requestor_spec.rb +54 -0
  32. data/spec/parser/arguments_mapper_spec.rb +78 -0
  33. data/spec/parser/arguments_parser_spec.rb +81 -0
  34. data/spec/parser/json_parser_spec.rb +108 -0
  35. data/spec/spec_helper.rb +49 -0
  36. data/spec/support/arguments_mapper_returning_blank_json.rb +7 -0
  37. data/spec/support/arguments_mapper_returning_json_with_id_and_skus.rb +7 -0
  38. data/spec/support/arguments_mapper_returning_page_params.rb +7 -0
  39. data/spec/support/arguments_parser_returning_expected_result.rb +6 -0
  40. data/spec/support/json_parser.rb +43 -0
  41. data/spec/support/stdout_helper.rb +10 -0
  42. data/spec/support/table_fields_matcher.rb +16 -0
  43. data/spec/utils/utils_spec.rb +90 -0
  44. metadata +194 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OGUwZWI3ZTk1NTBjOWNiMGZlMjEyYmIwYTY2YzEzMjQwNzNjMTFiYg==
5
+ data.tar.gz: !binary |-
6
+ ZjQxMzZkODk4ZDZjYjZjZmEyYjhkMjE0ODk3NWM2ODNkNjgyOWQxOA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ OGE5MTE4NGE0YTMyZDNkYTBkYjUzNzc4ODRkMzhhN2E5NzI0YTM3ZWUxYzA3
10
+ NGQ2YzAxOTU0OGU2YTEzNjllMDg3MWVmZDRjN2YzNjkzOWJhNjljYjk0MDZk
11
+ MDlmMTk3MWQ2MDExN2EwZDJmMzcyMzk1NGNkZmNmNTg1YTQ3ODk=
12
+ data.tar.gz: !binary |-
13
+ MmFlNzQ5YmZhYWIxODk3MjZiYTUyMWRiZTI4NWFjZmY3OWQxMDJhNTA5NjNm
14
+ MTQ2N2QzNDhjMmMwYzVhNmY3M2VlMDQzY2NhOTBlNDY0ZmRkMjc4MzgwZGYy
15
+ NGY2YTE1NTZjYmMxZDNiODdlODMwNDYzYTViMDA2Yzg0ZGM3NmU=
@@ -0,0 +1,19 @@
1
+ *.rbc
2
+ .bundle
3
+ .config
4
+ .yardoc
5
+ Gemfile.lock
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
17
+ *.sw*
18
+ null.txt
19
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cc-api-explorer.gemspec
4
+ gemspec
5
+
6
+ gem 'thor'
7
+ gem 'httparty'
8
+ gem 'multi_json'
9
+ gem 'command_line_reporter'
10
+ gem 'webmock'
11
+ gem 'guard-rspec'
12
+ gem 'pry'
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara features specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Neil Marion dela Cruz
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,186 @@
1
+ # CrystalCommerce CLI
2
+
3
+ This is a command line client for exploring CrystalCommerce APIs
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'cc-cli', :git => "git@github.com:crystalcommerce/cc-cli.git"
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as (not yet available as of the moment):
16
+
17
+ $ gem install cc-cli
18
+
19
+ ## Usage
20
+
21
+ To view help:
22
+
23
+ $ cc-cli
24
+
25
+ The license key pair `<ssologin>` and `<key>` are basically just basic auth username and password respectively.
26
+ To obtain a license key, contact: contact: Jerad Ellison or call (206) 274-7437 Ext. 3.
27
+
28
+ Add these lines in your ~/.bashrc (linux) or ~/.profile (mac) file:
29
+
30
+ export CC_API_LOGIN=<login>
31
+ export CC_API_KEY=<key>
32
+
33
+ If you are working in a project, you can also install the
34
+ [dotenv](http://rubygems.org/gems/dotenv) gem and put a .env file in
35
+ the working directory that looks like:
36
+
37
+ CC_API_LOGIN=<login>
38
+ CC_API_KEY=<key>
39
+
40
+ You can then run the program with `dotenv cc-cli`. This approach will
41
+ be advantageous if you don't want to edit your user's shell config to
42
+ use this tool.
43
+
44
+ These are the available commands:
45
+
46
+ $ cc-cli catalog [products] | [product_types] | [stores] | [categories]
47
+ $ cc-cli help [COMMND]
48
+ $ cc-cli lattice [products --id <PRODUCT ID> --skus <PRODUCT SKUS separated by ','>] | [offers --id <PRODUCT ID> --skus <PRODUCT SKUS separated by ','>] | [stores]
49
+ $ cc-cli store [products --token <access token> --store <store name>]
50
+
51
+ To choose columns/json keys to display:
52
+
53
+ Display the available columns for a given command. Say for example `$ cc-cli catalog products`:
54
+
55
+ $ cc-cli catalog products --available-cols
56
+
57
+ available columns
58
+ ====================
59
+ id
60
+ name
61
+ seoname
62
+ category_name
63
+ weight
64
+ description
65
+ asin
66
+ category_id
67
+ product_type_id
68
+ descriptors.*
69
+ photo.content_type
70
+ photo.urls.medium
71
+ photo.urls.thumb
72
+ photo.urls.large
73
+ photo.urls.ebay
74
+
75
+ USAGE:
76
+ --cols descriptors.Name,descriptors.Pow/Tgh,seoname
77
+
78
+ Then display the table
79
+
80
+ $ cc-cli catalog products --cols descriptors.Name,descriptors.Pow/Tgh,seoname
81
+ GET https://api.crystalcommerce.com/v1/catalog/products?page=1
82
+ response time: 2.091034343
83
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
84
+ ┃ descriptors.Name ┃ descriptors.Pow/Tgh ┃ seoname ┃
85
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
86
+ ┃ Abyssal Specter ┃ 2/3 ┃ abyssal_specter ┃
87
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
88
+ ┃ Air Elemental ┃ 4/4 ┃ air_elemental ┃
89
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
90
+ ┃ Aladdin's Ring ┃ ┃ aladdins_ring ┃
91
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
92
+ ┃ Ambition's Cost ┃ ┃ ambitions_cost ┃
93
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
94
+ ┃ Anaba Shaman ┃ 2/2 ┃ anaba_shaman ┃
95
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
96
+ ┃ Angel of Mercy ┃ 3/3 ┃ angel_of_mercy ┃
97
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
98
+
99
+ When `--cols` is not used, the default `--cols` values will then be selected.
100
+
101
+ This is also capable of displaying values from arrays within the JSON object from the API response. For example let's first print `$ cc-cli catalog product_types` available columns:
102
+
103
+ $ cc-cli catalog product_types --available-cols
104
+ GET https://api.crystalcommerce.com/v1/catalog/product_types?page=1
105
+ response time: 1.654095542
106
+
107
+ available columns
108
+ ====================
109
+ id
110
+ name
111
+ default_weight
112
+ amazon_search_index
113
+ variant_dimensions.<index>.name
114
+ variant_dimensions.<index>.product_type_id
115
+ variant_dimensions.<index>.default_option_id
116
+ variant_dimensions.<index>.options.<index>.value
117
+ variant_dimensions.<index>.options.<index>.code
118
+ descriptors.<index>.*
119
+
120
+ The `<index>` must be replaced by an integer:
121
+
122
+ $ cc-cli catalog product_types --cols name,variant_dimensions.0.name,variant_dimensions.0.default_option_id --colp 1
123
+ GET https://api.crystalcommerce.com/v1/catalog/product_types?page=1
124
+ response time: 1.389229104
125
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
126
+ ┃ name ┃ variant_dimensions.0.name ┃ variant_dimensions.0.default ┃
127
+ ┃ ┃ ┃ _option_id ┃
128
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
129
+ ┃ Pathfinder ┃ Condition ┃ 94 ┃
130
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
131
+ ┃ Horrorclix ┃ Condition ┃ ┃
132
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
133
+ ┃ Misc Products for Mad Al ┃ Condtion ┃ ┃
134
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
135
+ ┃ Miniatures Sealed Product ┃ Condition ┃ ┃
136
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
137
+ ┃ Dragon Ball CCG Sealed ┃ Condition ┃ 753 ┃
138
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
139
+ ┃ Battle Spirits Sealed Produc ┃ Condition ┃ ┃
140
+ ┃ t ┃ ┃ ┃
141
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
142
+ ┃ Other Card Games - Sealed ┃ Condition ┃ ┃
143
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
144
+ ┃ Axis & Allies: Air Force Min ┃ Condition ┃ ┃
145
+ ┃ iatures Singles ┃ ┃ ┃
146
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
147
+ ┃ DVDs ┃ Condition ┃ ┃
148
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
149
+ ┃ Sportscards & Trading Cards ┃ Condition ┃ ┃
150
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
151
+ ┃ Toys ┃ Condition ┃ ┃
152
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
153
+ ┃ Video Game Accessories ┃ Condition ┃ ┃
154
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
155
+ ┃ Kaijudo Sealed Product ┃ Condition ┃ 96 ┃
156
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
157
+ ┃ Candy ┃ Condition ┃ ┃
158
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
159
+ ┃ Marvel Super Hero Squad ┃ Condition ┃ ┃
160
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
161
+ ┃ Pathfinder Miniatures ┃ Condition ┃ ┃
162
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
163
+ ┃ Cardfight! Vanguard Sealed P ┃ Condition ┃ 163 ┃
164
+ ┃ roduct ┃ ┃ ┃
165
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
166
+ ┃ Cthulhu Tech ┃ Condition ┃ ┃
167
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
168
+ ┃ Cardfight!! Vanguard ┃ Condition ┃ 86 ┃
169
+ ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
170
+ ┃ Axis & Allies: War At Sea Mi ┃ Condition ┃ ┃
171
+ ┃ niatures ┃ ┃ ┃
172
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
173
+
174
+ Other available options:
175
+
176
+ [--offset=N] # Offset of the starting row to be displayed. Nothing is displayed when out of bounds.
177
+ [--limit=N] # Limit of rows to be displayed.
178
+ [--colw=N] # Width of every column to be displayed.
179
+ [--colp=N] # Padding of every cell to be displayed.
180
+ [--json] # Prints the JSON response body instead.
181
+ [--page=N] # Page number of the response.
182
+ [--csv=CSV_FILE_PATH] # Print out the result into a csv file. Columns are separated by comma
183
+
184
+ ## ISSUES
185
+
186
+ There is going to be an issue when trying to include as a `--cols` value a 'available-cols' that has a whitespace within its string. E.g. "descriptors.Set Name" for `$ cc-cli catalog products`
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'cc/api/explorer'
3
+ require 'httparty'
4
+ require 'command_line_reporter'
5
+ Cc::Api::Explorer::CLI.start
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cc/api/explorer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cc-cli"
8
+ spec.version = Cc::Api::Explorer::VERSION
9
+ spec.authors = ["Neil Marion dela Cruz", "Michael Xavier"]
10
+ spec.email = ["developers@crystalcommerce.com"]
11
+ spec.summary = %q{CrystalCommerce API Explorer}
12
+ spec.description = %q{This is a command line client for exploring CrystalCommerce APIs}
13
+ spec.homepage = "https://github.com/crystalcommerce/cc-cli"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "command_line_reporter"
22
+ spec.add_runtime_dependency "httparty"
23
+ spec.add_runtime_dependency "thor"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.5"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec"
28
+ end
@@ -0,0 +1,11 @@
1
+ test:
2
+ override:
3
+ - rvm use --default 1.9.3
4
+ - bundle install
5
+ - bundle exec rspec
6
+ - rvm use --default 2.1.0
7
+ - bundle install
8
+ - bundle exec rspec
9
+ - rvm use --default 2.1.1
10
+ - bundle install
11
+ - bundle exec rspec
@@ -0,0 +1,31 @@
1
+ lattice:
2
+ products:
3
+ url: https://api.crystalcommerce.com/v1/lattice/products
4
+ target_key_chain: "product.variants.FIRST.variant.store_variants"
5
+ stores:
6
+ url: https://api.crystalcommerce.com/v1/lattice/stores
7
+ target_key_chain: ""
8
+ offers:
9
+ url: https://api.crystalcommerce.com/v1/lattice/offers
10
+ method: POST
11
+ target_key_chain: "PRODUCT_ID"
12
+ catalog:
13
+ products:
14
+ url: https://api.crystalcommerce.com/v1/catalog/products
15
+ target_key_chain: "products"
16
+ ignores: ["descriptors"]
17
+ product_types:
18
+ url: https://api.crystalcommerce.com/v1/catalog/product_types
19
+ target_key_chain: "product_types"
20
+ ignores: ["descriptors.<index>"]
21
+ stores:
22
+ url: https://api.crystalcommerce.com/v1/catalog/stores
23
+ target_key_chain: "stores"
24
+ categories:
25
+ url: https://api.crystalcommerce.com/v1/catalog/categories
26
+ target_key_chain: "categories"
27
+ store:
28
+ products:
29
+ url: https://*-api.crystalcommerce.com/v1/products
30
+ target_key_chain: "paginated_collection.entries"
31
+ ignores: ["product.descriptors"]
@@ -0,0 +1,175 @@
1
+ require 'cc/api/explorer/version'
2
+ require 'cc/api/http/http_requestor'
3
+ require 'cc/api/parser/arguments_parser'
4
+ require 'cc/api/parser/json_parser'
5
+ require 'cc/api/presentor/presentor'
6
+ require 'cc/api/util/config_reader'
7
+ require 'cc/api/util/key_chains_getter'
8
+ require 'command_line_reporter'
9
+ require 'thor'
10
+ require 'yaml'
11
+
12
+ module Cc
13
+ module Api
14
+ module Explorer
15
+ class CLI < Thor
16
+ DEFAULT_COLS =
17
+ {
18
+ "lattice-products" => ["store_variant.store_name", "store_variant.qty", "store_variant.buy_price.money.currency"],
19
+ "lattice-stores" => ["store.name", "store.state", "store.url"],
20
+ "lattice-offers" => ["store.name", "buy_price.cents", "sell_price.cents"],
21
+ "catalog-products" => ["name", "barcode", "weight"],
22
+ "catalog-product_types" => ["name", "id", "default_weight"],
23
+ "catalog-stores" => ["name", "postal_code", "url"],
24
+ "catalog-categories" => ["name", "seoname", "description"],
25
+ "store-products" => ["product.seoname", "product.weight", "product.description"]
26
+ }
27
+
28
+ DESC =
29
+ {
30
+ "cols" => "Columns to display to the output table. To determine the 'available columns' for a selected command use --available_cols",
31
+ "available_cols" => "Output the available columns for output for a command",
32
+ "offset" => "Offset of the starting row to be displayed. Nothing is displayed when out of bounds",
33
+ "limit" => "Limit of rows to be displayed",
34
+ "colw" => "Width of every column to be displayed",
35
+ "colp" => "Padding of every cell to be displayed",
36
+ "json" => "Prints the JSON response body instead",
37
+ "id" => "Product ID",
38
+ "skus" => "SKUs separated by ',' if more than one",
39
+ "page" => "Page number of the response",
40
+ "token" => "OAuth Token",
41
+ "store" => "Store name (CrystalCommerce Client)",
42
+ "csv" => "Print out the result into a csv file. Columns are separated by comma"
43
+ }
44
+
45
+ option :csv, :desc => DESC["csv"], :banner => "CSV_FILE_PATH"
46
+ option :cols, :desc => DESC["cols"]
47
+ option :available_cols, :type => :boolean, :desc => DESC["available_cols"]
48
+ option :offset, :type => :numeric, :desc => DESC["offset"]
49
+ option :limit, :type => :numeric, :desc => DESC["limit"]
50
+ option :colw, :type => :numeric, :desc => DESC["colw"]
51
+ option :colp, :type => :numeric, :desc => DESC["colp"]
52
+ option :json, :type => :boolean, :desc => DESC["json"]
53
+ option :id, :desc => DESC["id"]
54
+ option :skus, :desc => DESC["skus"]
55
+ desc "lattice [products --id <PRODUCT ID> --skus <PRODUCT SKUS separated by ','>] | [offers --id <PRODUCT ID> --skus <PRODUCT SKUS separated by comma>] | [stores]",
56
+ "The Market Data APIs track the Prices, Quantities, and similar data. It also indicates which stores in the CrystalCommerce in-network currently has those products for sale."
57
+ def lattice(subcommand)
58
+ case subcommand
59
+ when "products"
60
+ # { product : { variants : { store_variants : [ { store_variant : { ... } } ] } } }
61
+ args = {:action => "lattice-products", :params => {:id => options[:id], :skus => options[:skus].to_s.split(',') } }
62
+ perform(args)
63
+ when "stores"
64
+ # { [ { store : { ... } } ] }
65
+ args = {:action => "lattice-stores"}
66
+ perform(args)
67
+ when "offers"
68
+ # { <PRODUCT ID> : [ { ... } ] }
69
+ args = {:action => "lattice-offers", :params => {:id => options[:id], :skus => options[:skus].to_s.split(',') } }
70
+ perform(args)
71
+ else
72
+ Cc::Api::Parser::ArgumentsParser.raise_cli_arguments_exception
73
+ end
74
+ end
75
+
76
+ option :csv, :desc => DESC["csv"], :banner => "CSV_FILE_PATH"
77
+ option :cols, :desc => DESC["cols"]
78
+ option :available_cols, :type => :boolean, :desc => DESC["available_cols"]
79
+ option :offset, :type => :numeric, :desc => DESC["offset"]
80
+ option :limit, :type => :numeric, :desc => DESC["limit"]
81
+ option :colw, :type => :numeric, :desc => DESC["colw"]
82
+ option :colp, :type => :numeric, :desc => DESC["colp"]
83
+ option :json, :type => :boolean, :desc => DESC["json"]
84
+ option :page, :type => :numeric, :desc => DESC["page"]
85
+
86
+ desc "catalog [products] | [product_types] | [stores] | [categories]",
87
+ "This API will give access to read the catalog of products. This includes what products could be sold but doesn't include prices or quantities, which are stored in the Market Data APIs."
88
+ def catalog(subcommand)
89
+ case subcommand
90
+ when "products"
91
+ # { products : [ { ... } }
92
+ args = {:action => "catalog-products", :params => { :page => options[:page] || 1 } }
93
+ perform(args)
94
+ when "product_types"
95
+ # { products : [ { ... } ] }
96
+ args = {:action => "catalog-product_types", :params => { :page => options[:page] || 1 } }
97
+ perform(args)
98
+ when "stores"
99
+ # { stores : [ { ... } ] }
100
+ args = {:action => "catalog-stores"}
101
+ perform(args)
102
+ when "categories"
103
+ # { categories : [ { ... } ] }
104
+ args = {:action => "catalog-categories", :params => { :page => options[:page] || 1} }
105
+ perform(args)
106
+ else
107
+ Cc::Api::Parser::ArgumentsParser.raise_cli_arguments_exception
108
+ end
109
+ end
110
+
111
+ option :csv, :desc => DESC["csv"], :banner => "CSV_FILE_PATH"
112
+ option :cols, :desc => DESC["cols"]
113
+ option :available_cols, :type => :boolean, :desc => DESC["available_cols"]
114
+ option :offset, :type => :numeric, :desc => DESC["offset"]
115
+ option :limit, :type => :numeric, :desc => DESC["limit"]
116
+ option :colw, :type => :numeric, :desc => DESC["colw"]
117
+ option :colp, :type => :numeric, :desc => DESC["colp"]
118
+ option :json, :type => :boolean, :desc => DESC["json"]
119
+ option :page, :type => :numeric, :desc => DESC["page"]
120
+ option :token, :desc => DESC["token"]
121
+ option :store, :desc => DESC["store"]
122
+
123
+ desc "store [products --token <access token> --store <store name>]", "The Store Data API provides access to the data related to a single store whereas the Market Data API applies to all stores."
124
+ def store(subcommand)
125
+ case subcommand
126
+ when "products"
127
+ # { paginated_collection : { entries : [ { product: { ... } } ] } }
128
+ args = {:action => "store-products", :params => {:token => options[:token], :store => options[:store], :page => options[:page] || 1} }
129
+ perform(args)
130
+ else
131
+ Cc::Api::Parser::ArgumentsParser.raise_cli_arguments_exception
132
+ end
133
+ end
134
+
135
+ private
136
+
137
+ def perform(args)
138
+
139
+ action = args[:action]
140
+
141
+ begin
142
+ param = Cc::Api::Parser::ArgumentsParser.parse args
143
+ response = http_requestor.request_for_json param
144
+
145
+ if options[:json]
146
+ puts JSON.pretty_generate response[:body]
147
+ else
148
+ target = Cc::Api::Parser::ArgumentsMapper.get_target_key_chain action
149
+ array = Cc::Api::Util::KeyChainsGetter.get_target_array response[:body], target, options[:id]
150
+ if options[:available_cols]
151
+ Cc::Api::Util::KeyChainsGetter.get_key_chains array.first, "", Cc::Api::Parser::ArgumentsMapper.get_ignored_key_chain(action)
152
+ else
153
+ puts "response time: #{response[:response_time]}"
154
+ begin
155
+ result = Cc::Api::Parser::JsonParser.vanilla_reduce array, options[:cols].split(',')
156
+ rescue
157
+ result = Cc::Api::Parser::JsonParser.vanilla_reduce array, DEFAULT_COLS[action]
158
+ end
159
+ tabler = Cc::Api::Presentor::Tabler.new
160
+ tabler.present result, options[:colw], options[:colp], options[:offset], options[:limit]
161
+ Cc::Api::Presentor::CSVer.to_csv result, options[:csv], options[:offset], options[:limit] if options[:csv]
162
+ end
163
+ end
164
+ rescue => e
165
+ puts e.message
166
+ end
167
+ end
168
+
169
+ def http_requestor
170
+ Cc::Api::Http::HttpRequestor.new
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end