cts-mpx 1.0.1

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +50 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +88 -0
  5. data/CONTRIBUTING +8 -0
  6. data/COPYRIGHT +10 -0
  7. data/EXAMPLES.md +81 -0
  8. data/Gemfile +4 -0
  9. data/Gemfile.lock +172 -0
  10. data/Guardfile +41 -0
  11. data/LICENSE +201 -0
  12. data/NOTICE +9 -0
  13. data/README.md +60 -0
  14. data/Rakefile +6 -0
  15. data/bin/console +14 -0
  16. data/bin/setup +8 -0
  17. data/config/data_services.json +423 -0
  18. data/config/ingest_services.json +14 -0
  19. data/config/root_registry_sea1.json +118 -0
  20. data/config/web_services.json +544 -0
  21. data/cts-mpx.gemspec +43 -0
  22. data/examples/basic_query.rb +23 -0
  23. data/examples/login.rb +7 -0
  24. data/examples/update_media.rb +16 -0
  25. data/examples/update_procedurally.rb +20 -0
  26. data/lib/cts/mpx.rb +42 -0
  27. data/lib/cts/mpx/driver.rb +47 -0
  28. data/lib/cts/mpx/driver/assemblers.rb +96 -0
  29. data/lib/cts/mpx/driver/connections.rb +41 -0
  30. data/lib/cts/mpx/driver/exceptions.rb +50 -0
  31. data/lib/cts/mpx/driver/helpers.rb +67 -0
  32. data/lib/cts/mpx/driver/page.rb +38 -0
  33. data/lib/cts/mpx/driver/request.rb +60 -0
  34. data/lib/cts/mpx/driver/response.rb +72 -0
  35. data/lib/cts/mpx/entries.rb +80 -0
  36. data/lib/cts/mpx/entry.rb +100 -0
  37. data/lib/cts/mpx/field.rb +38 -0
  38. data/lib/cts/mpx/fields.rb +120 -0
  39. data/lib/cts/mpx/query.rb +115 -0
  40. data/lib/cts/mpx/registry.rb +60 -0
  41. data/lib/cts/mpx/service.rb +70 -0
  42. data/lib/cts/mpx/services.rb +113 -0
  43. data/lib/cts/mpx/services/data.rb +124 -0
  44. data/lib/cts/mpx/services/ingest.rb +60 -0
  45. data/lib/cts/mpx/services/web.rb +90 -0
  46. data/lib/cts/mpx/user.rb +74 -0
  47. data/lib/cts/mpx/validators.rb +51 -0
  48. data/lib/cts/mpx/version.rb +6 -0
  49. data/sdk-ring-diagram.png +0 -0
  50. data/sdk-uml.png +0 -0
  51. data/uml.nomnoml +242 -0
  52. metadata +401 -0
@@ -0,0 +1,43 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'cts/mpx/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "cts-mpx"
7
+ spec.version = Cts::Mpx::VERSION
8
+ spec.authors = ["Ernie Brodeur"]
9
+ spec.email = ["ernest.brodeur@cable.comcast.net"]
10
+
11
+ spec.summary = "Ruby bindings for MPX services."
12
+ spec.description = "."
13
+
14
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ spec.bindir = "exe"
16
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.require_paths = ["lib"]
18
+ spec.required_ruby_version = '>= 2.4.0'
19
+
20
+ spec.add_runtime_dependency "creatable", "1.0.1"
21
+ spec.add_runtime_dependency "excon"
22
+ spec.add_runtime_dependency "oj", "3.5.0"
23
+
24
+ spec.add_development_dependency 'bump'
25
+ spec.add_development_dependency "bundler"
26
+ spec.add_development_dependency "erubis"
27
+ spec.add_development_dependency "gli"
28
+ spec.add_development_dependency "guard"
29
+ spec.add_development_dependency "guard-bundler"
30
+ spec.add_development_dependency "guard-rspec"
31
+ spec.add_development_dependency "guard-rubocop"
32
+ spec.add_development_dependency "guard-yard"
33
+ spec.add_development_dependency "pry"
34
+ spec.add_development_dependency 'pry-rescue'
35
+ spec.add_development_dependency 'pry-stack_explorer'
36
+ spec.add_development_dependency "rake"
37
+ spec.add_development_dependency "rspec"
38
+ spec.add_development_dependency "rubocop", "~>0.52.1"
39
+ spec.add_development_dependency "rubocop-rspec"
40
+ spec.add_development_dependency "simplecov"
41
+ spec.add_development_dependency "simplecov-console"
42
+ spec.add_development_dependency "yard"
43
+ end
@@ -0,0 +1,23 @@
1
+ require 'cts/mpx'
2
+
3
+ user = Cts::Mpx::User.create(username: 'username', password: '*****').sign_in
4
+ account = "http://access.auth.theplatform.com/data/Account/0000000000"
5
+ service = 'Media Data Service'
6
+ endpoint = 'Media'
7
+
8
+ # build our query, and immediately run it.
9
+ q = Query.create(account: account, service: service, endpoint: endpoint, fields: 'id,guid,title').run user: user
10
+
11
+ ### Print out a single entry
12
+ puts q.entries.first.to_h
13
+
14
+ ### Print out just the intries
15
+ puts q.entries.to_h
16
+
17
+ ### Print out the query (including entries)
18
+ puts q.entries.to_h
19
+
20
+ ### Print out the query (without entries)
21
+ puts q.entries.to_h include_entries: false
22
+
23
+ user.sign_out
@@ -0,0 +1,7 @@
1
+ require 'cts/mpx'
2
+
3
+ ### You can split the sign_in into it's own line.
4
+ user = Cts::Mpx::User.create(username: 'username', password: '*****').sign_in
5
+
6
+ ### begone token!
7
+ user.sign_out
@@ -0,0 +1,16 @@
1
+ require 'cts/mpx'
2
+
3
+ user = Cts::Mpx::User.create(username: 'username', password: '*****').sign_in
4
+ account = "http://access.auth.theplatform.com/data/Account/0000000000"
5
+ service = 'Media Data Service'
6
+ endpoint = 'Media'
7
+
8
+ # build our query, and immediately run it.
9
+ q = Query.create(account: account, service: service, endpoint: endpoint, fields: 'id,guid,title').run user: user
10
+
11
+ q.entries.each do |entry|
12
+ entry.title += '!!!'
13
+ entry.save
14
+ end
15
+
16
+ user.sign_out
@@ -0,0 +1,20 @@
1
+ require 'cts/mpx'
2
+
3
+ user = Cts::Mpx::User.create(username: 'username', password: '*****').sign_in
4
+ account = "http://access.auth.theplatform.com/data/Account/0000000000"
5
+ service = 'Media Data Service'
6
+ endpoint = 'Media'
7
+
8
+ response = Cts::Mpx::Services::Data.get user: user, service: service, endpoint: endpoint, account: account, fields: 'id,guid,title,description'
9
+ media = response.page
10
+
11
+ # modify them all
12
+ media.entries.each { |e| e["description"] = '1' }
13
+
14
+ # put them back
15
+ response = Cts::Mpx::Services::Data.put user: user, service: 'Media Data Service', endpoint: endpoint, account: account, page: media
16
+
17
+ # show response
18
+ puts response.status
19
+
20
+ user.sign_out
@@ -0,0 +1,42 @@
1
+ require 'base64'
2
+ require 'creatable'
3
+ require 'excon'
4
+ require 'oj'
5
+ require 'uri'
6
+ require 'cts/mpx/version'
7
+
8
+ # ring 1 (driver)
9
+ require 'cts/mpx/driver'
10
+ require 'cts/mpx/driver/assemblers'
11
+ require 'cts/mpx/driver/connections'
12
+ require 'cts/mpx/driver/exceptions'
13
+ require 'cts/mpx/driver/helpers'
14
+ require 'cts/mpx/driver/page'
15
+ require 'cts/mpx/driver/response'
16
+ require 'cts/mpx/driver/request'
17
+
18
+ # ring 2 (depends on driver)
19
+ require 'cts/mpx/validators'
20
+ require 'cts/mpx/user'
21
+ require 'cts/mpx/registry'
22
+ require 'cts/mpx/service'
23
+ require 'cts/mpx/services'
24
+ require 'cts/mpx/services/data'
25
+ require 'cts/mpx/services/web'
26
+ require 'cts/mpx/services/ingest'
27
+
28
+ # ring 3 (depends on ring 2 services)
29
+ require 'cts/mpx/field'
30
+ require 'cts/mpx/fields'
31
+ require 'cts/mpx/entry'
32
+ require 'cts/mpx/entries'
33
+ require 'cts/mpx/query'
34
+
35
+ # Comcast Technical Solutions
36
+ module Cts
37
+ # Media Platform
38
+ module Mpx
39
+ Services.initialize
40
+ Registry.initialize
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ module Cts
2
+ module Mpx
3
+ # responsible for low level calls to MPX
4
+ module Driver
5
+ module_function
6
+
7
+ #
8
+ # path to our gem directory, includes support for bundled env's.
9
+ #
10
+ # @return [String] full path to the root of our gem directory.
11
+ #
12
+ def gem_dir
13
+ return Dir.pwd unless Gem.loaded_specs.include? 'cts-mpx'
14
+ Gem.loaded_specs['cts-mpx'].full_gem_path
15
+ end
16
+
17
+ #
18
+ # path to our config files
19
+ #
20
+ # @return [String] full path to the root of our gem directory.
21
+ #
22
+ def config_dir
23
+ "#{gem_dir}/config"
24
+ end
25
+
26
+ #
27
+ # load a json file into a simple hash
28
+ #
29
+ # @param [String] filename filename to load
30
+ #
31
+ # @raise [RuntimeError] if the filename does not exist.
32
+ # @raise [RuntimeError] if the file cannot be parsed, supplies the exception.
33
+ #
34
+ # @return [Hash] data from the file
35
+ #
36
+ def load_json_file(filename)
37
+ raise "#{filename} does not exist" unless File.exist? filename
38
+
39
+ begin
40
+ Oj.load File.read filename
41
+ rescue Oj::ParseError => exception
42
+ raise "#{filename}: #{exception.message}"
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,96 @@
1
+ module Cts
2
+ module Mpx
3
+ module Driver
4
+ #
5
+ # collection of methods used to assemble various parts of a request.
6
+ #
7
+ module Assemblers
8
+ module_function
9
+
10
+ # assembles user service and account_id into a host string
11
+ # @param [Cts::Mpx::User] user user to make calls with
12
+ # @param [String] service title of a service
13
+ # @param [String] account_id long form account_id id (ownerId)
14
+ # @raise [ArgumentError] if user or service is not supplied
15
+ # @raise [RuntimeError] if the user token is not set
16
+ # @return [String] assembled scheme and host
17
+ def host(user: nil, service: nil, account_id: 'urn:theplatform:auth:root')
18
+ Helpers.required_arguments %i[user service], binding
19
+ user.token!
20
+
21
+ service = Services[service]
22
+ u = URI.parse service.url
23
+
24
+ [u.scheme, u.host].join('://')
25
+ end
26
+
27
+ # Assembles service, endpoint, extra_path, ids, and account_id into a host path
28
+ # @param [String] service title of a service
29
+ # @param [String] endpoint endpoint to make the call against
30
+ # @param [String] extra_path additional part to add to the path
31
+ # @param [String] ids comma delimited list of short id's to add to the path.
32
+ # @param [String] account_id long form account_id id (ownerId)
33
+ # @raise [ArgumentError] if service or endpoint is not supplied
34
+ # @return [String] assembled path for a data call
35
+ def path(service: nil, endpoint: nil, extra_path: nil, ids: nil, account_id: 'urn:theplatform:auth:root')
36
+ Helpers.required_arguments %i[service endpoint], binding
37
+ service = Services[service]
38
+
39
+ path = "#{URI.parse(service.url(account_id)).path}/#{service.path}/#{endpoint}"
40
+ path += "/#{extra_path}" if extra_path
41
+ path += "/feed" if service.type == 'data'
42
+ path += "/#{ids}" if ids
43
+ path
44
+ end
45
+
46
+ # Assembles service, endpoint, query, range, count, entries, sort and account_id into a query
47
+ # @param [Cts::Mpx::User] user user to make calls with
48
+ # @param [String] account_id long form account_id id (ownerId)
49
+ # @param [String] service title of a service
50
+ # @param [String] endpoint endpoint to make the call against
51
+ # @param [Hash] query any additional parameters to add
52
+ # @param [String] range string (service) format of a range.
53
+ # @param [TrueFalse] count ask for a count of objects from the services.
54
+ # @param [TrueFalse] entries return an array of entries.
55
+ # @param [String] sort set the sort field
56
+ # @raise [ArgumentError] if user, service or endpoint is not supplied
57
+ # @raise [RuntimeError] if the user token is not set
58
+ # @return [Hash] assembled query for a data call
59
+ def query(user: nil, account: nil, service: nil, endpoint: nil, query: {}, range: nil, count: nil, entries: nil, sort: nil)
60
+ Helpers.required_arguments %i[user service endpoint], binding
61
+ user.token!
62
+
63
+ service = Services[service]
64
+
65
+ h = {}
66
+ if service.type == 'data'
67
+ h.merge!(token: user.token, schema: service.schema, form: service.form)
68
+ h.merge!(query_data(range: range, count: count, entries: entries, sort: sort))
69
+ else
70
+ h.merge!(token: user.token, schema: service.endpoints[endpoint]['schema'], form: service.form)
71
+ end
72
+
73
+ h[:account] = account if account
74
+ h.delete :token if user.token == 'sign_in_token'
75
+ h.merge! query
76
+ h
77
+ end
78
+
79
+ # Assembles range, count, entries, sort into a query
80
+ # @param [String] range string (service) format of a range.
81
+ # @param [TrueFalse] count ask for a count of objects from the services.
82
+ # @param [TrueFalse] entries return an array of entries.
83
+ # @param [String] sort set the sort field
84
+ # @return [Hash] assembled query for a data call
85
+ def query_data(range: nil, count: nil, entries: nil, sort: nil)
86
+ h = {}
87
+ h.store :range, range if range
88
+ h.store :count, count if count
89
+ h.store :entries, entries if entries
90
+ h.store :sort, sort if sort
91
+ h
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,41 @@
1
+ module Cts
2
+ module Mpx
3
+ module Driver
4
+ #
5
+ # Container for active connections to the data service.
6
+ #
7
+ module Connections
8
+ module_function
9
+
10
+ #
11
+ # Addressable method for active connections. If you provide a string that is not active, an active one
12
+ # will be created.
13
+ #
14
+ # @param [String] uri uri of a service to connect to, must contain theplatform.
15
+ #
16
+ # @return [Excon] assembled excon objects with service defaults.
17
+ # @return [Excon[]] if nil, an array of all open connections.
18
+ #
19
+ def [](uri = nil)
20
+ return @open_connections unless uri
21
+ begin
22
+ parsed_uri = URI.parse uri
23
+ rescue URI::InvalidURIError
24
+ raise ArgumentError, "#{uri} is not a uri"
25
+ end
26
+
27
+ raise ArgumentError, "#{uri} does not contain theplatform in it." unless parsed_uri.host.include? "theplatform"
28
+
29
+ Excon.new([parsed_uri.scheme, parsed_uri.host].join("://"), persistent: true) unless @open_connections.include? parsed_uri.host
30
+ end
31
+
32
+ Excon.defaults[:headers] = {
33
+ 'Content-Type' => "application/json",
34
+ "User-Agent" => "cts-mpx ruby sdk version #{Cts::Mpx::VERSION}",
35
+ 'Content-Encoding' => 'bzip2,xz,gzip,deflate'
36
+ }
37
+ @open_connections = []
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,50 @@
1
+ module Cts
2
+ module Mpx
3
+ module Driver
4
+ module Exceptions
5
+ module_function
6
+
7
+ # Raise an ArgumentError if the argument does not pass Validators.account_id?
8
+ # @param [Object] argument argument to test if it is a valid account_id
9
+ # @raise [ArgumentError] if the argument is not a valid account_id
10
+ # @return [nil]
11
+ def raise_unless_account_id(argument)
12
+ raise ArgumentError, "#{argument} is not a valid account_id" unless Validators.account_id? argument
13
+ nil
14
+ end
15
+
16
+ # Raise an ArgumentError if the argument is not of the supplied type
17
+ # @param [Object] data argument to test if it is the correct type
18
+ # @param [Object] type type to test for
19
+ # @raise [ArgumentError] if the argument is not of the correct type
20
+ # @return [nil]
21
+ def raise_unless_argument_error?(data, type = nil, &block)
22
+ msg = "#{data} is not a valid #{type}"
23
+ if block
24
+ raise ArgumentError, msg unless Validators.argument_error?(data, type, &block)
25
+ elsif Validators.argument_error?(data, type, &block)
26
+ raise ArgumentError, msg
27
+ end
28
+ nil
29
+ end
30
+
31
+ # Raise an ArgumentError if the argument does not pass Validators.reference?
32
+ # @param [Object] argument argument to test if it is a valid reference
33
+ # @raise [ArgumentError] if the argument is not a valid reference
34
+ # @return [nil]
35
+ def raise_unless_reference?(argument)
36
+ raise ArgumentError, "#{argument} is not a valid reference" unless Validators.reference? argument
37
+ nil
38
+ end
39
+
40
+ # Raise an ArgumentError if the keyword is not supplied.
41
+ # @param [Object] keyword keyword to assure is supplied
42
+ # @raise [ArgumentError] if the keyword is not suppplied
43
+ # @return [nil]
44
+ def raise_unless_required_keyword?(keyword: nil)
45
+ raise ArgumentError, "#{keyword} is a required keyword." unless keyword && keyword
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,67 @@
1
+ module Cts
2
+ module Mpx
3
+ module Driver
4
+ #
5
+ # Collection of simple helpers for the development of the SDK
6
+ #
7
+ module Helpers
8
+ module_function
9
+
10
+ #
11
+ # used to raise an exception if the array of objects is not of the specified type.
12
+ #
13
+ # @param [Object[]] objects array of objects to itterate through
14
+ # @param [Class] type class to check the object array against.
15
+ #
16
+ # @raise [ArgumentError] if the argument is not of the specified type
17
+ #
18
+ # @return [nil] nil
19
+ #
20
+ def raise_if_not_a(objects, type)
21
+ objects.each { |k| Exceptions.raise_unless_argument_error?(k, type) }
22
+ nil
23
+ end
24
+
25
+ #
26
+ # Raise an error if any object in the array is not of a type Array
27
+ #
28
+ # @param [Object[]] objects array of objects to test if a valid array
29
+ #
30
+ # @raise [ArgumentError] if the argument is not an [Array]
31
+ # @return [nil] nil
32
+ #
33
+ def raise_if_not_an_array(objects)
34
+ raise_if_not_a(objects, Array)
35
+ nil
36
+ end
37
+
38
+ #
39
+ # Raise an error if any object in the array is not of a type Hash
40
+ #
41
+ # @param [Object[]] objects array of objects to test if a valid hash
42
+ #
43
+ # @raise [ArgumentError] if the argument is not a [Hash]
44
+ # @return [nil] nil
45
+ #
46
+ def raise_if_not_a_hash(objects)
47
+ raise_if_not_a(objects, Hash)
48
+ nil
49
+ end
50
+
51
+ #
52
+ # Raise an error if any keywords are not included inside of a specified binding.
53
+ #
54
+ # @param [Object] keywords list of keywords to check.
55
+ # @param [Binding] a_binding binding to check for local variables
56
+ #
57
+ # @raise [ArgumentError] if the argument is not of the specified type.
58
+ # @return [nil] nil
59
+ #
60
+ def required_arguments(keywords, a_binding)
61
+ keywords.each { |arg| Exceptions.raise_unless_required_keyword?(keyword: a_binding.local_variable_get(arg)) }
62
+ nil
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end