Module: AgentCode::Routes

Defined in:
lib/agentcode/routes.rb

Overview

Dynamic route registration from AgentCode configuration. Mirrors the Laravel routes/api.php behavior exactly.

Class Method Summary collapse

Class Method Details

.draw(router) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/agentcode/routes.rb', line 8

def draw(router)
  config = AgentCode.config
  route_groups = config.route_groups

  # Sort: literal prefixes first, parameterized (containing ':') last
  sorted_groups = route_groups.sort_by { |_name, cfg| cfg[:prefix].include?(":") ? 1 : 0 }

  router.instance_eval do
    scope path: "api", defaults: { format: :json } do
      # ---------------------------------------------------------------
      # Auth Routes (always registered)
      # ---------------------------------------------------------------
      scope path: "auth" do
        post "login", to: "agentcode/auth#login"
        post "password/recover", to: "agentcode/auth#recover_password"
        post "password/reset", to: "agentcode/auth#reset"
        post "register", to: "agentcode/auth#register_with_invitation"
        post "logout", to: "agentcode/auth#logout"
      end

      # ---------------------------------------------------------------
      # Invitation accept (public, always registered)
      # ---------------------------------------------------------------
      post "invitations/accept", to: "agentcode/invitations#accept"

      # ---------------------------------------------------------------
      # Tenant-specific routes (invitations + nested)
      # ---------------------------------------------------------------
      if config.has_tenant_group?
        tenant_config = route_groups[:tenant]
        tenant_prefix = tenant_config[:prefix]

        # Invitation routes under tenant prefix
        invitation_prefix = tenant_prefix.present? ? "#{tenant_prefix}/invitations" : "invitations"

        scope path: invitation_prefix do
          get "/", to: "agentcode/invitations#index"
          post "/", to: "agentcode/invitations#create"
          post ":id/resend", to: "agentcode/invitations#resend"
          delete ":id", to: "agentcode/invitations#cancel"
        end

        # Nested operations under tenant prefix
        nested_config = config.nested
        nested_path = nested_config[:path] || "nested"
        nested_prefix = tenant_prefix.present? ? "#{tenant_prefix}/#{nested_path}" : nested_path

        post nested_prefix, to: "agentcode/resources#nested", as: :agentcode_nested
      else
        # No tenant group — register nested at top level
        nested_config = config.nested
        nested_path = nested_config[:path] || "nested"
        post nested_path, to: "agentcode/resources#nested", as: :agentcode_nested
      end

      # ---------------------------------------------------------------
      # Per-group CRUD routes
      # ---------------------------------------------------------------
      sorted_groups.each do |group_name, group_config|
        group_prefix = group_config[:prefix]
        group_models = config.models_for_group(group_name)

        group_models.each do |slug|
          model_class_name = config.models[slug]
          model_class = begin
            model_class_name.constantize
          rescue NameError
            next
          end

          except_actions = model_class.try(:agentcode_except_actions_list) || []

          route_prefix = [group_prefix, slug.to_s].reject(&:blank?).join("/")

          scope path: route_prefix, defaults: { model_slug: slug.to_s, route_group: group_name.to_s } do
            unless except_actions.include?("index")
              get "/", to: "agentcode/resources#index", as: "agentcode_#{group_name}_#{slug}_index"
            end

            unless except_actions.include?("store")
              post "/", to: "agentcode/resources#store", as: "agentcode_#{group_name}_#{slug}_store"
            end

            if model_class.try(:uses_soft_deletes?)
              unless except_actions.include?("trashed")
                get "trashed", to: "agentcode/resources#trashed", as: "agentcode_#{group_name}_#{slug}_trashed"
              end

              unless except_actions.include?("restore")
                post ":id/restore", to: "agentcode/resources#restore", as: "agentcode_#{group_name}_#{slug}_restore"
              end

              unless except_actions.include?("forceDelete")
                delete ":id/force-delete", to: "agentcode/resources#force_delete", as: "agentcode_#{group_name}_#{slug}_force_delete"
              end
            end

            unless except_actions.include?("show")
              get ":id", to: "agentcode/resources#show", as: "agentcode_#{group_name}_#{slug}_show"
            end

            unless except_actions.include?("update")
              put ":id", to: "agentcode/resources#update", as: "agentcode_#{group_name}_#{slug}_update"
            end

            unless except_actions.include?("destroy")
              delete ":id", to: "agentcode/resources#destroy", as: "agentcode_#{group_name}_#{slug}_destroy"
            end
          end
        end
      end
    end
  end
end