gloo-web 1.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.
@@ -0,0 +1,43 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # A helper class for Resource routing.
5
+ #
6
+
7
+ module Routing
8
+ class ResourceRouter
9
+
10
+ INDEX = 'index'.freeze
11
+ SHOW = 'show'.freeze
12
+ DELETE = 'delete'.freeze
13
+ UPDATE = 'update'.freeze
14
+
15
+ POST_ROUTE = 'create'.freeze
16
+
17
+
18
+ #
19
+ # Is the given route segment an implicit create resource?
20
+ # It is explicit if it is 'create'
21
+ # and implicit if it is a POST to the resource.
22
+ #
23
+ def self.is_implicit_create?( method, route_segment )
24
+ return false unless WebSvr::WebMethod.is_post?( method )
25
+
26
+ return ! route_segment.eql?( POST_ROUTE )
27
+ end
28
+
29
+ #
30
+ # Add the segment based on the method.
31
+ #
32
+ def self.segment_for_method( method )
33
+ if WebSvr::WebMethod.is_delete?( method )
34
+ return DELETE
35
+ elsif WebSvr::WebMethod.is_patch?( method )
36
+ return UPDATE
37
+ else
38
+ return SHOW
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,228 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # A helper class for page routing.
5
+ #
6
+
7
+ module Routing
8
+ class Router
9
+
10
+ PAGE_CONTAINER = 'page'.freeze
11
+ SEGMENT_DIVIDER = '/'.freeze
12
+
13
+ attr_reader :route_segments
14
+
15
+
16
+ # ---------------------------------------------------------------------
17
+ # Initialization
18
+ # ---------------------------------------------------------------------
19
+
20
+ #
21
+ # Set up the web server.
22
+ #
23
+ def initialize( engine, web_svr_obj )
24
+ @engine = engine
25
+ @log = @engine.log
26
+
27
+ @web_svr_obj = web_svr_obj
28
+ @show_routes = ShowRoutes.new( @engine )
29
+ end
30
+
31
+
32
+ # ---------------------------------------------------------------------
33
+ # Routing
34
+ # ---------------------------------------------------------------------
35
+
36
+ #
37
+ # Find and return the page for the given route.
38
+ #
39
+ def page_for_route( path, method )
40
+ @log.info "routing to #{path} for method #{method}"
41
+ @method = method
42
+ route_params = nil
43
+ @id = nil
44
+
45
+ detect_segments path
46
+
47
+ return @web_svr_obj.home_page if is_root_path?
48
+
49
+ pages = @web_svr_obj.pages_container
50
+ if pages
51
+ # If the method is POST and the last segment is NOT 'create',
52
+ # we'll add create to the route segments.
53
+ if Routing::ResourceRouter.is_implicit_create?( method, @route_segments.last )
54
+ @route_segments << Routing::ResourceRouter::POST_ROUTE
55
+ page = find_route_segment( pages.children )
56
+ return [ page, @id, route_params ] if page
57
+
58
+ # We didn't find the page, so remove the last segment and try again
59
+ # posting to the resource.
60
+ @route_segments.pop
61
+ end
62
+
63
+ page = find_route_segment( pages.children )
64
+
65
+ # Are there any remaining segments to be added as route parameters?
66
+ if @route_segments.count > 0
67
+ route_params = @route_segments
68
+ end
69
+
70
+ return [ page, @id, route_params ] if page
71
+ end
72
+
73
+ return nil
74
+ end
75
+
76
+
77
+ # ---------------------------------------------------------------------
78
+ # Dynamic Add Page Routes
79
+ # ---------------------------------------------------------------------
80
+
81
+ #
82
+ # Get the root level page container.
83
+ #
84
+ def page_container
85
+ pn = Gloo::Core::Pn.new( @engine, PAGE_CONTAINER )
86
+ return pn.resolve
87
+ end
88
+
89
+ #
90
+ # Add all page routes to the web server pages (routes).
91
+ #
92
+ def add_page_routes
93
+ can = page_container
94
+ return unless can
95
+
96
+ @log.debug 'Adding page routes to web server…'
97
+ @factory = @engine.factory
98
+
99
+ add_pages can, @web_svr_obj.pages_container
100
+ end
101
+
102
+ #
103
+ # Add the pages to the web server pages.
104
+ # This is a recursive function that will add all
105
+ # pages in the folder and subfolders.
106
+ #
107
+ def add_pages can, parent
108
+ # for each file in the page container
109
+ # create a page object and add it to the routes
110
+ can.children.each do |obj|
111
+ if obj.class == Gloo::Objs::Container
112
+ child_can = parent.find_add_child( obj.name, 'container' )
113
+ add_pages( obj, child_can )
114
+ elsif obj.class == Objs::Page
115
+ add_route_alias( parent, obj.name, obj.pn )
116
+ end
117
+ end
118
+ end
119
+
120
+ #
121
+ # Add route alias to the page.
122
+ #
123
+ def add_route_alias( parent, name, pn )
124
+ name = name.gsub( '.', '_' )
125
+
126
+ # First make sure the child doesn't already exist.
127
+ child = parent.find_child( name )
128
+ return if child
129
+
130
+ @factory.create_alias( name, pn, parent )
131
+ end
132
+
133
+
134
+ # ---------------------------------------------------------------------
135
+ # Helper funcions
136
+ # ---------------------------------------------------------------------
137
+
138
+ #
139
+ # Show the routes in the running app.
140
+ # This uses the ShowRoutes helper class.
141
+ #
142
+ def show_routes
143
+ @show_routes.show page_container
144
+ end
145
+
146
+ #
147
+ # Find the route segment in the object container.
148
+ #
149
+ def find_route_segment objs
150
+ this_segment = next_segment
151
+
152
+ if this_segment.blank? # && WebSvr::WebMethod.is_post?( @method )
153
+ this_segment = Routing::ResourceRouter::INDEX
154
+ end
155
+
156
+ objs.each do |o|
157
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
158
+
159
+ if o.name == this_segment
160
+ if o.class == Objs::Page
161
+ @log.debug "found page for route: #{o.pn}"
162
+ return o
163
+ elsif o.class == Gloo::Objs::FileHandle
164
+ @log.debug "found static file for route: #{o.pn}"
165
+ return o
166
+ else
167
+ return nil unless o.child_count > 0
168
+
169
+ return find_route_segment( o.children )
170
+ end
171
+ end
172
+ end
173
+
174
+ return nil
175
+ end
176
+
177
+ #
178
+ # Get the next segment in the route.
179
+ #
180
+ def next_segment
181
+ this_segment = @route_segments.shift
182
+ return nil if this_segment.nil?
183
+
184
+ # A URL might include a dot in a name, but we can't do that
185
+ # because dot is a reserve path thing. So we replace it with
186
+ # an underscore.
187
+ this_segment = this_segment.gsub( '.', '_' )
188
+
189
+ return this_segment
190
+ end
191
+
192
+ #
193
+ # Is this the root path?
194
+ def is_root_path?
195
+ return @route_segments.count == 0
196
+ end
197
+
198
+ #
199
+ # Create a list of path segments.
200
+ #
201
+ def detect_segments path
202
+ # For Assets, substitute the published name with fingerprint
203
+ # for the simple asset name (if it is found).
204
+ asset_info = WebSvr::AssetInfo.find_info_for( path )
205
+ unless asset_info.blank?
206
+ path = asset_info.pn
207
+ end
208
+
209
+ # Split the path into segments.
210
+ @route_segments = path.split SEGMENT_DIVIDER
211
+
212
+ # Remove the first segment if it is empty.
213
+ @route_segments.shift if @route_segments.first.blank?
214
+
215
+ @route_segments.each do |seg|
216
+ if seg.to_i.to_s == seg
217
+ @id = seg.to_i
218
+ @log.info "found id for route: #{@id}"
219
+ @route_segments.delete seg
220
+ @route_segments << ResourceRouter.segment_for_method( @method )
221
+ end
222
+ end
223
+
224
+ return @route_segments
225
+ end
226
+
227
+ end
228
+ end
@@ -0,0 +1,90 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # A helper class for to show routes for a running app.
5
+ #
6
+
7
+ module Routing
8
+ class ShowRoutes
9
+
10
+ SEGMENT_DIVIDER = '/'.freeze
11
+
12
+
13
+ # ---------------------------------------------------------------------
14
+ # Initialization
15
+ # ---------------------------------------------------------------------
16
+
17
+ #
18
+ # Set up the web server.
19
+ #
20
+ def initialize( engine )
21
+ @engine = engine
22
+ @log = @engine.log
23
+ end
24
+
25
+
26
+ # ---------------------------------------------------------------------
27
+ # Show Routes
28
+ # ---------------------------------------------------------------------
29
+
30
+ #
31
+ # Show all available routes.
32
+ #
33
+ def show page_container
34
+ @log.debug "showing routes"
35
+
36
+ @found_routes = []
37
+ @log.debug "building route table"
38
+ add_container_routes( page_container, SEGMENT_DIVIDER )
39
+
40
+ show_table
41
+ end
42
+
43
+ #
44
+ # Show the routes in the given container.
45
+ # This is a recursive function travese the object tree.
46
+ #
47
+ def add_container_routes can, route_path
48
+ can.children.each do |obj|
49
+ if obj.class == Gloo::Objs::Container
50
+ add_container_routes obj, "#{route_path}#{obj.name}#{SEGMENT_DIVIDER}"
51
+ elsif obj.class == Gloo::Objs::Page
52
+ route = "#{route_path}#{obj.name}"
53
+ @found_routes << [ obj.name, obj.pn, route, WebSvr::WebMethod::GET ]
54
+
55
+ # If the method is POST, add a route alias for the create.
56
+ if obj.name.eql? ResourceRouter::POST_ROUTE
57
+ @found_routes << [ '', '', route_path, WebSvr::WebMethod::POST ]
58
+ elsif obj.name.eql? ResourceRouter::UPDATE
59
+ @found_routes << [ '', '', route_path, WebSvr::WebMethod::PATCH ]
60
+ elsif obj.name.eql? ResourceRouter::DELETE
61
+ @found_routes << [ '', '', route_path, WebSvr::WebMethod::DELETE ]
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+
68
+ # ---------------------------------------------------------------------
69
+ # Show Routes
70
+ # ---------------------------------------------------------------------
71
+
72
+ #
73
+ # Show the Routes title.
74
+ #
75
+ def show_table
76
+ puts Gloo::App::Platform::RETURN
77
+ title = "Routes in Running Web App"
78
+ @engine.platform.table.show headers, @found_routes, title
79
+ puts Gloo::App::Platform::RETURN
80
+ end
81
+
82
+ #
83
+ # Get the table headers.
84
+ #
85
+ def headers
86
+ return [ 'Obj Name', 'Obj Path', 'Route', 'Method' ]
87
+ end
88
+
89
+ end
90
+ end