api_maker 0.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 (103) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +476 -0
  4. data/Rakefile +27 -0
  5. data/app/channels/api_maker/subscriptions_channel.rb +80 -0
  6. data/app/controllers/api_maker/base_controller.rb +32 -0
  7. data/app/controllers/api_maker/commands_controller.rb +26 -0
  8. data/app/controllers/api_maker/devise_controller.rb +60 -0
  9. data/app/controllers/api_maker/session_statuses_controller.rb +33 -0
  10. data/app/services/api_maker/application_service.rb +7 -0
  11. data/app/services/api_maker/collection_command_service.rb +24 -0
  12. data/app/services/api_maker/command_response.rb +67 -0
  13. data/app/services/api_maker/command_service.rb +31 -0
  14. data/app/services/api_maker/create_command.rb +62 -0
  15. data/app/services/api_maker/create_command_service.rb +18 -0
  16. data/app/services/api_maker/destroy_command.rb +39 -0
  17. data/app/services/api_maker/destroy_command_service.rb +22 -0
  18. data/app/services/api_maker/generate_react_native_api_service.rb +61 -0
  19. data/app/services/api_maker/index_command.rb +96 -0
  20. data/app/services/api_maker/index_command_service.rb +22 -0
  21. data/app/services/api_maker/js_method_namer_service.rb +11 -0
  22. data/app/services/api_maker/member_command_service.rb +25 -0
  23. data/app/services/api_maker/model_content_generator_service.rb +108 -0
  24. data/app/services/api_maker/models_finder_service.rb +22 -0
  25. data/app/services/api_maker/models_generator_service.rb +104 -0
  26. data/app/services/api_maker/update_command.rb +43 -0
  27. data/app/services/api_maker/update_command_service.rb +21 -0
  28. data/app/services/api_maker/valid_command.rb +35 -0
  29. data/app/services/api_maker/valid_command_service.rb +21 -0
  30. data/app/views/api_maker/_data.html.erb +15 -0
  31. data/config/rails_best_practices.yml +55 -0
  32. data/config/routes.rb +7 -0
  33. data/lib/api_maker.rb +36 -0
  34. data/lib/api_maker/ability.rb +39 -0
  35. data/lib/api_maker/ability_loader.rb +21 -0
  36. data/lib/api_maker/action_controller_base_extensions.rb +5 -0
  37. data/lib/api_maker/base_command.rb +81 -0
  38. data/lib/api_maker/base_resource.rb +78 -0
  39. data/lib/api_maker/collection_serializer.rb +69 -0
  40. data/lib/api_maker/command_spec_helper.rb +57 -0
  41. data/lib/api_maker/configuration.rb +34 -0
  42. data/lib/api_maker/engine.rb +5 -0
  43. data/lib/api_maker/individual_command.rb +37 -0
  44. data/lib/api_maker/javascript/api.js +92 -0
  45. data/lib/api_maker/javascript/base-model.js +543 -0
  46. data/lib/api_maker/javascript/bootstrap/attribute-row.jsx +16 -0
  47. data/lib/api_maker/javascript/bootstrap/attribute-rows.jsx +47 -0
  48. data/lib/api_maker/javascript/bootstrap/card.jsx +79 -0
  49. data/lib/api_maker/javascript/bootstrap/checkbox.jsx +127 -0
  50. data/lib/api_maker/javascript/bootstrap/checkboxes.jsx +105 -0
  51. data/lib/api_maker/javascript/bootstrap/live-table.jsx +168 -0
  52. data/lib/api_maker/javascript/bootstrap/money-input.jsx +136 -0
  53. data/lib/api_maker/javascript/bootstrap/radio-buttons.jsx +80 -0
  54. data/lib/api_maker/javascript/bootstrap/select.jsx +168 -0
  55. data/lib/api_maker/javascript/bootstrap/string-input.jsx +203 -0
  56. data/lib/api_maker/javascript/cable-connection-pool.js +169 -0
  57. data/lib/api_maker/javascript/cable-subscription-pool.js +111 -0
  58. data/lib/api_maker/javascript/cable-subscription.js +33 -0
  59. data/lib/api_maker/javascript/collection.js +186 -0
  60. data/lib/api_maker/javascript/commands-pool.js +123 -0
  61. data/lib/api_maker/javascript/custom-error.js +14 -0
  62. data/lib/api_maker/javascript/deserializer.js +35 -0
  63. data/lib/api_maker/javascript/devise.js.erb +113 -0
  64. data/lib/api_maker/javascript/error-logger.js +119 -0
  65. data/lib/api_maker/javascript/event-connection.jsx +24 -0
  66. data/lib/api_maker/javascript/event-created.jsx +26 -0
  67. data/lib/api_maker/javascript/event-destroyed.jsx +26 -0
  68. data/lib/api_maker/javascript/event-emitter-listener.jsx +32 -0
  69. data/lib/api_maker/javascript/event-listener.jsx +41 -0
  70. data/lib/api_maker/javascript/event-updated.jsx +26 -0
  71. data/lib/api_maker/javascript/form-data-to-object.js +70 -0
  72. data/lib/api_maker/javascript/included.js +39 -0
  73. data/lib/api_maker/javascript/key-value-store.js +47 -0
  74. data/lib/api_maker/javascript/logger.js +23 -0
  75. data/lib/api_maker/javascript/model-name.js +21 -0
  76. data/lib/api_maker/javascript/model-template.js.erb +110 -0
  77. data/lib/api_maker/javascript/models-response-reader.js +43 -0
  78. data/lib/api_maker/javascript/paginate.jsx +128 -0
  79. data/lib/api_maker/javascript/params.js +68 -0
  80. data/lib/api_maker/javascript/resource-route.jsx +75 -0
  81. data/lib/api_maker/javascript/resource-routes.jsx +36 -0
  82. data/lib/api_maker/javascript/result.js +25 -0
  83. data/lib/api_maker/javascript/session-status-updater.js +113 -0
  84. data/lib/api_maker/javascript/sort-link.jsx +88 -0
  85. data/lib/api_maker/javascript/updated-attribute.jsx +60 -0
  86. data/lib/api_maker/loader.rb +14 -0
  87. data/lib/api_maker/memory_storage.rb +65 -0
  88. data/lib/api_maker/model_extensions.rb +96 -0
  89. data/lib/api_maker/permitted_params_argument.rb +12 -0
  90. data/lib/api_maker/preloader.rb +91 -0
  91. data/lib/api_maker/preloader_belongs_to.rb +58 -0
  92. data/lib/api_maker/preloader_has_many.rb +69 -0
  93. data/lib/api_maker/preloader_has_one.rb +70 -0
  94. data/lib/api_maker/preloader_through.rb +101 -0
  95. data/lib/api_maker/railtie.rb +14 -0
  96. data/lib/api_maker/relationship_includer.rb +42 -0
  97. data/lib/api_maker/resource_routing.rb +8 -0
  98. data/lib/api_maker/result_parser.rb +50 -0
  99. data/lib/api_maker/serializer.rb +86 -0
  100. data/lib/api_maker/spec_helper.rb +100 -0
  101. data/lib/api_maker/version.rb +3 -0
  102. data/lib/tasks/api_maker_tasks.rake +5 -0
  103. metadata +581 -0
@@ -0,0 +1,18 @@
1
+ class ApiMaker::CreateCommandService < ApiMaker::CommandService
2
+ def execute
3
+ ApiMaker::CreateCommand.execute_in_thread!(
4
+ ability: ability,
5
+ args: args,
6
+ collection: collection,
7
+ commands: commands,
8
+ command_response: command_response,
9
+ controller: controller
10
+ )
11
+
12
+ ServicePattern::Response.new(success: true)
13
+ end
14
+
15
+ def collection
16
+ @collection ||= model_class.accessible_by(@ability, :create)
17
+ end
18
+ end
@@ -0,0 +1,39 @@
1
+ class ApiMaker::DestroyCommand < ApiMaker::BaseCommand
2
+ attr_reader :command, :model, :params, :serializer
3
+
4
+ def execute!
5
+ each_command do |command|
6
+ @command = command
7
+ @model = command.model
8
+ @params = command.args || {}
9
+ @serializer = serialized_resource(model)
10
+
11
+ if command.model.destroy
12
+ success_response
13
+ else
14
+ failure_response
15
+ end
16
+ end
17
+
18
+ ServicePattern::Response.new(success: true)
19
+ end
20
+
21
+ def failure_response
22
+ command.fail(
23
+ model: serializer.result,
24
+ success: false,
25
+ errors: model.errors.full_messages
26
+ )
27
+ end
28
+
29
+ def serialized_resource(model)
30
+ ApiMaker::Serializer.new(ability: current_ability, args: api_maker_args, model: model)
31
+ end
32
+
33
+ def success_response
34
+ command.result(
35
+ model: serializer.result,
36
+ success: true
37
+ )
38
+ end
39
+ end
@@ -0,0 +1,22 @@
1
+ class ApiMaker::DestroyCommandService < ApiMaker::CommandService
2
+ def execute
3
+ ApiMaker::DestroyCommand.execute_in_thread!(
4
+ ability: ability,
5
+ args: args,
6
+ collection: collection,
7
+ commands: commands,
8
+ command_response: command_response,
9
+ controller: controller
10
+ )
11
+
12
+ ServicePattern::Response.new(success: true)
13
+ end
14
+
15
+ def collection
16
+ @collection ||= model_class.accessible_by(@ability, :destroy).where(model_class.primary_key => ids)
17
+ end
18
+
19
+ def ids
20
+ @commands.values.map { |command| command.fetch("primary_key") }
21
+ end
22
+ end
@@ -0,0 +1,61 @@
1
+ class ApiMaker::GenerateReactNativeApiService < ApiMaker::ApplicationService
2
+ def execute
3
+ check_if_root_folder_defined
4
+ create_root_folder
5
+ create_model_files
6
+
7
+ ServicePattern::Response.new(success: true)
8
+ end
9
+
10
+ def root_folder
11
+ @root_folder ||= ApiMaker::Configuration.current.react_native_path
12
+ end
13
+
14
+ def check_if_root_folder_defined
15
+ raise "No root folder detected" if root_folder.blank?
16
+
17
+ Dir.mkdir(model_path) unless Dir.exist?(model_path)
18
+ end
19
+
20
+ def create_root_folder
21
+ Dir.mkdir(root_folder) unless Dir.exist?(root_folder)
22
+ end
23
+
24
+ def create_model_files
25
+ model_generator_service.models.each do |model|
26
+ next if model_generator_service.ignore_model?(model)
27
+
28
+ model_content_response = ApiMaker::ModelContentGeneratorService.execute!(model: model)
29
+
30
+ if model_content_response.success?
31
+ File.open(model_file(model), "w") { |fp| fp.write(model_content_response.result) }
32
+ else
33
+ puts model_content_response.errors.join(". ")
34
+ end
35
+ end
36
+ end
37
+
38
+ def model_generator_service
39
+ @model_generator_service ||= ApiMaker::ModelsGeneratorService.new
40
+ end
41
+
42
+ def model_file(model)
43
+ resource_class = ApiMaker::MemoryStorage.current.resource_for_model(model)
44
+ File.join(model_path, "#{resource_class.short_name.underscore.dasherize}.js")
45
+ end
46
+
47
+ def model_path
48
+ @model_path ||= File.join(root_folder, "models")
49
+ end
50
+
51
+ def copy_base_model
52
+ files = %w[
53
+ api.js base-model.js cable-connection-pool.js cable-subscription.js cable-subscription-pool.js
54
+ collection.js commands-pool.js devise.js event-listener.jsx error-logger.js form-data-to-object.js logger.js
55
+ model-name.js models-response-reader.js result.js event-connection.jsx
56
+ ]
57
+ path = File.join(__dir__, "..", "..", "..", "lib", "api_maker", "javascript")
58
+
59
+ copy_base_files(files, path, root_folder)
60
+ end
61
+ end
@@ -0,0 +1,96 @@
1
+ class ApiMaker::IndexCommand < ApiMaker::BaseCommand
2
+ attr_reader :params
3
+
4
+ def execute!
5
+ ApiMaker::Configuration.profile("IndexCommand execute") do
6
+ each_command do |command|
7
+ @params = command.args || {}
8
+
9
+ set_collection
10
+
11
+ if params[:count]
12
+ count = @query.count
13
+ count = count.length if count.is_a?(Hash)
14
+
15
+ command.result(count: count)
16
+ else
17
+ collection = collection_from_query(@query.fix)
18
+ response = collection.as_json
19
+ include_pagination_data(response, @query)
20
+
21
+ command.result(response)
22
+ end
23
+ end
24
+ end
25
+
26
+ ServicePattern::Response.new(success: true)
27
+ end
28
+
29
+ def filter_custom_accessible_by(collection)
30
+ return collection if params[:accessible_by].blank?
31
+
32
+ collection.accessible_by(current_ability, params[:accessible_by].to_sym)
33
+ end
34
+
35
+ def collection_from_query(collection)
36
+ ApiMaker::Configuration.profile("IndexCommand collection_from_query") do
37
+ select = parse_select(params[:select]&.permit!&.to_hash) if params[:select]
38
+
39
+ ApiMaker::CollectionSerializer.new(
40
+ ability: current_ability,
41
+ args: api_maker_args,
42
+ collection: collection,
43
+ include_param: params[:include],
44
+ select: select
45
+ ).result
46
+ end
47
+ end
48
+
49
+ def include_pagination_data(response, collection)
50
+ return if params[:page].blank?
51
+
52
+ response[:meta] = {
53
+ currentPage: collection.current_page,
54
+ totalCount: collection.try(:total_count) || collection.try(:total_entries),
55
+ totalPages: collection.total_pages
56
+ }
57
+ end
58
+
59
+ def manage_through_relationship
60
+ return if params[:through].blank?
61
+
62
+ model_class = params[:through][:model].safe_constantize
63
+ through_model = model_class.accessible_by(current_ability).find(params[:through][:id])
64
+ association = ActiveRecord::Associations::Association.new(through_model, model_class.reflections.fetch(params[:through][:reflection]))
65
+
66
+ query_through = association.scope
67
+ query_through = query_through.accessible_by(current_ability)
68
+ query_through = filter_custom_accessible_by(query_through)
69
+ query_through
70
+ end
71
+
72
+ # This converts the list of attributes to a hash that contains the data needed for the serializer (so the serializer doesn't have to do it for each model)
73
+ def parse_select(select)
74
+ new_select = {}
75
+
76
+ select.each do |model_collection_name, attributes|
77
+ model_class = model_collection_name.underscore.singularize.camelize
78
+ resource = "Resources::#{model_class}Resource".safe_constantize
79
+ raise "Resource not found for: #{model_collection_name}" unless resource
80
+
81
+ new_attributes = resource._attributes.select { |key| attributes.include?(key.to_s) }
82
+ new_select[resource.model_class] = new_attributes
83
+ end
84
+
85
+ new_select
86
+ end
87
+
88
+ def set_collection
89
+ @query = manage_through_relationship || collection
90
+ @query = @query.distinct if params[:distinct]
91
+ @query = @query.ransack(params[:q]).result
92
+ @query = @query.limit(params[:limit]) if params[:limit].present?
93
+ @query = @query.page(params[:page]) if params[:page].present?
94
+ @query = filter_custom_accessible_by(@query)
95
+ end
96
+ end
@@ -0,0 +1,22 @@
1
+ class ApiMaker::IndexCommandService < ApiMaker::CommandService
2
+ def execute
3
+ ApiMaker::IndexCommand.execute_in_thread!(
4
+ ability: ability,
5
+ args: args,
6
+ collection: collection,
7
+ commands: commands,
8
+ command_response: command_response,
9
+ controller: controller
10
+ )
11
+
12
+ ServicePattern::Response.new(success: true)
13
+ end
14
+
15
+ def collection
16
+ @collection ||= model_class.accessible_by(@ability)
17
+ end
18
+
19
+ def ids
20
+ @ids ||= @commands.values.map { |command| command.fetch("primary_key") }
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ class ApiMaker::JsMethodNamerService < ApiMaker::ApplicationService
2
+ def initialize(name:)
3
+ @name = name
4
+ end
5
+
6
+ def execute
7
+ camelized = @name.to_s.camelize
8
+ new_name = "#{camelized[0..0].downcase}#{camelized[1..camelized.length]}"
9
+ ServicePattern::Response.new(result: new_name)
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ class ApiMaker::MemberCommandService < ApiMaker::CommandService
2
+ def execute
3
+ ability_name = @command_name.to_sym
4
+ collection = model_class.accessible_by(@ability, ability_name).where(model_class.primary_key => ids)
5
+
6
+ constant.execute_in_thread!(
7
+ ability: ability,
8
+ args: args,
9
+ collection: collection,
10
+ commands: commands,
11
+ command_response: command_response,
12
+ controller: controller
13
+ )
14
+
15
+ ServicePattern::Response.new(success: true)
16
+ end
17
+
18
+ def constant
19
+ @constant ||= "Commands::#{namespace}::#{@command_name.camelize}".constantize
20
+ end
21
+
22
+ def ids
23
+ @commands.values.map { |command| command.fetch("primary_key") }
24
+ end
25
+ end
@@ -0,0 +1,108 @@
1
+ class ApiMaker::ModelContentGeneratorService < ApiMaker::ApplicationService
2
+ attr_reader :model
3
+
4
+ def initialize(model:)
5
+ @model = model
6
+ end
7
+
8
+ def execute
9
+ if resource
10
+ ServicePattern::Response.new(result: model_content)
11
+ else
12
+ ServicePattern::Response.new(errors: ["No resource defined for #{model.name}"])
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def attributes
19
+ resource._attributes.map do |attribute, _data|
20
+ {name: attribute, type: model_type(attribute)}
21
+ end
22
+ end
23
+
24
+ def collection_commands
25
+ ApiMaker::Loader.load_everything
26
+ ApiMaker::MemoryStorage.current.storage_for(resource, :collection_commands)
27
+ end
28
+
29
+ def member_commands
30
+ ApiMaker::Loader.load_everything
31
+ ApiMaker::MemoryStorage.current.storage_for(resource, :member_commands)
32
+ end
33
+
34
+ def model_content
35
+ erb = ERB.new(File.read(model_template_path))
36
+ erb.filename = File.realpath(model_template_path)
37
+ erb.result(binding)
38
+ end
39
+
40
+ def model_template_path
41
+ File.join(__dir__, "..", "..", "..", "lib", "api_maker", "javascript", "model-template.js.erb")
42
+ end
43
+
44
+ def model_type(attribute_name)
45
+ model_type = model.columns_hash[attribute_name.to_s]&.type
46
+ model_type = :money if monetized_attributes.include?(attribute_name.to_s)
47
+ model_type ||= :unknown
48
+ model_type
49
+ end
50
+
51
+ def monetized_attributes
52
+ @monetized_attributes ||= @model.try(:monetized_attributes).try(:map) { |attribute| attribute[0] } || []
53
+ end
54
+
55
+ def reflections
56
+ @reflections ||= resource._relationships.map do |name, _data|
57
+ reflection = model.reflections.values.find { |reflection_i| reflection_i.name == name }
58
+ raise "Couldnt find reflection by that name: #{name}" unless reflection
59
+
60
+ reflection
61
+ end
62
+ end
63
+
64
+ def reflection_has_many_parameters(reflection)
65
+ {
66
+ reflectionName: reflection.name,
67
+ model: "{{this}}",
68
+ modelName: reflection.class_name,
69
+ modelClass: "{{modelClass}}",
70
+ targetPathName: "/api_maker/#{reflection.klass.model_name.route_key}"
71
+ }
72
+ end
73
+
74
+ def reflection_has_many_parameters_query(reflection)
75
+ if reflection.options[:through]
76
+ {
77
+ params: {
78
+ through: {
79
+ model: model.name,
80
+ id: "{{id}}",
81
+ reflection: reflection.name
82
+ }
83
+ }
84
+ }
85
+ else
86
+ {
87
+ ransack: {
88
+ "#{reflection.foreign_key}_eq" => "{{id}}"
89
+ }
90
+ }
91
+ end
92
+ end
93
+
94
+ def reflections_for_model_class_data
95
+ @reflections_for_model_class_data ||= reflections.map do |reflection|
96
+ {
97
+ className: reflection.class_name,
98
+ collectionName: ApiMaker::MemoryStorage.current.resource_for_model(reflection.klass).collection_name,
99
+ name: reflection.name,
100
+ macro: reflection.macro
101
+ }
102
+ end
103
+ end
104
+
105
+ def resource
106
+ @resource ||= ApiMaker::MemoryStorage.current.resource_for_model(@model)
107
+ end
108
+ end
@@ -0,0 +1,22 @@
1
+ class ApiMaker::ModelsFinderService < ApiMaker::ApplicationService
2
+ def execute
3
+ ServicePattern::Response.new(result: models)
4
+ end
5
+
6
+ private
7
+
8
+ def models
9
+ result = []
10
+ Dir.glob(Rails.root.join("app", "api_maker", "resources", "**", "*.rb")) do |model_path|
11
+ next unless model_path.start_with?(Rails.root.to_s)
12
+
13
+ path_name = model_path.gsub(/\A#{Regexp.escape(Rails.root.to_s)}\/app\/api_maker\/resources\//, "").gsub(/\.rb\Z/, "")
14
+ next if path_name == "application_resource"
15
+
16
+ resource_class = "Resources::#{path_name.classify}".constantize
17
+ result << resource_class.model_class
18
+ end
19
+
20
+ result
21
+ end
22
+ end
@@ -0,0 +1,104 @@
1
+ class ApiMaker::ModelsGeneratorService < ApiMaker::ApplicationService
2
+ def execute
3
+ create_base_structure
4
+ copy_base_model
5
+ copy_base_controllers
6
+
7
+ models.each do |model|
8
+ next if ignore_model?(model)
9
+
10
+ model_content_response = ApiMaker::ModelContentGeneratorService.execute(model: model)
11
+
12
+ if model_content_response.success?
13
+ File.open(model_file(model), "w") { |fp| fp.write(model_content_response.result) }
14
+ else
15
+ puts model_content_response.errors.join(". ")
16
+ end
17
+ end
18
+
19
+ ApiMaker::GenerateReactNativeApiService.execute! if ApiMaker::Configuration.current.react_native_path.present?
20
+ ServicePattern::Response.new(success: true)
21
+ end
22
+
23
+ def ignore_model?(model)
24
+ model.name.end_with?("::Translation") ||
25
+ model.name.start_with?("ActiveStorage::") ||
26
+ model.name.end_with?("::ApplicationRecord")
27
+ end
28
+
29
+ def models
30
+ ApiMaker::ModelsFinderService.execute!
31
+ end
32
+
33
+ private
34
+
35
+ def api_maker_root_path
36
+ Rails.root.join("app", "javascript", "api-maker")
37
+ end
38
+
39
+ def controller_path
40
+ Rails.root.join("app", "controllers", "api_maker")
41
+ end
42
+
43
+ def copy_base_controllers
44
+ files = %w[devise_controller.rb]
45
+ path = File.join(__dir__, "..", "..", "controllers", "api_maker")
46
+ target_path = Rails.root.join("app", "controllers", "api_maker")
47
+
48
+ copy_base_files(files, path, target_path)
49
+ end
50
+
51
+ def copy_base_model
52
+ files = %w[
53
+ api.js base-model.js cable-connection-pool.js cable-subscription.js cable-subscription-pool.js collection.js
54
+ commands-pool.js event-created.jsx custom-error.js deserializer.js devise.js event-destroyed.jsx event-emitter-listener.jsx event-listener.jsx
55
+ event-updated.jsx error-logger.js form-data-to-object.js included.js key-value-store.js logger.js model-name.js models-response-reader.js
56
+ params.js result.js event-connection.jsx paginate.jsx sort-link.jsx updated-attribute.jsx resource-routes.jsx resource-route.jsx
57
+ session-status-updater.js bootstrap/attribute-row.jsx bootstrap/attribute-rows.jsx bootstrap/card.jsx
58
+ bootstrap/checkbox.jsx bootstrap/checkboxes.jsx bootstrap/money-input.jsx bootstrap/radio-buttons.jsx
59
+ bootstrap/select.jsx bootstrap/string-input.jsx bootstrap/live-table.jsx
60
+ ]
61
+ path = File.join(__dir__, "..", "..", "..", "lib", "api_maker", "javascript")
62
+ target_path = api_maker_root_path
63
+
64
+ copy_base_files(files, path, target_path)
65
+ end
66
+
67
+ def copy_base_files(files, path, target_path)
68
+ files.each do |file|
69
+ base_model_source_path = File.join(path, file)
70
+ base_model_target_path = File.join(target_path, file)
71
+
72
+ base_model_target_dir = File.dirname(base_model_target_path)
73
+ FileUtils.mkdir_p(base_model_target_dir) unless File.exist?(base_model_target_dir)
74
+
75
+ if File.exist?(base_model_source_path)
76
+ content = File.read(base_model_source_path)
77
+ else
78
+ base_model_source_path << ".erb"
79
+ erb = ERB.new(File.read(base_model_source_path))
80
+ erb.filename = base_model_source_path
81
+ content = erb.result(binding)
82
+ end
83
+
84
+ base_model_target_path = File.join(target_path, file)
85
+
86
+ File.open(base_model_target_path, "w") do |fp|
87
+ fp.write(content)
88
+ end
89
+ end
90
+ end
91
+
92
+ def create_base_structure
93
+ # Dont remove all the files. It messes up running Webpack Dev Servers which forces you to restart all the time.
94
+ # FileUtils.rm_rf(api_maker_root_path) if File.exist?(api_maker_root_path)
95
+
96
+ FileUtils.mkdir_p(api_maker_root_path.join("models"))
97
+ FileUtils.mkdir_p(controller_path) unless File.exist?(controller_path)
98
+ end
99
+
100
+ def model_file(model)
101
+ resource_class = ApiMaker::MemoryStorage.current.resource_for_model(model)
102
+ api_maker_root_path.join("models", "#{resource_class.short_name.underscore.dasherize}.js")
103
+ end
104
+ end