r2-oas 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +21 -0
  3. data/.travis.yml +3 -1
  4. data/CHANGELOG.md +15 -0
  5. data/GEMSPEC.md +23 -0
  6. data/Gemfile.lock +3 -1
  7. data/README.ja.md +2 -2
  8. data/README.md +2 -2
  9. data/docs/README.md +2 -2
  10. data/docs/index.html +1 -0
  11. data/docs/setting/configure.md +13 -0
  12. data/docs/usage/analyze_docs.md +14 -14
  13. data/docs/usage/deploy_docs.md +4 -4
  14. data/docs/usage/edit_docs.md +12 -12
  15. data/docs/usage/generate_docs.md +367 -211
  16. data/docs/usage/monitor_docs.md +16 -16
  17. data/docs/usage/use_hook_to_generate_docs.md +8 -8
  18. data/docs/usage/use_schema_namespace.md +30 -32
  19. data/docs/usage/use_tag_namespace.md +24 -26
  20. data/docs/usage/view_docs.md +16 -16
  21. data/lib/r2-oas.rb +1 -0
  22. data/lib/r2-oas/errors.rb +1 -0
  23. data/lib/r2-oas/lib/three-way-merge/twm.rb +83 -0
  24. data/lib/r2-oas/schema/builder.rb +23 -0
  25. data/lib/r2-oas/schema/generator.rb +1 -1
  26. data/lib/r2-oas/schema/manager/file_manager.rb +26 -0
  27. data/lib/r2-oas/schema/v3/analyzer/base_analyzer.rb +1 -6
  28. data/lib/r2-oas/schema/v3/builder.rb +28 -0
  29. data/lib/r2-oas/schema/v3/builder/base_builder.rb +60 -0
  30. data/lib/r2-oas/schema/v3/builder/doc_builder.rb +43 -0
  31. data/lib/r2-oas/schema/v3/generator.rb +1 -5
  32. data/lib/r2-oas/schema/v3/generator/base_generator.rb +30 -1
  33. data/lib/r2-oas/schema/v3/generator/components/object_generator.rb +6 -25
  34. data/lib/r2-oas/schema/v3/generator/components/request_body_generator.rb +6 -6
  35. data/lib/r2-oas/schema/v3/generator/doc_generator.rb +84 -19
  36. data/lib/r2-oas/schema/v3/generator/path_generator.rb +7 -19
  37. data/lib/r2-oas/schema/v3/generator/schema_generator.rb +5 -25
  38. data/lib/r2-oas/schema/v3/manager/file/base_file_manager.rb +3 -4
  39. data/lib/r2-oas/schema/v3/manager/pathname_manager.rb +6 -1
  40. data/lib/r2-oas/store.rb +118 -0
  41. data/lib/r2-oas/task_logging.rb +6 -0
  42. data/lib/r2-oas/tasks/main.rake +66 -73
  43. data/lib/r2-oas/tasks/tool.rake +25 -28
  44. data/lib/r2-oas/version.rb +1 -1
  45. data/r2-oas.gemspec +9 -2
  46. metadata +40 -6
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'r2-oas/schema/v3/builder'
5
+
6
+ module R2OAS
7
+ module Schema
8
+ class Builder
9
+ extend Forwardable
10
+
11
+ def_delegators :@builder, :build_docs, :oas_doc
12
+
13
+ def initialize(options = {})
14
+ case ::R2OAS.version
15
+ when :v3
16
+ @builder = V3::Builder.new(options)
17
+ else
18
+ raise NoImplementError, "Do not support version: #{::R2OAS.version}"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -8,7 +8,7 @@ module R2OAS
8
8
  class Generator
9
9
  extend Forwardable
10
10
 
11
- def_delegators :@generator, :generate_docs, :oas_doc
11
+ def_delegators :@generator, :generate_docs
12
12
 
13
13
  def initialize(options = {})
14
14
  case ::R2OAS.version
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'r2-oas/schema/v3/manager/file_manager'
4
+
5
+ module R2OAS
6
+ module Schema
7
+ class FileManager
8
+ extend Forwardable
9
+
10
+ def_delegators :@manager, :save, :delete
11
+
12
+ def initialize(path, path_type = :ref)
13
+ case ::R2OAS.version
14
+ when :v3
15
+ @manager = V3::FileManager.new(path, path_type)
16
+ else
17
+ raise "Do not support version: #{::R2OAS.version}"
18
+ end
19
+ end
20
+
21
+ class << self
22
+ alias build new
23
+ end
24
+ end
25
+ end
26
+ end
@@ -26,14 +26,13 @@ module R2OAS
26
26
 
27
27
  private
28
28
 
29
- attr_accessor :edited_schema_file_path
30
29
  attr_accessor :existing_schema_file_path
31
30
  attr_accessor :type
32
31
 
33
32
  def create_after_schema_data
34
33
  case @type
35
34
  when :edited
36
- create_after_schema_data_when_edited
35
+ {}
37
36
  when :existing
38
37
  if existing_schema_file_path.present?
39
38
  create_after_schema_data_when_specify_path
@@ -43,10 +42,6 @@ module R2OAS
43
42
  end
44
43
  end
45
44
 
46
- def create_after_schema_data_when_edited
47
- YAML.load_file(edited_schema_file_path)
48
- end
49
-
50
45
  def create_after_schema_data_when_not_specify_path
51
46
  if FileTest.exists?(doc_save_file_path)
52
47
  YAML.load_file(doc_save_file_path)
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'forwardable'
5
+ require 'r2-oas/routing/parser'
6
+ require_relative 'builder/doc_builder'
7
+ require_relative 'builder/base_builder'
8
+
9
+ module R2OAS
10
+ module Schema
11
+ module V3
12
+ class Builder < BaseBuilder
13
+ extend Forwardable
14
+
15
+ def_delegators :@doc_builder, :oas_doc
16
+
17
+ def initialize(options = {})
18
+ super
19
+ @doc_builder = DocBuilder.new(options)
20
+ end
21
+
22
+ def build_docs
23
+ @doc_builder.build_docs
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'r2-oas/schema/v3/base'
4
+ require 'r2-oas/routing/parser'
5
+ require 'r2-oas/schema/v3/object/openapi_object'
6
+ require 'r2-oas/schema/v3/manager/file/path_item_file_manager'
7
+
8
+ module R2OAS
9
+ module Schema
10
+ module V3
11
+ class BaseBuilder < Base
12
+ include Sortable
13
+
14
+ def initialize(options = {})
15
+ super
16
+ @glob_schema_paths = create_glob_schema_paths
17
+ end
18
+
19
+ private
20
+
21
+ attr_accessor :unit_paths_file_path
22
+ attr_accessor :skip_load_dot_paths
23
+
24
+ def schema_file_do_not_exists?
25
+ schema_files_paths.count == 0
26
+ end
27
+
28
+ def create_glob_schema_paths
29
+ exclude_paths_regexp_paths = ["#{schema_save_dir_path}/**.yml"]
30
+ components_security_schemes_regexp_paths = ["#{schema_save_dir_path}/components/securitySchemes/**/**.yml"]
31
+
32
+ # components/securitySchemes is not referenced in $ ref.
33
+ exclude_paths_regexp_paths + many_paths_file_paths + many_components_file_paths + components_security_schemes_regexp_paths
34
+ end
35
+
36
+ def schema_files_paths
37
+ Dir.glob(@glob_schema_paths)
38
+ end
39
+
40
+ def many_paths_file_paths
41
+ if unit_paths_file_path.present? && !skip_load_dot_paths
42
+ [unit_paths_file_path]
43
+ elsif !unit_paths_file_path.present? && !skip_load_dot_paths && paths_config.all_load_paths?
44
+ paths_config.many_paths_file_paths
45
+ else
46
+ Dir.glob("#{schema_save_dir_path}/paths/**/**.yml")
47
+ end
48
+ end
49
+
50
+ def many_components_file_paths
51
+ @many_components_file_paths ||= many_paths_file_paths.each_with_object([]) do |unit_paths_path, result|
52
+ file_manager = PathItemFileManager.new(unit_paths_path, :full)
53
+ components_file_paths_at_path = file_manager.descendants_ref_paths
54
+ result.push(*components_file_paths_at_path)
55
+ end.uniq
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require 'fileutils'
5
+ require_relative 'base_builder'
6
+
7
+ module R2OAS
8
+ module Schema
9
+ module V3
10
+ class DocBuilder < BaseBuilder
11
+ attr_accessor :oas_doc
12
+
13
+ def build_docs
14
+ logger.info '[Build OAS schema files] start'
15
+ logger.info '[Build OAS docs from schema files] start'
16
+ build_docs_from_schema_files
17
+ logger.info '[Build OAS docs from schema files] end'
18
+ logger.info '[Build OAS schema files] end'
19
+ end
20
+
21
+ private
22
+
23
+ def build_docs_from_schema_files
24
+ result_before_squeeze = schema_files_paths.each_with_object({}) do |path, data|
25
+ file_manager = FileManager.new(path)
26
+ yaml = YAML.load_file(path)
27
+ data.deep_merge!(yaml)
28
+ logger.info " Use schema file: \t#{file_manager.save_file_path(type: :relative)}"
29
+ end
30
+
31
+ result = if many_paths_file_paths.present?
32
+ Squeezer.new(result_before_squeeze, many_paths_file_paths: many_paths_file_paths).squeeze_docs
33
+ else
34
+ result_before_squeeze
35
+ end
36
+
37
+ @oas_doc = result
38
+ File.write(doc_save_file_path, result.to_yaml)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -12,16 +12,12 @@ module R2OAS
12
12
  class Generator < BaseGenerator
13
13
  extend Forwardable
14
14
 
15
- def_delegators :@doc_generator, :oas_doc
15
+ def_delegators :@doc_generator, :generate_docs
16
16
 
17
17
  def initialize(options = {})
18
18
  super
19
19
  @doc_generator = DocGenerator.new(options)
20
20
  end
21
-
22
- def generate_docs
23
- @doc_generator.generate_docs
24
- end
25
21
  end
26
22
  end
27
23
  end
@@ -4,6 +4,7 @@ require 'r2-oas/schema/v3/base'
4
4
  require 'r2-oas/routing/parser'
5
5
  require 'r2-oas/schema/v3/object/openapi_object'
6
6
  require 'r2-oas/schema/v3/manager/file/path_item_file_manager'
7
+ require 'r2-oas/store'
7
8
 
8
9
  module R2OAS
9
10
  module Schema
@@ -13,14 +14,16 @@ module R2OAS
13
14
 
14
15
  def initialize(options = {})
15
16
  super
17
+ @store = Store.create
16
18
  @glob_schema_paths = create_glob_schema_paths
17
19
  end
18
20
 
19
21
  private
20
22
 
21
23
  attr_accessor :unit_paths_file_path
22
- attr_accessor :skip_generate_docs
23
24
  attr_accessor :skip_load_dot_paths
25
+ attr_accessor :is_create_cache
26
+ attr_accessor :store
24
27
 
25
28
  # Scope Rails
26
29
  def create_docs
@@ -82,6 +85,32 @@ module R2OAS
82
85
  def exists_paths_files?
83
86
  Dir.glob("#{schema_save_dir_path}/paths/**/**.yml").present?
84
87
  end
88
+
89
+ def cache_docs
90
+ if exists_cache?
91
+ result = IO.binread(abs_cache_docs_path)
92
+ inflate = Zlib::Inflate.inflate(result)
93
+ @cache_docs ||= Marshal.load(inflate)
94
+ else
95
+ @cache_docs ||= {}
96
+ end
97
+ end
98
+
99
+ def exists_cache?
100
+ FileTest.exists?(abs_cache_docs_path)
101
+ end
102
+
103
+ def abs_cache_docs_path
104
+ File.expand_path(relative_cahe_docs_path)
105
+ end
106
+
107
+ def relative_cahe_docs_path
108
+ "#{@root_dir_path}/.docs"
109
+ end
110
+
111
+ def unknown_paths_path
112
+ "#{@root_dir_path}/src/paths/unknown.yml"
113
+ end
85
114
  end
86
115
  end
87
116
  end
@@ -20,37 +20,17 @@ module R2OAS
20
20
  end
21
21
 
22
22
  def generate_docs
23
- if components_objects_file_do_not_exists?
24
- logger.info ' <From routes data>'
25
- generate_docs_from_routes_data
26
- else
27
- logger.info ' <From schema files>'
28
- generate_docs_from_schema_fiels
29
- end
23
+ logger.info ' <From routes data>'
24
+ generate_docs_from_routes_data
30
25
  end
31
26
 
32
27
  private
33
28
 
34
29
  alias components_objects_files_paths schema_files_paths
35
- alias components_objects_file_do_not_exists? schema_file_do_not_exists?
36
-
37
- def generate_docs_from_schema_fiels
38
- components_schemas_from_schema_files = components_objects_files_paths.each_with_object({}) do |path, data|
39
- yaml = YAML.load_file(path)
40
- data.deep_merge!(yaml)
41
- full_path = File.expand_path(path, './')
42
- logger.info " Fetch Components schema file: \t#{full_path}"
43
- end
44
- @components_objects.deep_merge!(components_schemas_from_schema_files[@major_category][@middle_category])
45
-
46
- process_when_generate_docs do |save_file_path|
47
- logger.info " Merge schema file: \t#{save_file_path}"
48
- end
49
- end
50
30
 
51
31
  def generate_docs_from_routes_data
52
32
  process_when_generate_docs do |save_file_path|
53
- logger.info " Write schema file: \t#{save_file_path}"
33
+ logger.info " Add schema file into store: \t#{save_file_path}"
54
34
  end
55
35
  end
56
36
 
@@ -65,9 +45,10 @@ module R2OAS
65
45
 
66
46
  relative_path = "#{@major_category}/#{@middle_category}/#{schema_name}"
67
47
  file_manager = ComponentsFileManager.build(relative_path, :relative)
68
- file_manager.save(result.to_yaml) unless file_manager.skip_save?
48
+ save_file_path = file_manager.save_file_path(type: :relative)
49
+ store.add(save_file_path, result.to_yaml)
69
50
 
70
- yield file_manager.save_file_path(type: :relative) if block_given?
51
+ yield save_file_path if block_given?
71
52
  end
72
53
  end
73
54
 
@@ -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(type: :relative) 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,31 +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
- file_manager = FileManager.new(path)
33
- yaml = YAML.load_file(path)
34
- data.deep_merge!(yaml)
35
- logger.info " Use schema file: \t#{file_manager.save_file_path(type: :relative)}"
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
36
57
  end
37
58
 
38
- result = if many_paths_file_paths.present?
39
- Squeezer.new(result_before_squeeze, many_paths_file_paths: many_paths_file_paths).squeeze_docs
40
- else
41
- result_before_squeeze
42
- 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
43
94
 
44
- @oas_doc = result
45
- 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
46
111
  end
47
112
  end
48
113
  end