r2-oas 0.4.0

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 (136) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +99 -0
  3. data/GEMSPEC.md +20 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.ja.md +271 -0
  6. data/README.md +271 -0
  7. data/lib/r2-oas.rb +35 -0
  8. data/lib/r2-oas/app_configuration.rb +121 -0
  9. data/lib/r2-oas/app_configuration/deprecation.rb +28 -0
  10. data/lib/r2-oas/app_configuration/server.rb +35 -0
  11. data/lib/r2-oas/app_configuration/swagger.rb +35 -0
  12. data/lib/r2-oas/app_configuration/swagger/editor.rb +47 -0
  13. data/lib/r2-oas/app_configuration/swagger/ui.rb +45 -0
  14. data/lib/r2-oas/app_configuration/tool.rb +31 -0
  15. data/lib/r2-oas/app_configuration/tool/paths/stats.rb +43 -0
  16. data/lib/r2-oas/base.rb +48 -0
  17. data/lib/r2-oas/configuration.rb +121 -0
  18. data/lib/r2-oas/configuration/paths_config.rb +44 -0
  19. data/lib/r2-oas/deploy/client.rb +70 -0
  20. data/lib/r2-oas/deploy/swagger-ui/index.html.erb +60 -0
  21. data/lib/r2-oas/dynamic/schema/v3/object/from_routes/hookable_base_object.rb +100 -0
  22. data/lib/r2-oas/errors.rb +13 -0
  23. data/lib/r2-oas/hooks/global_hook.rb +20 -0
  24. data/lib/r2-oas/hooks/hook.rb +79 -0
  25. data/lib/r2-oas/hooks/repository.rb +15 -0
  26. data/lib/r2-oas/lib/core_ext/hash/deep_merge.rb +44 -0
  27. data/lib/r2-oas/lib/core_ext/object/blank.rb +135 -0
  28. data/lib/r2-oas/lib/three-way-merge/twm.rb +83 -0
  29. data/lib/r2-oas/logger/stdout_logger.rb +129 -0
  30. data/lib/r2-oas/pluggable_configuration.rb +36 -0
  31. data/lib/r2-oas/plugin/base.rb +44 -0
  32. data/lib/r2-oas/plugin/executor.rb +148 -0
  33. data/lib/r2-oas/plugin/hookable.rb +42 -0
  34. data/lib/r2-oas/plugin/public.rb +3 -0
  35. data/lib/r2-oas/plugin/transform/transform.rb +10 -0
  36. data/lib/r2-oas/plugin/transform/v3/transform.rb +20 -0
  37. data/lib/r2-oas/plugin/transform/v3/visitable.rb +37 -0
  38. data/lib/r2-oas/public.rb +5 -0
  39. data/lib/r2-oas/routing/adjustor.rb +44 -0
  40. data/lib/r2-oas/routing/base.rb +12 -0
  41. data/lib/r2-oas/routing/components/all.rb +5 -0
  42. data/lib/r2-oas/routing/components/base_component.rb +10 -0
  43. data/lib/r2-oas/routing/components/path_component.rb +67 -0
  44. data/lib/r2-oas/routing/components/request_component.rb +75 -0
  45. data/lib/r2-oas/routing/components/verb_component.rb +21 -0
  46. data/lib/r2-oas/routing/parser.rb +93 -0
  47. data/lib/r2-oas/schema/analyzer.rb +23 -0
  48. data/lib/r2-oas/schema/base.rb +11 -0
  49. data/lib/r2-oas/schema/builder.rb +23 -0
  50. data/lib/r2-oas/schema/cleaner.rb +23 -0
  51. data/lib/r2-oas/schema/editor.rb +146 -0
  52. data/lib/r2-oas/schema/generator.rb +23 -0
  53. data/lib/r2-oas/schema/manager/file/path_item_file_manager.rb +24 -0
  54. data/lib/r2-oas/schema/manager/file_manager.rb +26 -0
  55. data/lib/r2-oas/schema/monitor.rb +52 -0
  56. data/lib/r2-oas/schema/squeezer.rb +23 -0
  57. data/lib/r2-oas/schema/ui.rb +73 -0
  58. data/lib/r2-oas/schema/v3/analyzer.rb +58 -0
  59. data/lib/r2-oas/schema/v3/analyzer/base_analyzer.rb +71 -0
  60. data/lib/r2-oas/schema/v3/analyzer/components/object_analyzer.rb +38 -0
  61. data/lib/r2-oas/schema/v3/analyzer/components_analyzer.rb +30 -0
  62. data/lib/r2-oas/schema/v3/analyzer/path_analyzer.rb +116 -0
  63. data/lib/r2-oas/schema/v3/analyzer/tag_analyzer.rb +38 -0
  64. data/lib/r2-oas/schema/v3/base.rb +28 -0
  65. data/lib/r2-oas/schema/v3/builder.rb +28 -0
  66. data/lib/r2-oas/schema/v3/builder/base_builder.rb +72 -0
  67. data/lib/r2-oas/schema/v3/builder/doc_builder.rb +51 -0
  68. data/lib/r2-oas/schema/v3/cleaner.rb +19 -0
  69. data/lib/r2-oas/schema/v3/cleaner/base_cleaner.rb +30 -0
  70. data/lib/r2-oas/schema/v3/cleaner/components_cleaner.rb +42 -0
  71. data/lib/r2-oas/schema/v3/generator.rb +24 -0
  72. data/lib/r2-oas/schema/v3/generator/base_generator.rb +122 -0
  73. data/lib/r2-oas/schema/v3/generator/components/object_generator.rb +64 -0
  74. data/lib/r2-oas/schema/v3/generator/components/request_body_generator.rb +45 -0
  75. data/lib/r2-oas/schema/v3/generator/components_generator.rb +38 -0
  76. data/lib/r2-oas/schema/v3/generator/doc_generator.rb +115 -0
  77. data/lib/r2-oas/schema/v3/generator/path_generator.rb +78 -0
  78. data/lib/r2-oas/schema/v3/generator/schema_generator.rb +58 -0
  79. data/lib/r2-oas/schema/v3/manager/diff/base_array_diff_manager.rb +60 -0
  80. data/lib/r2-oas/schema/v3/manager/diff/base_diff_manager.rb +29 -0
  81. data/lib/r2-oas/schema/v3/manager/diff/base_hash_diff_manager.rb +95 -0
  82. data/lib/r2-oas/schema/v3/manager/diff/components_diff_manager.rb +19 -0
  83. data/lib/r2-oas/schema/v3/manager/diff/tag_diff_manager.rb +17 -0
  84. data/lib/r2-oas/schema/v3/manager/file/base_file_manager.rb +66 -0
  85. data/lib/r2-oas/schema/v3/manager/file/components_file_manager.rb +22 -0
  86. data/lib/r2-oas/schema/v3/manager/file/include_ref_base_file_manager.rb +89 -0
  87. data/lib/r2-oas/schema/v3/manager/file/path_item_file_manager.rb +22 -0
  88. data/lib/r2-oas/schema/v3/manager/file_manager.rb +12 -0
  89. data/lib/r2-oas/schema/v3/manager/pathname_manager.rb +78 -0
  90. data/lib/r2-oas/schema/v3/object/from_files/base_object.rb +62 -0
  91. data/lib/r2-oas/schema/v3/object/from_files/components/request_body_object.rb +103 -0
  92. data/lib/r2-oas/schema/v3/object/from_files/components/schema_object.rb +102 -0
  93. data/lib/r2-oas/schema/v3/object/from_files/components_object.rb +46 -0
  94. data/lib/r2-oas/schema/v3/object/from_files/external_document_object.rb +23 -0
  95. data/lib/r2-oas/schema/v3/object/from_files/info_object.rb +23 -0
  96. data/lib/r2-oas/schema/v3/object/from_files/openapi_object.rb +61 -0
  97. data/lib/r2-oas/schema/v3/object/from_files/path_item_object.rb +110 -0
  98. data/lib/r2-oas/schema/v3/object/from_files/paths_object.rb +33 -0
  99. data/lib/r2-oas/schema/v3/object/from_files/utils/all.rb +4 -0
  100. data/lib/r2-oas/schema/v3/object/from_files/utils/deep_methods.rb +27 -0
  101. data/lib/r2-oas/schema/v3/object/from_files/utils/refs.rb +151 -0
  102. data/lib/r2-oas/schema/v3/object/from_routes/base_object.rb +75 -0
  103. data/lib/r2-oas/schema/v3/object/from_routes/components/request_body_object.rb +96 -0
  104. data/lib/r2-oas/schema/v3/object/from_routes/components/schema_object.rb +59 -0
  105. data/lib/r2-oas/schema/v3/object/from_routes/components_object.rb +81 -0
  106. data/lib/r2-oas/schema/v3/object/from_routes/external_document_object.rb +28 -0
  107. data/lib/r2-oas/schema/v3/object/from_routes/info_object.rb +43 -0
  108. data/lib/r2-oas/schema/v3/object/from_routes/openapi_object.rb +59 -0
  109. data/lib/r2-oas/schema/v3/object/from_routes/path_item_object.rb +175 -0
  110. data/lib/r2-oas/schema/v3/object/from_routes/paths_object.rb +77 -0
  111. data/lib/r2-oas/schema/v3/object/from_routes/public.rb +9 -0
  112. data/lib/r2-oas/schema/v3/object/from_routes/server_object.rb +21 -0
  113. data/lib/r2-oas/schema/v3/object/from_routes/tag_object.rb +37 -0
  114. data/lib/r2-oas/schema/v3/object/store.rb +54 -0
  115. data/lib/r2-oas/schema/v3/squeezer.rb +29 -0
  116. data/lib/r2-oas/schema/v3/squeezer/base_squeezer.rb +37 -0
  117. data/lib/r2-oas/schema/v3/squeezer/path_squeezer.rb +28 -0
  118. data/lib/r2-oas/schema/v3/squeezer/tag_squeezer.rb +19 -0
  119. data/lib/r2-oas/shared/all.rb +4 -0
  120. data/lib/r2-oas/shared/callable.rb +17 -0
  121. data/lib/r2-oas/shared/sortable.rb +23 -0
  122. data/lib/r2-oas/store.rb +122 -0
  123. data/lib/r2-oas/support/deprecation.rb +24 -0
  124. data/lib/r2-oas/support/deprecation/behavior.rb +21 -0
  125. data/lib/r2-oas/support/deprecation/instance_delegator.rb +42 -0
  126. data/lib/r2-oas/support/deprecation/reporting.rb +91 -0
  127. data/lib/r2-oas/task.rb +11 -0
  128. data/lib/r2-oas/task_logging.rb +41 -0
  129. data/lib/r2-oas/tasks/common.rake +25 -0
  130. data/lib/r2-oas/tasks/main.rake +132 -0
  131. data/lib/r2-oas/tasks/tool.rake +86 -0
  132. data/lib/r2-oas/tool/paths/ls.rb +15 -0
  133. data/lib/r2-oas/tool/paths/stats.rb +84 -0
  134. data/lib/r2-oas/version.rb +5 -0
  135. data/r2-oas.gemspec +48 -0
  136. metadata +415 -0
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ require_relative 'app_configuration'
6
+ require_relative 'pluggable_configuration'
7
+ require_relative 'configuration/paths_config'
8
+ require_relative 'logger/stdout_logger'
9
+ require_relative 'support/deprecation'
10
+
11
+ module R2OAS
12
+ module Configuration
13
+ extend AppConfiguration
14
+ extend PluggableConfiguration
15
+
16
+ PUBLIC_VALID_OPTIONS_KEYS = AppConfiguration::VALID_OPTIONS_KEYS + PluggableConfiguration::VALID_OPTIONS_KEYS
17
+
18
+ UNPUBLIC_VALID_OPTIONS_KEYS = %i[
19
+ paths_config
20
+ logger
21
+ ].freeze
22
+
23
+ VALID_OPTIONS_KEYS = PUBLIC_VALID_OPTIONS_KEYS + UNPUBLIC_VALID_OPTIONS_KEYS
24
+
25
+ attr_accessor *PUBLIC_VALID_OPTIONS_KEYS
26
+
27
+ # MEMO: override because deprecated
28
+ def use_object_classes=(data)
29
+ ::R2OAS::Deprecation.will_remove(<<-MSG.squish)
30
+ Using a R2OAS.use_object_classes= in configuration is deprecated and
31
+ will be removed in r2-oas (v0.4.2).
32
+ MSG
33
+ @use_object_classes = data
34
+ end
35
+
36
+ def self.extended(base)
37
+ base.send :set_default_for_configuration, base
38
+ base.send :set_default_for_pluggable, base
39
+ end
40
+
41
+ def configure
42
+ yield self if block_given?
43
+ load_local_plugins
44
+ end
45
+
46
+ def options
47
+ VALID_OPTIONS_KEYS.inject({}) do |option, key|
48
+ option.merge!(key => send(key))
49
+ end
50
+ end
51
+
52
+ def logger
53
+ @_stdout_logger ||= StdoutLogger.new
54
+ end
55
+
56
+ def paths_config
57
+ @_paths_config ||= PathsConfig.new(root_dir_path, schema_save_dir_name)
58
+ end
59
+
60
+ def app_configuration_options
61
+ AppConfiguration::VALID_OPTIONS_KEYS.inject({}) do |option, key|
62
+ option.merge!(key => send(key))
63
+ end
64
+ end
65
+
66
+ def pluggable_configuration_options
67
+ PluggableConfiguration::VALID_OPTIONS_KEYS.inject({}) do |option, key|
68
+ option.merge!(key => send(key))
69
+ end
70
+ end
71
+
72
+ def load_tasks
73
+ tasks_path = File.expand_path("#{root_dir_path}/#{local_tasks_dir_name}")
74
+ Dir.glob("#{tasks_path}/**/*.rake").sort.each do |file|
75
+ load file if FileTest.exists?(file)
76
+ end
77
+ end
78
+
79
+ def init
80
+ plugins_path = File.expand_path("#{root_dir_path}/#{local_plugins_dir_name}")
81
+ plugins_helpers_path = "#{plugins_path}/helpers"
82
+ tasks_path = File.expand_path("#{root_dir_path}/#{local_tasks_dir_name}")
83
+ tasks_helpers_path = "#{tasks_path}/helpers"
84
+
85
+ gitkeep_plugins_path = "#{plugins_path}/.gitkeep"
86
+ gitkeep_plugins_helpers_path = "#{plugins_helpers_path}/.gitkeep"
87
+ gitkeep_tasks_path = "#{tasks_path}/.gitkeep"
88
+ gitkeep_tasks_helpers_path = "#{tasks_helpers_path}/.gitkeep"
89
+
90
+ FileUtils.mkdir_p(plugins_helpers_path) unless FileTest.exists?(plugins_helpers_path)
91
+ FileUtils.mkdir_p(tasks_helpers_path) unless FileTest.exists?(tasks_helpers_path)
92
+
93
+ File.write(gitkeep_plugins_path, '') unless FileTest.exists?(gitkeep_plugins_path)
94
+ File.write(gitkeep_plugins_helpers_path, '') unless FileTest.exists?(gitkeep_plugins_helpers_path)
95
+ File.write(gitkeep_tasks_path, '') unless FileTest.exists?(gitkeep_tasks_path)
96
+ File.write(gitkeep_tasks_helpers_path, '') unless FileTest.exists?(gitkeep_tasks_helpers_path)
97
+ paths_config.create_dot_paths
98
+ end
99
+
100
+ def output_dir_path
101
+ output_path.to_s.split('/').slice(0..-2).join('/')
102
+ end
103
+
104
+ private
105
+
106
+ def load_local_plugins
107
+ plugins_path = File.expand_path("#{root_dir_path}/#{local_plugins_dir_name}")
108
+ Dir.glob("#{plugins_path}/**/*.rb").sort.each do |file|
109
+ require file if FileTest.exists?(file)
110
+ end
111
+ end
112
+
113
+ def set_default_for_configuration(target)
114
+ AppConfiguration.set_default(target)
115
+ end
116
+
117
+ def set_default_for_pluggable(target)
118
+ PluggableConfiguration.set_default(target)
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'r2-oas/schema/manager/file/path_item_file_manager'
4
+
5
+ module R2OAS
6
+ module Configuration
7
+ class PathsConfig
8
+ def initialize(root_dir_path, schema_save_dir_name)
9
+ @root_dir_path = root_dir_path
10
+ @schema_save_dir_path = "#{root_dir_path}/#{schema_save_dir_name}"
11
+ end
12
+
13
+ def abs_paths_path
14
+ File.expand_path("#{@root_dir_path}/.paths")
15
+ end
16
+
17
+ def all_load_paths?
18
+ many_paths_file_paths.present?
19
+ end
20
+
21
+ def many_paths_file_paths
22
+ @many_paths_file_paths ||= File.read(abs_paths_path).split("\n").each_with_object([]) do |relative_path, result|
23
+ abs_path = File.expand_path("#{@schema_save_dir_path}/paths/#{relative_path}")
24
+ result.push(abs_path) if FileTest.exists?(abs_path) && FileTest.file?(abs_path)
25
+ end.uniq.compact.reject(&:empty?)
26
+ end
27
+
28
+ def create_dot_paths
29
+ abs_root_path = File.expand_path(@root_dir_path)
30
+
31
+ FileUtils.mkdir_p(abs_root_path) unless FileTest.exists?(abs_root_path)
32
+ File.write(abs_paths_path, '') unless FileTest.exists?(abs_paths_path)
33
+ end
34
+
35
+ def many_components_file_paths
36
+ @many_components_file_paths ||= many_paths_file_paths.each_with_object([]) do |unit_paths_path, result|
37
+ file_manager = Schema::PathItemFileManager.new(unit_paths_path, :full)
38
+ components_file_paths_at_path = file_manager.descendants_ref_paths
39
+ result.push(*components_file_paths_at_path)
40
+ end.uniq
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal:true
2
+
3
+ require 'fileutils'
4
+
5
+ # Scope Rails
6
+ module R2OAS
7
+ module Deploy
8
+ class Client < Schema::Base
9
+ SWAGGER_UI_DIST_URL = 'https://github.com/swagger-api/swagger-ui/trunk/dist'
10
+
11
+ def initialize(options = {})
12
+ super(options)
13
+ @download_dir = "#{SecureRandom.uuid[0..7]}/dist"
14
+ @dist_path = File.expand_path(Rails.root.join(@download_dir), __FILE__)
15
+ end
16
+
17
+ def download_swagger_ui_dist
18
+ system("svn export #{SWAGGER_UI_DIST_URL} #{@dist_path}")
19
+ end
20
+
21
+ def deploy
22
+ copy_swagger_ui_dist
23
+ copy_swagger_ui_index
24
+ copy_oas_doc_file
25
+ ensure
26
+ remove_download_dist
27
+ end
28
+
29
+ private
30
+
31
+ def copy_swagger_ui_dist
32
+ docs_path = File.expand_path(Rails.root.join(deploy_dir_path), __FILE__)
33
+ FileUtils.mkdir_p(docs_path) unless FileTest.exists?(docs_path)
34
+ FileUtils.mkdir_p(@dist_path) unless FileTest.exists?(@dist_path)
35
+ FileUtils.cp_r(@dist_path, docs_path)
36
+ end
37
+
38
+ def copy_swagger_ui_index
39
+ index_path = File.expand_path(Rails.root.join(deploy_dir_path, 'index.html'), __FILE__)
40
+ @schema_file_path = doc_save_file_name
41
+ template_path = File.expand_path('swagger-ui/index.html.erb', __dir__)
42
+ template = File.read(template_path)
43
+ index = make_index(template)
44
+ File.write(index_path, index)
45
+ end
46
+
47
+ def copy_oas_doc_file
48
+ swagger_file_path = File.expand_path(Rails.root.join(deploy_dir_path, doc_save_file_name), __FILE__)
49
+ oas_doc_file_path = File.expand_path(output_path)
50
+ FileUtils.cp_r(oas_doc_file_path, swagger_file_path)
51
+ end
52
+
53
+ def remove_download_dist
54
+ FileUtils.rm_rf(File.expand_path('..', @dist_path))
55
+ end
56
+
57
+ # [ref]
58
+ # https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Lint/ErbNewArguments
59
+ def make_index(template)
60
+ if RUBY_VERSION >= '2.6'
61
+ ERB.new(template, trim_mode: '%').result(binding)
62
+ else
63
+ # rubocop:disable Lint/ErbNewArguments
64
+ ERB.new(template, nil, trim_mode: '%').result(binding)
65
+ # rubocop:enable Lint/ErbNewArguments
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,60 @@
1
+ <!-- HTML for static distribution bundle build -->
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <title>Swagger UI</title>
7
+ <link rel="stylesheet" type="text/css" href="dist/swagger-ui.css" >
8
+ <link rel="icon" type="image/png" href="dist/favicon-32x32.png" sizes="32x32" />
9
+ <link rel="icon" type="image/png" href="dist/favicon-16x16.png" sizes="16x16" />
10
+ <style>
11
+ html
12
+ {
13
+ box-sizing: border-box;
14
+ overflow: -moz-scrollbars-vertical;
15
+ overflow-y: scroll;
16
+ }
17
+
18
+ *,
19
+ *:before,
20
+ *:after
21
+ {
22
+ box-sizing: inherit;
23
+ }
24
+
25
+ body
26
+ {
27
+ margin:0;
28
+ background: #fafafa;
29
+ }
30
+ </style>
31
+ </head>
32
+
33
+ <body>
34
+ <div id="swagger-ui"></div>
35
+
36
+ <script src="dist/swagger-ui-bundle.js"> </script>
37
+ <script src="dist/swagger-ui-standalone-preset.js"> </script>
38
+ <script>
39
+ window.onload = function() {
40
+ // Begin Swagger UI call region
41
+ const ui = SwaggerUIBundle({
42
+ url: "<%= @schema_file_path %>",
43
+ dom_id: '#swagger-ui',
44
+ deepLinking: true,
45
+ presets: [
46
+ SwaggerUIBundle.presets.apis,
47
+ SwaggerUIStandalonePreset
48
+ ],
49
+ plugins: [
50
+ SwaggerUIBundle.plugins.DownloadUrl
51
+ ],
52
+ layout: "StandaloneLayout"
53
+ })
54
+ // End Swagger UI call region
55
+
56
+ window.ui = ui
57
+ }
58
+ </script>
59
+ </body>
60
+ </html>
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'r2-oas/schema/v3/object/from_routes/base_object'
4
+ require 'r2-oas/hooks/hook'
5
+
6
+ module R2OAS
7
+ module Dynamic
8
+ module Schema
9
+ module V3
10
+ class HookableBaseObject < R2OAS::Schema::V3::BaseObject
11
+ module ClassMethods
12
+ def before_create(&block)
13
+ proc = (block_given? ? block : proc {})
14
+ on(:before_create, proc)
15
+ end
16
+
17
+ def after_create(&block)
18
+ proc = (block_given? ? block : proc {})
19
+ on(:after_create, proc)
20
+ end
21
+ end
22
+
23
+ def self.inherited(base)
24
+ base.extend ClassMethods
25
+ self.hook = Hooks::Hook.register(:dynamic, base)
26
+ end
27
+
28
+ def self.hooks
29
+ superclass.hook.repository[:dynamic][self].global_hooks_data
30
+ end
31
+
32
+ def self.hook=(value)
33
+ @@hook = value
34
+ end
35
+
36
+ def self.hook
37
+ @@hook
38
+ end
39
+
40
+ class << self
41
+ def on(on, callback, once = false)
42
+ hook.on(on, callback, self, once)
43
+ end
44
+
45
+ # MEMO: Do not Use
46
+ def off(on, callback, once = false)
47
+ hook.off(on, callback, self, once)
48
+ end
49
+
50
+ def execute_hook(on, *data)
51
+ hook.execute_hook(on, *data, self)
52
+ end
53
+
54
+ def has_hook?(name)
55
+ hook.has_hook?(name, self)
56
+ end
57
+ end
58
+
59
+ attr_accessor :doc
60
+
61
+ def initialize(opts = {})
62
+ super(opts)
63
+ self.doc = {}
64
+ end
65
+
66
+ # MEMO: Please overwrite when passing arguments other than `doc`
67
+ def to_doc
68
+ execute_before_create
69
+ create_doc
70
+ execute_after_create
71
+ doc
72
+ end
73
+
74
+ def use_superclass_hook
75
+ self.class.hook.repository[:dynamic][self.class] = self.class.hook.repository[:dynamic][self.class.superclass]
76
+ end
77
+
78
+ private
79
+
80
+ def create_doc
81
+ raise NoImplementError
82
+ end
83
+
84
+ def execute_before_create(*data)
85
+ execute_hook_method(:before_create, *data)
86
+ end
87
+
88
+ def execute_after_create(*data)
89
+ execute_hook_method(:after_create, *data)
90
+ end
91
+
92
+ def execute_hook_method(method_name, *data)
93
+ args = [doc].push(*data)
94
+ self.class.execute_hook(method_name.to_sym, *args) if self.class.has_hook?(method_name.to_sym)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module R2OAS
4
+ class NoImplementError < StandardError; end
5
+ class NoFileExistsError < StandardError; end
6
+ class NoSupportError < StandardError; end
7
+ class ChecksumError < StandardError; end
8
+ class PluginNameError < StandardError; end
9
+ class PluginDuplicationError < StandardError; end
10
+ class PluginLoadError < StandardError; end
11
+ class DepulicateSchemaNameError < StandardError; end
12
+ class RefInvalidAssignment < StandardError; end
13
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module R2OAS
4
+ module Hooks
5
+ class GlobalHook
6
+ attr_accessor :callback, :once, :uid, :target
7
+
8
+ def initialize(callback, once, uid, target)
9
+ self.callback = callback
10
+ self.once = once
11
+ self.uid = uid
12
+ self.target = target
13
+ end
14
+
15
+ def call(*data)
16
+ callback.call(*data)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+ require_relative './global_hook'
5
+ require_relative './repository'
6
+
7
+ module R2OAS
8
+ module Hooks
9
+ class Hook
10
+ include Singleton
11
+
12
+ class << self
13
+ attr_accessor :repository
14
+
15
+ def register(type, target_class)
16
+ @repository ||= {}
17
+ @repository[type] ||= {}
18
+ @type = type
19
+ @hooks ||= {}
20
+ @repository[type][target_class] = Repository.new(target_class)
21
+ self
22
+ end
23
+
24
+ def on(on, callback, target_class, once = false)
25
+ target_repository = @repository[@type][target_class]
26
+ uid = target_repository.last_hook_id + 1
27
+ target_repository.last_hook_id = uid
28
+
29
+ target_repository.global_hooks_data[on] ||= []
30
+ global_hook = GlobalHook.new(callback, once, uid, target_class)
31
+
32
+ target_repository.global_hooks_data[on].push(global_hook)
33
+
34
+ uid
35
+ end
36
+
37
+ # MEMO: Do not Use
38
+ def off(uid, target_class)
39
+ target_repository = @repository[@type][target_class]
40
+ result = uid
41
+
42
+ target_repository.global_hooks_data.each do |on|
43
+ global_hooks = target_repository.global_hooks_data[on]
44
+ index = global_hooks.find_index { |hook| hook.uid == uid }
45
+
46
+ if index
47
+ global_hooks.delete_if { |hook| hook.uid == uid }
48
+ else
49
+ result = nil
50
+ end
51
+ end
52
+
53
+ result
54
+ end
55
+
56
+ def execute_hook(on, *data, target_class)
57
+ return data unless has_hook?(on, target_class)
58
+
59
+ execute_global_hook(on, *data, target_class)
60
+ end
61
+
62
+ def has_hook?(name, target_class)
63
+ !!get_hook(name, target_class)
64
+ end
65
+
66
+ private
67
+
68
+ def execute_global_hook(on, *data, target_class)
69
+ global_hook = get_hook(on, target_class)
70
+ global_hook.present? ? global_hook.call(*data) : data
71
+ end
72
+
73
+ def get_hook(name, target_class)
74
+ target_class.hooks[name]&.first
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end