r2-oas 0.1.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.rubocop.yml +6 -3
  4. data/.rubocop_todo.yml +68 -1
  5. data/.travis.yml +6 -2
  6. data/Appraisals +13 -0
  7. data/CHANGELOG.md +58 -1
  8. data/GEMSPEC.md +20 -0
  9. data/README.ja.md +65 -396
  10. data/README.md +62 -392
  11. data/devscript/all_support_ruby.sh +43 -0
  12. data/devscript/bundle_for_all_support_ruby.sh +31 -0
  13. data/devscript/rspec_for_all_support_ruby.sh +27 -0
  14. data/docs/.nojekyll +0 -0
  15. data/docs/README.md +173 -0
  16. data/docs/_sidebar.md +25 -0
  17. data/docs/attention/if_clash.md +17 -0
  18. data/docs/index.html +29 -0
  19. data/docs/{versions/v3.md → schema/3.0.0.md} +1 -1
  20. data/docs/setting/COC.md +14 -0
  21. data/docs/setting/CORS.md +22 -0
  22. data/docs/setting/configure.md +176 -0
  23. data/docs/trableshouting/runtime_error.md +44 -0
  24. data/docs/{HOW_TO_ANALYZE_DOCS.md → usage/analyze_docs.md} +52 -52
  25. data/docs/usage/clean_docs.md +19 -0
  26. data/docs/{HOW_TO_DEPLOY_SWAGGER_DOC.md → usage/deploy_docs.md} +29 -29
  27. data/docs/usage/display_paths_list.md +35 -0
  28. data/docs/{HOW_TO_DISPLAY_PATHS_STATS.md → usage/display_paths_stats.md} +15 -14
  29. data/docs/{HOW_TO_START_SWAGGER_EDITOR.md → usage/edit_docs.md} +88 -88
  30. data/docs/usage/generate_docs.md +412 -0
  31. data/docs/{HOW_TO_MONITOR_SWAGGER_DOC.md → usage/monitor_docs.md} +71 -71
  32. data/docs/usage/use_hook_methods.md +236 -0
  33. data/docs/{HOW_TO_USE_HOOK_WHEN_GENERATE_DOC.md → usage/use_hook_to_generate_docs.md} +48 -57
  34. data/docs/{HOW_TO_USE_SCHEMA_NAMESPACE.md → usage/use_schema_namespace.md} +46 -41
  35. data/docs/{HOW_TO_USE_TAG_NAMESPACE.md → usage/use_tag_namespace.md} +46 -42
  36. data/docs/{HOW_TO_START_SWAGGER_UI.md → usage/view_docs.md} +132 -132
  37. data/gemfiles/ruby_2.3.3.gemfile +11 -0
  38. data/gemfiles/ruby_2.4.2.gemfile +11 -0
  39. data/gemfiles/ruby_2.5.8.gemfile +11 -0
  40. data/gemfiles/ruby_2.6.6.gemfile +11 -0
  41. data/gemfiles/ruby_2.7.1.gemfile +11 -0
  42. data/lib/r2-oas.rb +3 -4
  43. data/lib/r2-oas/app_configuration.rb +19 -16
  44. data/lib/r2-oas/deploy/client.rb +14 -2
  45. data/lib/r2-oas/errors.rb +1 -0
  46. data/lib/r2-oas/lib/core_ext/hash/deep_merge.rb +44 -0
  47. data/lib/r2-oas/lib/core_ext/object/blank.rb +135 -0
  48. data/lib/r2-oas/lib/three-way-merge/twm.rb +83 -0
  49. data/lib/r2-oas/schema/builder.rb +23 -0
  50. data/lib/r2-oas/schema/editor.rb +26 -7
  51. data/lib/r2-oas/schema/generator.rb +1 -1
  52. data/lib/r2-oas/schema/manager/file_manager.rb +26 -0
  53. data/lib/r2-oas/schema/ui.rb +0 -1
  54. data/lib/r2-oas/schema/v3/analyzer/base_analyzer.rb +1 -6
  55. data/lib/r2-oas/schema/v3/analyzer/components/object_analyzer.rb +1 -1
  56. data/lib/r2-oas/schema/v3/analyzer/path_analyzer.rb +1 -1
  57. data/lib/r2-oas/schema/v3/analyzer/tag_analyzer.rb +1 -1
  58. data/lib/r2-oas/schema/v3/builder.rb +28 -0
  59. data/lib/r2-oas/schema/v3/builder/base_builder.rb +60 -0
  60. data/lib/r2-oas/schema/v3/builder/doc_builder.rb +43 -0
  61. data/lib/r2-oas/schema/v3/cleaner/base_cleaner.rb +1 -1
  62. data/lib/r2-oas/schema/v3/generator.rb +1 -5
  63. data/lib/r2-oas/schema/v3/generator/base_generator.rb +30 -1
  64. data/lib/r2-oas/schema/v3/generator/components/object_generator.rb +6 -25
  65. data/lib/r2-oas/schema/v3/generator/components/request_body_generator.rb +6 -6
  66. data/lib/r2-oas/schema/v3/generator/doc_generator.rb +84 -18
  67. data/lib/r2-oas/schema/v3/generator/path_generator.rb +7 -19
  68. data/lib/r2-oas/schema/v3/generator/schema_generator.rb +6 -26
  69. data/lib/r2-oas/schema/v3/manager/file/base_file_manager.rb +10 -4
  70. data/lib/r2-oas/schema/v3/manager/pathname_manager.rb +6 -1
  71. data/lib/r2-oas/schema/v3/object/path_item_object.rb +17 -9
  72. data/lib/r2-oas/store.rb +118 -0
  73. data/lib/r2-oas/task_logging.rb +6 -0
  74. data/lib/r2-oas/tasks/main.rake +66 -73
  75. data/lib/r2-oas/tasks/tool.rake +25 -28
  76. data/lib/r2-oas/tool/paths/ls.rb +1 -1
  77. data/lib/r2-oas/version.rb +1 -1
  78. data/r2-oas.gemspec +20 -25
  79. metadata +122 -52
  80. data/Gemfile.lock +0 -207
  81. data/docs/HOW_TO_CLEAN_DOCS.md +0 -19
  82. data/docs/HOW_TO_DISPLAY_PATHS_LIST.md +0 -28
  83. data/docs/HOW_TO_GENERATE_DOCS.md +0 -256
@@ -24,18 +24,18 @@ module R2OAS
24
24
 
25
25
  relative_path = "#{@major_category}/#{@middle_category}/#{schema_name}"
26
26
  file_manager = ComponentsFileManager.build(relative_path, :relative)
27
- file_manager.save(result.to_yaml) unless file_manager.skip_save?
27
+ save_file_path = file_manager.save_file_path(type: :relative)
28
+ store.add(save_file_path, result.to_yaml)
28
29
 
29
30
  if data.key?('has_one') && data['has_one']['type'].eql?('schema')
30
31
  original_path = data['has_one']['original_path']
31
32
  file_manager = ComponentsFileManager.new(original_path, :ref)
32
- unless file_manager.skip_save?
33
- result = data['has_one']['data']
34
- file_manager.save(result.to_yaml)
35
- end
33
+ result = data['has_one']['data']
34
+ save_file_path = file_manager.save_file_path(type: :relative)
35
+ store.add(save_file_path, result.to_yaml)
36
36
  end
37
37
 
38
- yield file_manager.save_file_path if block_given?
38
+ yield save_file_path if block_given?
39
39
  end
40
40
  end
41
41
  end
@@ -2,6 +2,9 @@
2
2
 
3
3
  require 'yaml'
4
4
  require 'fileutils'
5
+ require 'r2-oas/errors'
6
+ require 'r2-oas/lib/three-way-merge/twm'
7
+ require 'r2-oas/schema/v3/manager/file_manager'
5
8
  require_relative 'base_generator'
6
9
  require_relative 'schema_generator'
7
10
 
@@ -9,8 +12,6 @@ module R2OAS
9
12
  module Schema
10
13
  module V3
11
14
  class DocGenerator < BaseGenerator
12
- attr_accessor :oas_doc
13
-
14
15
  def initialize(options = {})
15
16
  super
16
17
  @schema_generator = SchemaGenerator.new(options)
@@ -18,30 +19,95 @@ module R2OAS
18
19
 
19
20
  def generate_docs
20
21
  logger.info '[Generate OAS schema files] start'
21
- @schema_generator.generate_docs unless skip_generate_docs
22
+ @schema_generator.generate_docs
23
+ save_schemas_from_store
22
24
  logger.info '[Generate OAS schema files] end'
23
- logger.info '[Generate OAS docs from schema files] start'
24
- generate_docs_from_schema_files
25
- logger.info '[Generate OAS docs from schema files] end'
26
25
  end
27
26
 
28
27
  private
29
28
 
30
- def generate_docs_from_schema_files
31
- result_before_squeeze = schema_files_paths.each_with_object({}) do |path, data|
32
- yaml = YAML.load_file(path)
33
- data.deep_merge!(yaml)
34
- logger.info " Use schema file: \t#{path}"
29
+ def save_schemas_from_store
30
+ local_store = Store.new(cache_docs)
31
+
32
+ # Check checksum
33
+ unless local_store.checksum?
34
+ raise R2OAS::ChecksumError, <<-ERR
35
+
36
+ Invalid file: #{relative_cahe_docs_path}
37
+ Please delete #{relative_cahe_docs_path} and execute the following command again.
38
+
39
+ CACHE_DOCS=true bundle exec rake routes:oas:docs
40
+ ERR
41
+ end
42
+
43
+ save_diff_schemas_from(local_store)
44
+ end
45
+
46
+ def save_diff_schemas_from(local_store)
47
+ local_sha1s = local_store.data['data'].keys
48
+ global_sha1s = store.data['data'].keys
49
+
50
+ # Maake diff sha1s
51
+ new_sha1s, after_sha1s, before_sha1s = nil
52
+ if exists_cache?
53
+ after_sha1s = global_sha1s - local_sha1s
54
+ before_sha1s = local_sha1s - global_sha1s
55
+ else
56
+ new_sha1s = global_sha1s - local_sha1s
35
57
  end
36
58
 
37
- result = if many_paths_file_paths.present?
38
- Squeezer.new(result_before_squeeze, many_paths_file_paths: many_paths_file_paths).squeeze_docs
39
- else
40
- result_before_squeeze
41
- end
59
+ # Make diff store
60
+ new_store = store.dup_slice(*new_sha1s)
61
+ after_store = store.dup_slice(*after_sha1s)
62
+ before_store = local_store.dup_slice(*before_sha1s)
63
+
64
+ is_exists_cache = exists_cache?
65
+ if is_exists_cache || schema_file_do_not_exists?
66
+ unless is_create_cache
67
+ # First try
68
+ if new_store&.exists?
69
+ new_store.save do |save_path|
70
+ logger.info " Write schema file: \t#{save_path}"
71
+ end
72
+ end
73
+
74
+ # Change routing
75
+ after_store.diff_from(before_store) do |analyze_data|
76
+ analyze_data.each do |file_path, data|
77
+ left = data['after']
78
+ orig = data['before']
79
+ right = FileManager.new(file_path, :full).load_data
80
+ merged3 = Twm.yaml_merge(left, orig, right)
81
+ analyzer = Analyzer.new({}, merged3, type: :edited)
82
+ analyzer.analyze_docs
83
+ end
84
+ end
85
+
86
+ # TODO: Fix Bugs
87
+ # Delete paths/unknown.yml
88
+ file_manager = FileManager.new(unknown_paths_path, :full)
89
+ file_manager.delete
90
+ end
91
+ else
92
+ unless is_create_cache || is_exists_cache
93
+ raise NoFileExistsError, <<-ERR
42
94
 
43
- @oas_doc = result
44
- File.write(doc_save_file_path, result.to_yaml)
95
+ Can't find the file #{relative_cahe_docs_path}
96
+ Please execute the following command to create #{relative_cahe_docs_path}
97
+
98
+ CACHE_DOCS=true bundle exec rake routes:oas:docs
99
+ ERR
100
+ end
101
+ end
102
+
103
+ # Save docs cache
104
+ deflated_cache_docs = Zlib::Deflate.deflate(Marshal.dump(store.data))
105
+ IO.binwrite(abs_cache_docs_path, deflated_cache_docs)
106
+ if is_exists_cache
107
+ logger.info "[Generate OAS docs] Update cache at #{relative_cahe_docs_path}"
108
+ else
109
+ logger.info "[Generate OAS docs] Create cache at #{relative_cahe_docs_path}"
110
+ end
45
111
  end
46
112
  end
47
113
  end
@@ -17,29 +17,17 @@ module R2OAS
17
17
  end
18
18
 
19
19
  def generate_docs
20
- if paths_file_do_not_exists?
21
- logger.info ' <From routes data>'
22
- generate_docs_from_routes_data
23
- else
24
- logger.info ' <From schema files>'
25
- generate_docs_from_schema_fiels
26
- end
20
+ logger.info ' <From routes data>'
21
+ generate_docs_from_routes_data
27
22
  end
28
23
 
29
24
  private
30
25
 
31
26
  alias paths_files_paths schema_files_paths
32
- alias paths_file_do_not_exists? schema_file_do_not_exists?
33
-
34
- def generate_docs_from_schema_fiels
35
- process_when_generate_docs do |save_file_path|
36
- logger.info " Merge schema file: \t#{save_file_path}"
37
- end
38
- end
39
27
 
40
28
  def generate_docs_from_routes_data
41
29
  process_when_generate_docs do |save_file_path|
42
- logger.info " Write schema file: \t#{save_file_path}"
30
+ logger.info " Add schema file into store: \t#{save_file_path}"
43
31
  end
44
32
  end
45
33
 
@@ -47,11 +35,11 @@ module R2OAS
47
35
  logger.info ' <Update schema files (paths)>'
48
36
  save_each_tags(@paths) do |tag_name, result|
49
37
  relative_path = "paths/#{tag_name}"
50
- path_item_file_manager = PathItemFileManager.new(relative_path, :relative)
51
-
52
- path_item_file_manager.save(result.to_yaml) unless path_item_file_manager.skip_save?
38
+ file_manager = PathItemFileManager.new(relative_path, :relative)
39
+ save_file_path = file_manager.save_file_path(type: :relative)
40
+ store.add(save_file_path, result.to_yaml)
53
41
 
54
- yield path_item_file_manager.save_file_path if block_given?
42
+ yield save_file_path if block_given?
55
43
  end
56
44
  end
57
45
 
@@ -17,36 +17,15 @@ module R2OAS
17
17
  end
18
18
 
19
19
  def generate_docs
20
- if force_update_schema || schema_file_do_not_exists?
21
- logger.info '<From routes data>'
22
- generate_docs_from_routes_data
23
- else
24
- logger.info '<From schema files>'
25
- generate_docs_from_schema_fiels
26
- end
27
- end
28
-
29
- def create_docs
30
- if !skip_generate_docs
31
- super
32
- elsif skip_generate_docs && FileTest.exists?(doc_save_file_path)
33
- YAML.load_file(doc_save_file_path)
34
- else
35
- {}
36
- end
20
+ logger.info '<From routes data>'
21
+ generate_docs_from_routes_data
37
22
  end
38
23
 
39
24
  private
40
25
 
41
- def generate_docs_from_schema_fiels
42
- process_when_generate_docs do |save_file_path|
43
- logger.info " Merge schema file: \t#{save_file_path}"
44
- end
45
- end
46
-
47
26
  def generate_docs_from_routes_data
48
27
  process_when_generate_docs do |save_file_path|
49
- logger.info " Write schema file: \t#{save_file_path}"
28
+ logger.info " Add schema file into store: \t#{save_file_path}"
50
29
  end
51
30
  end
52
31
 
@@ -66,9 +45,10 @@ module R2OAS
66
45
  logger.info ' [Generate OAS schema files (components)] end'
67
46
  else
68
47
  file_manager = FileManager.new(field_name, :relative)
69
- file_manager.save(result.to_yaml)
48
+ save_file_path = file_manager.save_file_path(type: :relative)
49
+ store.add(save_file_path, result.to_yaml)
70
50
 
71
- yield file_manager.save_file_path if block_given?
51
+ yield file_manager.save_file_path(type: :relative) if block_given?
72
52
  end
73
53
  end
74
54
  end
@@ -23,6 +23,8 @@ module R2OAS
23
23
  end
24
24
 
25
25
  def save(data)
26
+ abs_dir = File.dirname(save_file_path)
27
+ FileUtils.mkdir_p(abs_dir) unless FileTest.exists?(abs_dir)
26
28
  File.write(save_file_path, data)
27
29
  end
28
30
 
@@ -31,10 +33,14 @@ module R2OAS
31
33
  save(result.to_yaml)
32
34
  end
33
35
 
34
- def save_file_path
35
- File.expand_path(@relative_save_file_path).tap do |abs_path|
36
- abs_dir = File.dirname(abs_path)
37
- FileUtils.mkdir_p(abs_dir) unless FileTest.exists?(abs_dir)
36
+ def save_file_path(type: :full)
37
+ file_path = File.expand_path(@relative_save_file_path)
38
+
39
+ case type
40
+ when :relative
41
+ file_path.sub(%r{^#{Dir.getwd}/?}, '')
42
+ else
43
+ file_path
38
44
  end
39
45
  end
40
46
 
@@ -60,7 +60,12 @@ module R2OAS
60
60
  when :ref
61
61
  "#{@path.gsub('#/', '')}.#{@ext_name}"
62
62
  when :relative
63
- "#{@path}.#{@ext_name}"
63
+ ext_name = File.extname(@path)
64
+ if ext_name.empty?
65
+ "#{@path}.#{@ext_name}"
66
+ else
67
+ @path
68
+ end
64
69
  when :full
65
70
  @path
66
71
  else
@@ -64,18 +64,26 @@ module R2OAS
64
64
 
65
65
  def responses_when_http_status
66
66
  http_statuses.each_with_object({}) do |http_status, result|
67
- result.deep_merge!(
68
- http_status => {
69
- 'description' => "#{@tag_name} description",
70
- 'content' => {
71
- 'application/json' => {
72
- 'schema' => {
73
- '$ref' => "#/components/schemas/#{_components_schema_name(http_status)}"
67
+ if ignored_http_statuses_when_generate_component_schema.include?(http_status)
68
+ result.deep_merge!(
69
+ http_status => {
70
+ 'description' => "#{@tag_name} description"
71
+ }
72
+ )
73
+ else
74
+ result.deep_merge!(
75
+ http_status => {
76
+ 'description' => "#{@tag_name} description",
77
+ 'content' => {
78
+ 'application/json' => {
79
+ 'schema' => {
80
+ '$ref' => "#/components/schemas/#{_components_schema_name(http_status)}"
81
+ }
74
82
  }
75
83
  }
76
84
  }
77
- }
78
- )
85
+ )
86
+ end
79
87
  end
80
88
  end
81
89
 
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest/sha1'
4
+ require 'zlib'
5
+
6
+ require 'r2-oas/schema/manager/file_manager'
7
+
8
+ module R2OAS
9
+ class Store
10
+ attr_accessor :data
11
+
12
+ def initialize(data = {})
13
+ if data.empty?
14
+ @data = {}
15
+ @data['type'] = :schema
16
+ @data['data'] = {}
17
+ else
18
+ @data = data
19
+ end
20
+ end
21
+
22
+ def add(key, value, type = :schema)
23
+ sha1 = calc_sha1(key, value)
24
+
25
+ @data['data'][sha1] ||= {}
26
+ @data['type'] = type
27
+ @data['data'][sha1]['key'] = key
28
+ @data['data'][sha1]['value'] = Zlib::Deflate.deflate(value)
29
+ end
30
+
31
+ def save
32
+ type = @data['type']
33
+ @data['data'].values.each do |value|
34
+ case type
35
+ when :schema
36
+ save_path = value['key']
37
+ save_data = Zlib::Inflate.inflate(value['value'])
38
+ manager = Schema::FileManager.new(save_path, :full)
39
+ manager.save(save_data)
40
+ yield save_path
41
+ end
42
+ end
43
+ end
44
+
45
+ def dup_slice(*sha1s)
46
+ dup_store = Store.new(@data.dup)
47
+ dup_data = dup_store.data['data']
48
+ dup_store.data['data'] = sha1s.each_with_object({}) { |sha1, data| data[sha1] = dup_data[sha1] if dup_store.key?(sha1) }
49
+ dup_store
50
+ end
51
+
52
+ def checksum?
53
+ @data['data'].each_with_object([]) do |(sha1, value), arr|
54
+ child_key = value['key']
55
+ child_value = Zlib::Inflate.inflate(value['value'])
56
+ arr.push(sha1.eql? calc_sha1(child_key, child_value))
57
+ end.all?
58
+ end
59
+
60
+ def key?(key)
61
+ @data['data']&.key?(key)
62
+ end
63
+
64
+ def exists?
65
+ !@data['data']&.empty?
66
+ end
67
+
68
+ def diff_from(local_store)
69
+ to_hash = adjust(values.to_h, 'after')
70
+ from_hash = adjust(local_store.send(:values).to_h, 'before')
71
+ analyze_data = to_hash.deep_merge(from_hash)
72
+ if block_given?
73
+ yield analyze_data
74
+ else
75
+ analyze_data
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ def calc_sha1(key, value)
82
+ Digest::SHA1.hexdigest("#{key}\0#{value}")
83
+ end
84
+
85
+ def values
86
+ arr = @data['data'].values
87
+ arr.each_with_object([]) do |el, result|
88
+ key = el['key']
89
+ value = el['value']
90
+ result.push([key, value])
91
+ end
92
+ end
93
+
94
+ def adjust(hash, direct)
95
+ hash.each_with_object({}) do |(key, value), result|
96
+ result[key] = { direct => {} }
97
+ result[key][direct] = YAML.safe_load(Zlib::Inflate.inflate(value))
98
+ result
99
+ end
100
+ end
101
+
102
+ class << self
103
+ extend Forwardable
104
+
105
+ def_delegators :instance, :add
106
+
107
+ def create
108
+ instance
109
+ end
110
+
111
+ private
112
+
113
+ def instance
114
+ @instance ||= new
115
+ end
116
+ end
117
+ end
118
+ end