typekit-client 0.0.5 → 0.0.6

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -3
  3. data/.travis.yml +4 -0
  4. data/.yardopts +6 -0
  5. data/CHANGELOG.md +12 -0
  6. data/Guardfile +21 -3
  7. data/README.md +253 -248
  8. data/bin/typekit-client +16 -16
  9. data/bin/typekit-publisher +6 -5
  10. data/lib/typekit.rb +6 -2
  11. data/lib/typekit/client.rb +66 -24
  12. data/lib/typekit/collection.rb +6 -11
  13. data/lib/typekit/collection/base.rb +40 -0
  14. data/lib/typekit/collection/serialization.rb +17 -0
  15. data/lib/typekit/converter.rb +26 -0
  16. data/lib/typekit/converter/boolean.rb +12 -0
  17. data/lib/typekit/converter/collection.rb +13 -0
  18. data/lib/typekit/converter/datetime.rb +12 -0
  19. data/lib/typekit/converter/element.rb +13 -0
  20. data/lib/typekit/converter/errors.rb +12 -0
  21. data/lib/typekit/converter/unknown.rb +13 -0
  22. data/lib/typekit/core.rb +8 -10
  23. data/lib/typekit/element.rb +27 -0
  24. data/lib/typekit/element/association.rb +63 -0
  25. data/lib/typekit/element/base.rb +61 -0
  26. data/lib/typekit/element/persistence.rb +61 -0
  27. data/lib/typekit/element/query.rb +25 -0
  28. data/lib/typekit/element/serialization.rb +17 -0
  29. data/lib/typekit/error.rb +23 -0
  30. data/lib/typekit/helper.rb +59 -10
  31. data/lib/typekit/record.rb +18 -22
  32. data/lib/typekit/record/family.rb +24 -1
  33. data/lib/typekit/record/kit.rb +29 -1
  34. data/lib/typekit/record/library.rb +4 -1
  35. data/lib/typekit/record/variation.rb +13 -1
  36. data/lib/typekit/version.rb +1 -1
  37. data/spec/feature/create_kit_spec.rb +52 -0
  38. data/spec/feature/delete_kit_spec.rb +33 -0
  39. data/spec/feature/index_kits_spec.rb +55 -0
  40. data/spec/feature/publish_kit_spec.rb +15 -0
  41. data/spec/feature/show_family_spec.rb +75 -0
  42. data/spec/feature/show_kit_spec.rb +56 -0
  43. data/spec/feature/show_library_spec.rb +29 -0
  44. data/spec/feature/show_variation_spec.rb +18 -0
  45. data/spec/feature/update_kit_spec.rb +88 -0
  46. data/spec/fixture/cassette/create_kits_bad.yml +16 -0
  47. data/spec/fixture/cassette/create_kits_ok.yml +16 -0
  48. data/spec/fixture/cassette/delete_kits_xxx_not_found.yml +13 -0
  49. data/spec/{cassettes → fixture/cassette}/delete_kits_xxx_ok.yml +0 -3
  50. data/spec/fixture/cassette/index_kits_show_kit_xxx_ok.yml +25 -0
  51. data/spec/{cassettes → fixture/cassette}/index_kits_unauthorized.yml +0 -3
  52. data/spec/{cassettes → fixture/cassette}/show_families_xxx_found.yml +0 -3
  53. data/spec/{cassettes → fixture/cassette}/show_families_xxx_ok.yml +0 -3
  54. data/spec/{cassettes → fixture/cassette}/show_families_xxx_yyy_ok.yml +0 -3
  55. data/spec/fixture/cassette/show_families_yyy_update_kits_xxx_families_ok.yml +35 -0
  56. data/spec/fixture/cassette/show_kits_xxx_families_yyy_show_family_yyy_ok.yml +45 -0
  57. data/spec/fixture/cassette/show_kits_xxx_not_found.yml +13 -0
  58. data/spec/fixture/cassette/show_kits_xxx_show_family_yyy_ok.yml +46 -0
  59. data/spec/{cassettes → fixture/cassette}/show_libraries_xxx_ok.yml +0 -3
  60. data/spec/fixture/cassette/update_kits_xxx_empty_families_ok.yml +16 -0
  61. data/spec/fixture/cassette/update_kits_xxx_families_ok.yml +18 -0
  62. data/spec/fixture/cassette/update_kits_xxx_families_variations_ok.yml +18 -0
  63. data/spec/fixture/cassette/update_kits_xxx_name_ok.yml +17 -0
  64. data/spec/fixture/cassette/update_kits_xxx_publish_ok.yml +16 -0
  65. data/spec/fixture/record/article.rb +11 -0
  66. data/spec/fixture/record/section.rb +10 -0
  67. data/spec/lib/typekit/collection_spec.rb +22 -0
  68. data/spec/{typekit/processing → lib/typekit}/converter_spec.rb +13 -13
  69. data/spec/lib/typekit/element/association_spec.rb +96 -0
  70. data/spec/lib/typekit/element/base_spec.rb +70 -0
  71. data/spec/lib/typekit/element/persistence_spec.rb +97 -0
  72. data/spec/lib/typekit/element/serialization_spec.rb +28 -0
  73. data/spec/lib/typekit/element_spec.rb +58 -0
  74. data/spec/{typekit → lib/typekit}/helper_spec.rb +6 -8
  75. data/spec/lib/typekit/record_spec.rb +57 -0
  76. data/spec/spec_helper.rb +10 -3
  77. data/spec/support/common_helper.rb +5 -0
  78. data/spec/support/record_helper.rb +38 -0
  79. data/typekit-client.gemspec +11 -4
  80. metadata +164 -58
  81. data/lib/typekit/processing.rb +0 -8
  82. data/lib/typekit/processing/converter.rb +0 -28
  83. data/lib/typekit/processing/converter/boolean.rb +0 -14
  84. data/lib/typekit/processing/converter/collection.rb +0 -18
  85. data/lib/typekit/processing/converter/datetime.rb +0 -14
  86. data/lib/typekit/processing/converter/errors.rb +0 -24
  87. data/lib/typekit/processing/converter/record.rb +0 -16
  88. data/lib/typekit/processing/converter/unknown.rb +0 -15
  89. data/lib/typekit/processing/translator.rb +0 -13
  90. data/lib/typekit/record/base.rb +0 -52
  91. data/spec/cassettes/index_kits_ok.yml +0 -16
  92. data/spec/cassettes/show_kits_xxx_families_yyy_ok.yml +0 -16
  93. data/spec/cassettes/show_kits_xxx_ok.yml +0 -17
  94. data/spec/features/client/delete_kit_spec.rb +0 -13
  95. data/spec/features/client/index_kits_spec.rb +0 -25
  96. data/spec/features/client/show_family_spec.rb +0 -47
  97. data/spec/features/client/show_kit_spec.rb +0 -18
  98. data/spec/features/client/show_library_spec.rb +0 -18
  99. data/spec/features/client/show_variation_spec.rb +0 -22
  100. data/spec/support/resource_helper.rb +0 -34
  101. data/spec/typekit/record/base_spec.rb +0 -85
  102. data/spec/typekit/record_spec.rb +0 -80
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
 
5
6
  require 'typekit'
6
7
  require 'readline'
@@ -11,42 +12,41 @@ class Controller
11
12
  ACTIONS = %w{index show create update delete}
12
13
  KEYWORDS = %w{families kits libraries published publish}
13
14
 
14
- def initialize(**options)
15
- @client = Typekit::Client.new(**options)
15
+ def initialize(options)
16
+ @client = Typekit::Client.new(options)
16
17
  end
17
18
 
18
19
  def process(command)
19
20
  action, path, parameters = parse(command)
20
- print @client.perform(action, path, parameters)
21
+ print @client.process(action, path, parameters)
21
22
  rescue Exception => e
22
23
  puts e
23
24
  end
24
25
 
25
26
  def help
26
27
  puts <<-HELP
27
- Usage: <action> <resource> [parameters]
28
+ Usage: <action> <endpoint> [parameters]
28
29
 
29
30
  <action> index, show, create, update, or delete
30
- <resource> a list separated by whitespaces
31
+ <endpoint> a list separated by whitespaces
31
32
  [parameters] a JSON-encoded hash (optional)
32
33
 
33
34
  Examples:
34
35
  index kits
35
- show kits bas4cfe families vcsm
36
- show families vcsm i9
37
- show libraries trial { "page": 10, "per_page": 5 }
38
- create kits { "name": "Megakit", "domains": "localhost" }
39
- update kits bas4cfe { "name": "Ultrakit" }
36
+ create kits { "name": "Megakit", domains: ["localhost"] }
37
+ show kits bas4cfe
38
+ update kits bas4cfe { families: [{ "id": "vybr" }] }
39
+ update kits bas4cfe publish
40
40
  delete kits bas4cfe
41
+ show families vybr i4
42
+ show libraries trial { "page": 10, "per_page": 5 }
41
43
  HELP
42
44
  end
43
45
 
44
46
  protected
45
47
 
46
48
  def print(output)
47
- puts JSON.pretty_generate(output)
48
- rescue JSON::GeneratorError
49
- puts output.to_s # neither hash nor array
49
+ puts JSON.pretty_generate(output, quirks_mode: true)
50
50
  end
51
51
 
52
52
  def parse(command)
@@ -59,7 +59,7 @@ HELP
59
59
  raise 'Invalid action name' unless ACTIONS.include?(action)
60
60
  raise 'Missing resource name' if path.empty?
61
61
 
62
- [ action, path, parameters ]
62
+ [action, path, parameters]
63
63
  end
64
64
 
65
65
  def extract_parameters!(command)
@@ -132,7 +132,7 @@ puts %{Type 'help' for help and 'exit' to exit.}
132
132
 
133
133
  COMMANDS = Controller::ACTIONS + Controller::KEYWORDS + %w{help exit}
134
134
  Readline.completion_proc = proc do |input|
135
- COMMANDS.grep(/^#{ Regexp.escape(input) }/)
135
+ COMMANDS.grep(/^#{Regexp.escape(input)}/)
136
136
  end
137
137
 
138
138
  loop do
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
 
5
6
  require 'typekit'
6
7
  require 'readline'
@@ -59,9 +60,9 @@ kits = process(:index, :kits)
59
60
 
60
61
  puts 'Which kit would you like to publish?'
61
62
  kits.each_with_index do |kit, i|
62
- puts "%4d. %s" % [ i + 1, kit.id ]
63
+ puts "%4d. %s" % [i + 1, kit.id]
63
64
  end
64
- puts "%4d. all" % [ kits.length + 1 ]
65
+ puts "%4d. all" % [kits.length + 1]
65
66
 
66
67
  k = Readline.readline('> ')
67
68
  if k.nil? || k.empty?
@@ -76,10 +77,10 @@ if k < 1 || k > kits.length + 1
76
77
  exit
77
78
  end
78
79
 
79
- range = k == kits.length + 1 ? 0...kits.length : [ k - 1 ]
80
+ range = k == kits.length + 1 ? 0...kits.length : [k - 1]
80
81
 
81
82
  range.each do |i|
82
- print "Publishing #{ kits[i].id }..."
83
+ print "Publishing #{kits[i].id}..."
83
84
  process(:update, :kits, kits[i].id, :publish)
84
85
  puts ' Done.'
85
86
  end
@@ -2,12 +2,16 @@ require 'forwardable'
2
2
  require 'apitizer'
3
3
 
4
4
  require_relative 'typekit/core'
5
+ require_relative 'typekit/error'
5
6
  require_relative 'typekit/helper'
6
7
 
7
- require_relative 'typekit/processing'
8
+ require_relative 'typekit/converter'
8
9
 
10
+ require_relative 'typekit/client'
11
+
12
+ require_relative 'typekit/element'
9
13
  require_relative 'typekit/collection'
14
+
10
15
  require_relative 'typekit/record'
11
- require_relative 'typekit/client'
12
16
 
13
17
  require_relative 'typekit/version'
@@ -1,40 +1,82 @@
1
1
  module Typekit
2
- class Client
3
- extend Forwardable
2
+ module Client
3
+ def self.new(options)
4
+ raise Error, 'Token is missing' unless options.key?(:token)
4
5
 
5
- def_delegator :translator, :process, :translate
6
+ client = Module.new
7
+ client.extend(InstanceMethods)
8
+ client.configure(Typekit.defaults.merge(options))
6
9
 
7
- def initialize(**options)
8
- @options = Typekit.defaults.merge(options)
9
- raise Error, 'Token is missing' unless @options.key?(:token)
10
+ client
10
11
  end
11
12
 
12
- [ :process, :index, :show, :create, :update, :delete ].each do |method|
13
- define_method(method) do |*arguments|
14
- translate(engine.send(method, *arguments))
13
+ module InstanceMethods
14
+ [:process, :index, :show, :create, :update, :delete].each do |method|
15
+ define_method(method) do |*arguments|
16
+ translate(engine.send(method, *arguments))
17
+ end
15
18
  end
16
- end
17
- alias_method :perform, :process
18
19
 
19
- private
20
+ def configure(options)
21
+ self.options = options
22
+ end
20
23
 
21
- def engine
22
- @engine ||= build_engine
23
- end
24
+ private
25
+
26
+ attr_accessor :options
27
+
28
+ def engine
29
+ @engine ||= build_engine
30
+ end
31
+
32
+ def build_engine
33
+ engine_options = options.merge(dictionary: Typekit.dictionary,
34
+ headers: Typekit.headers.call(options[:token]))
35
+
36
+ version = options[:version]
37
+ format = options[:format]
38
+
39
+ Apitizer::Base.new(engine_options) do
40
+ instance_exec(version, format, &Typekit.schema)
41
+ end
42
+ end
24
43
 
25
- def translator
26
- @translator ||= Processing::Translator.new
44
+ def translate(result)
45
+ unless result.is_a?(Hash) && result.length == 1
46
+ raise ServerError.new(result.code)
47
+ end
48
+ name, object = *result.first
49
+ converter(name).process(result, object)
50
+ end
51
+
52
+ def const_missing(name)
53
+ record_class(name)
54
+ end
55
+
56
+ def converter(name)
57
+ (@converters ||= {})[name] ||= Converter.build(name, self)
58
+ end
59
+
60
+ def record_class(name)
61
+ (@record_classes ||= {})[name] ||= Record.build(name, self)
62
+ end
27
63
  end
28
64
 
29
- def build_engine
30
- version = @options[:version]
31
- format = @options[:format]
65
+ module Proxy
66
+ attr_reader :client, :token
67
+
68
+ def connect(object = nil, token = Helper.tokenize(self.class))
69
+ self.client = object.respond_to?(:client) ? object.client : object
70
+ self.token = token
71
+ end
72
+
73
+ private
32
74
 
33
- options = @options.merge(dictionary: Typekit.dictionary,
34
- headers: Typekit.headers.call(@options[:token]))
75
+ attr_writer :client, :token
35
76
 
36
- Apitizer::Base.new(**options) do
37
- instance_exec(version, format, &Typekit.schema)
77
+ def process(action, *arguments)
78
+ raise Error, 'Client is not specified' if client.nil?
79
+ client.process(action, token, *arguments)
38
80
  end
39
81
  end
40
82
  end
@@ -1,15 +1,10 @@
1
- module Typekit
2
- class Collection
3
- extend Forwardable
4
-
5
- def_delegator :@records, :to_json
6
- def_delegators :@records, :each, :map, :[], :size, :length
1
+ require_relative 'collection/serialization'
2
+ require_relative 'collection/base'
7
3
 
8
- def initialize(name, collection_attributes = nil)
9
- @klass = Record.classify(name)
10
- @records = collection_attributes.map do |attributes|
11
- @klass.new(attributes)
12
- end
4
+ module Typekit
5
+ module Collection
6
+ def self.build(name, *arguments)
7
+ Base.new(name, *arguments)
13
8
  end
14
9
  end
15
10
  end
@@ -0,0 +1,40 @@
1
+ module Typekit
2
+ module Collection
3
+ class Base
4
+ extend Forwardable
5
+ include Enumerable
6
+
7
+ include Client::Proxy
8
+
9
+ include Serialization
10
+
11
+ def_delegators :elements, :to_ary, :to_a, :to_json,
12
+ :[], :each, :size, :length, :empty?, :delete
13
+ def_delegator :klass, :feature?
14
+
15
+ def initialize(name, *arguments)
16
+ objects = Helper.extract_array!(arguments)
17
+
18
+ @elements = []
19
+ @klass = Element.classify(name)
20
+ connect(arguments.first, name)
21
+
22
+ objects.each { |object| push(object) }
23
+ end
24
+
25
+ def push(object)
26
+ if object.is_a?(klass)
27
+ object.connect(self)
28
+ elements << object
29
+ else
30
+ elements << klass.new(self, object)
31
+ end
32
+ end
33
+ alias_method :<<, :push
34
+
35
+ private
36
+
37
+ attr_reader :elements, :klass
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,17 @@
1
+ module Typekit
2
+ module Collection
3
+ module Serialization
4
+ def serialize
5
+ result = nil
6
+
7
+ if klass.feature?(:serialization)
8
+ result = elements.map(&:serialize)
9
+ # FIXME: A nasty hack to empty collections.
10
+ result = '' if result.empty?
11
+ end
12
+
13
+ result
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'converter/element'
2
+ require_relative 'converter/collection'
3
+ require_relative 'converter/boolean'
4
+ require_relative 'converter/datetime'
5
+ require_relative 'converter/errors'
6
+ require_relative 'converter/unknown'
7
+
8
+ module Typekit
9
+ module Converter
10
+ MAPPING = {
11
+ :element => Element,
12
+ :collection => Collection,
13
+
14
+ 'ok' => Boolean,
15
+ 'errors' => Errors,
16
+ 'published' => DateTime,
17
+
18
+ nil => Errors
19
+ }
20
+ MAPPING.default = Unknown
21
+
22
+ def self.build(name, *arguments)
23
+ MAPPING[Record.identify(name) || name].new(name, *arguments)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ module Typekit
2
+ module Converter
3
+ class Boolean
4
+ def initialize(*)
5
+ end
6
+
7
+ def process(result, object)
8
+ object # already boolean
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Typekit
2
+ module Converter
3
+ class Collection
4
+ def initialize(*arguments)
5
+ @arguments = arguments
6
+ end
7
+
8
+ def process(result, collection_attributes)
9
+ Typekit::Collection.build(*@arguments, collection_attributes)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Typekit
2
+ module Converter
3
+ class DateTime
4
+ def initialize(*)
5
+ end
6
+
7
+ def process(result, object)
8
+ ::DateTime.parse(object)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Typekit
2
+ module Converter
3
+ class Element
4
+ def initialize(*arguments)
5
+ @arguments = arguments
6
+ end
7
+
8
+ def process(result, attributes)
9
+ Typekit::Element.build(*@arguments, attributes)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Typekit
2
+ module Converter
3
+ class Errors
4
+ def initialize(*)
5
+ end
6
+
7
+ def process(result, errors)
8
+ raise ServerError.new(result.code, Array(errors).join(', '))
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Typekit
2
+ module Converter
3
+ class Unknown
4
+ def initialize(name, *)
5
+ @name = name
6
+ end
7
+
8
+ def process(result, object)
9
+ { @name => object }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,25 +1,23 @@
1
1
  module Typekit
2
- Error = Class.new(StandardError)
3
-
4
2
  @defaults = { version: 1, format: :json }
5
3
 
6
4
  @schema = Proc.new do |version, format|
7
- address "https://typekit.com/api/v#{ version }/#{ format }"
8
-
9
- resources :families, only: :show do
10
- show ':variation', on: :member
11
- end
5
+ address "https://typekit.com/api/v#{version}/#{format}"
12
6
 
13
7
  resources :kits do
14
- resources :families, only: [ :show, :update, :delete ]
8
+ resources :families, only: [:show, :update, :delete]
15
9
  show :published, on: :member
16
10
  update :publish, on: :member
17
11
  end
18
12
 
19
- resources :libraries, only: [ :index, :show ]
13
+ resources :families, only: :show do
14
+ show ':variation', on: :member
15
+ end
16
+
17
+ resources :libraries, only: [:index, :show]
20
18
  end
21
19
 
22
- @dictionary = { :update => :post } # not PUT
20
+ @dictionary = { :update => :post } # not PATCH
23
21
 
24
22
  @headers = Proc.new do |token|
25
23
  { 'X-Typekit-Token' => token }