gloo 3.1.1 → 3.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2040934825cd8c004b50e10414322e232c68d30299d7696bef2ae2f23cdb3e8
4
- data.tar.gz: 70374a3c6d010fcc1d84d34ac1036c41d12d9699d8ce3629baf3a58683f0aac9
3
+ metadata.gz: f1dca7b53440a446850b2c3bd58b9a2b3c66ef73156bf7e8e90bfba9ddd71032
4
+ data.tar.gz: 012614b36386042458633b635a4f28c33fd9be21a50be7bcf37271d8c2aa8360
5
5
  SHA512:
6
- metadata.gz: 55b6ece805e4705bcc909de79b80bad0a188d72ccf547f74f272d7f50d720d19e5c9412a99247378f9675f11f53b940ef6a83c05fc5dccf5b87b925742a140f6
7
- data.tar.gz: b53f60308d786d1d4a90ac4e6e8aceb0527832f824b2110d72b767d55bf5f7ed3df467da22df8be0c7ea240462cee1cb21ce9a30c9859f469635133f3687f56c
6
+ metadata.gz: 0ae04823687860a34d4134bc9f3338a7d05dd68b6cd618d8ef8f1f51198bbcd2ea692f3737ab6e235f175ffa184114c6158071fc743ccc1073cba27d1d4efca0
7
+ data.tar.gz: 4a0c04fb3f64e2d7c045b72fd4a6f7c8b8d172b18b030de033d492803adf67eaf8c0f657e174b861d6de05172755f8bfb8273f3be42d53913c074923468371e7
data/lib/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.1
1
+ 3.2.0
data/lib/VERSION_NOTES CHANGED
@@ -1,3 +1,9 @@
1
+ 3.2.0 - 2024.07.07
2
+ - Update with more web server functionality, http methods, resource routing
3
+ - Expands query with additional html table support
4
+ - Other web additions and expansion
5
+
6
+
1
7
  3.1.1 - 2024.04.26
2
8
  - Clean build
3
9
 
data/lib/gloo/app/log.rb CHANGED
@@ -17,6 +17,8 @@ module Gloo
17
17
  ERROR = 'error'.freeze
18
18
  LEVELS = [ DEBUG, INFO, WARN, ERROR ].freeze
19
19
 
20
+ CLEARED = "\n\n --- Log files cleared. --- \n\n".freeze
21
+
20
22
  LOG_FILE = 'gloo.log'.freeze
21
23
  ERROR_FILE = 'error.log'.freeze
22
24
 
@@ -46,15 +48,32 @@ module Gloo
46
48
  # Create the default [file] logger.
47
49
  #
48
50
  def create_loggers
49
- f = File.join( @engine.settings.log_path, LOG_FILE )
50
- @logger = Logger.new( f )
51
+ @logger = Logger.new( log_file )
51
52
  @logger.level = Logger::DEBUG
52
53
 
53
- err = File.join( @engine.settings.log_path, ERROR_FILE )
54
- @error = Logger.new( err )
54
+ @error = Logger.new( err_file )
55
55
  @error.level = Logger::WARN
56
56
  end
57
57
 
58
+ # ---------------------------------------------------------------------
59
+ # Files
60
+ # ---------------------------------------------------------------------
61
+
62
+ #
63
+ # Get the log file.
64
+ #
65
+ def log_file
66
+ return File.join( @engine.settings.log_path, LOG_FILE )
67
+ end
68
+
69
+ #
70
+ # Get the error log file.
71
+ #
72
+ def err_file
73
+ return File.join( @engine.settings.log_path, ERROR_FILE )
74
+ end
75
+
76
+
58
77
  # ---------------------------------------------------------------------
59
78
  # Static Helpers
60
79
  # ---------------------------------------------------------------------
@@ -67,6 +86,21 @@ module Gloo
67
86
  return LEVELS.include? str.strip.downcase
68
87
  end
69
88
 
89
+ # ---------------------------------------------------------------------
90
+ # Log file clearing
91
+ # ---------------------------------------------------------------------
92
+
93
+ #
94
+ # Clear the log files.
95
+ #
96
+ def clear
97
+ File.write( log_file, CLEARED )
98
+ File.write( err_file, CLEARED )
99
+
100
+ create_loggers
101
+ end
102
+
103
+
70
104
  # ---------------------------------------------------------------------
71
105
  # Standard Output
72
106
  # ---------------------------------------------------------------------
@@ -74,8 +108,14 @@ module Gloo
74
108
  #
75
109
  # Show a message unless we're in quite mode.
76
110
  #
77
- def show( msg )
78
- puts msg unless @quiet
111
+ def show( msg, color=nil )
112
+ return if @quiet
113
+
114
+ if color
115
+ puts ColorizedString[ msg ].colorize( color.to_sym )
116
+ else
117
+ puts msg
118
+ end
79
119
  end
80
120
 
81
121
  # ---------------------------------------------------------------------
@@ -10,7 +10,7 @@ module Gloo
10
10
  module App
11
11
  class RunningApp
12
12
 
13
- attr_reader :obj
13
+ attr_reader :obj, :db_time
14
14
 
15
15
  #
16
16
  # Set up the running app for the given object.
@@ -19,6 +19,8 @@ module Gloo
19
19
  @engine = engine
20
20
  @log = @engine.log
21
21
  @obj = obj
22
+
23
+ @db_clients = {}
22
24
  end
23
25
 
24
26
  #
@@ -36,6 +38,45 @@ module Gloo
36
38
  @log.debug "running app stopped for #{@obj.pn}"
37
39
  end
38
40
 
41
+
42
+ # ---------------------------------------------------------------------
43
+ # DB function timer
44
+ # ---------------------------------------------------------------------
45
+
46
+ #
47
+ # Add the given time to the db time.
48
+ #
49
+ def add_db_time time
50
+ @db_time = 0 unless @db_time
51
+ @db_time += time
52
+ end
53
+
54
+ #
55
+ # Reset the db time to zero
56
+ #
57
+ def reset_db_time
58
+ @db_time = 0
59
+ end
60
+
61
+
62
+ # ---------------------------------------------------------------------
63
+ # Cached Database Connections
64
+ # ---------------------------------------------------------------------
65
+
66
+ #
67
+ # Cache the given DB client for the given object.
68
+ #
69
+ def cache_db_client( obj, client )
70
+ @db_clients[ obj.pn ] = client
71
+ end
72
+
73
+ #
74
+ # Get the DB client for the given object.
75
+ #
76
+ def db_client_for_obj( obj )
77
+ return @db_clients[ obj.pn ]
78
+ end
79
+
39
80
  end
40
81
  end
41
82
  end
data/lib/gloo/core/obj.rb CHANGED
@@ -137,6 +137,14 @@ module Gloo
137
137
  return self.value.to_s.strip.empty?
138
138
  end
139
139
 
140
+ #
141
+ # Is this an alias to another object?
142
+ #
143
+ def is_alias?
144
+ return self.type_display == Gloo::Objs::Alias.typename
145
+ end
146
+
147
+
140
148
  # ---------------------------------------------------------------------
141
149
  # Children
142
150
  # ---------------------------------------------------------------------
@@ -193,7 +201,7 @@ module Gloo
193
201
  return o if name.downcase == o.name.downcase
194
202
  end
195
203
 
196
- if self.type_display == Gloo::Objs::Alias.typename
204
+ if is_alias?
197
205
  ln = Gloo::Core::Pn.new( @engine, self.value )
198
206
  redirect = ln.resolve
199
207
  return redirect.find_child( name )
@@ -201,6 +209,16 @@ module Gloo
201
209
  return nil
202
210
  end
203
211
 
212
+ #
213
+ # Get the index of the child with the given name.
214
+ #
215
+ def child_index( name )
216
+ @children.each_with_index do |o, i|
217
+ return i if name.downcase == o.name.downcase
218
+ end
219
+ return nil
220
+ end
221
+
204
222
  #
205
223
  # Delete all children from the container.
206
224
  #
@@ -300,6 +318,21 @@ module Gloo
300
318
  @engine.persist_man.reload self
301
319
  end
302
320
 
321
+
322
+ # ---------------------------------------------------------------------
323
+ # Render
324
+ # ---------------------------------------------------------------------
325
+
326
+ #
327
+ # Render the object.
328
+ # By default this is just the object's value.
329
+ # The render_ƒ is 'render_html', 'render_text', 'render_json', etc.
330
+ #
331
+ def render render_ƒ
332
+ return self.value.to_s
333
+ end
334
+
335
+
303
336
  # ---------------------------------------------------------------------
304
337
  # Help
305
338
  # ---------------------------------------------------------------------
@@ -10,6 +10,7 @@ module Gloo
10
10
  class ExecEnv
11
11
 
12
12
  attr_accessor :verbs, :actions, :scripts, :here
13
+ attr_reader :running_script
13
14
 
14
15
  VERB_STACK = 'verbs'.freeze
15
16
  ACTION_STACK = 'actions'.freeze
@@ -22,6 +23,7 @@ module Gloo
22
23
  def initialize( engine )
23
24
  @engine = engine
24
25
  @engine.log.debug 'exec env intialized...'
26
+ @running_script = nil
25
27
 
26
28
  @verbs = Gloo::Exec::Stack.new( @engine, VERB_STACK )
27
29
  @actions = Gloo::Exec::Stack.new( @engine, ACTION_STACK )
@@ -43,6 +45,7 @@ module Gloo
43
45
  #
44
46
  def push_script( script )
45
47
  @scripts.push script
48
+ @running_script = script
46
49
  @here.push script.obj
47
50
  end
48
51
 
@@ -51,6 +54,7 @@ module Gloo
51
54
  #
52
55
  def pop_script
53
56
  @scripts.pop
57
+ @running_script = @scripts.stack.last
54
58
  @here.pop
55
59
  end
56
60
 
@@ -9,13 +9,13 @@ module Gloo
9
9
  class Script
10
10
 
11
11
  attr_accessor :obj
12
-
13
12
  #
14
13
  # Set up the script.
15
14
  #
16
15
  def initialize( engine, obj )
17
16
  @engine = engine
18
17
  @obj = obj
18
+ @break_out = false
19
19
  end
20
20
 
21
21
  #
@@ -30,6 +30,7 @@ module Gloo
30
30
  @engine.parser.run @obj.value
31
31
  elsif @obj.value.is_a? Array
32
32
  @obj.value.each do |line|
33
+ break if @break_out
33
34
  @engine.parser.run line
34
35
  end
35
36
  end
@@ -45,6 +46,13 @@ module Gloo
45
46
  return @obj.pn
46
47
  end
47
48
 
49
+ #
50
+ # Stop running this script.
51
+ #
52
+ def break_out
53
+ @break_out = true
54
+ end
55
+
48
56
  end
49
57
  end
50
58
  end
@@ -33,7 +33,7 @@ module Gloo
33
33
  # Get a list of message names that this object receives.
34
34
  #
35
35
  def self.messages
36
- return super + %w[count delete_children show_key_value_table]
36
+ return super + %w[count delete_children child_exists show_key_value_table]
37
37
  end
38
38
 
39
39
  #
@@ -57,9 +57,25 @@ module Gloo
57
57
  #
58
58
  def msg_show_key_value_table
59
59
  data = self.children.map { |o| [ o.name, o.value ] }
60
- @engine.platform.show_table nil, data, title
60
+
61
+ # TODO: this doesn't work:
62
+ # @engine.platform.show_table nil, data, title
61
63
  end
62
64
 
65
+ #
66
+ # Check to see if there is a child with the given name.
67
+ #
68
+ def msg_child_exists
69
+ if @params&.token_count&.positive?
70
+ expr = Gloo::Expr::Expression.new( @engine, @params.tokens )
71
+ data = expr.evaluate
72
+ end
73
+ return unless data
74
+
75
+ val = self.contains_child?( data )
76
+ @engine.heap.it.set_to val
77
+ return val
78
+ end
63
79
  end
64
80
  end
65
81
  end
@@ -68,7 +68,10 @@ module Gloo
68
68
  #
69
69
  def add_loop_child
70
70
  o = find_child LOOP
71
- return if o
71
+ if o
72
+ o.set_value true
73
+ return
74
+ end
72
75
 
73
76
  fac = @engine.factory
74
77
  fac.create_bool LOOP, true, self
@@ -324,7 +327,7 @@ module Gloo
324
327
  # Run the selected command.
325
328
  #
326
329
  def run_command( cmd )
327
- @engine.log.debug "Menu Command: #{cmd}"
330
+ @engine.log.info "Menu Command: #{cmd}"
328
331
  obj = find_cmd cmd
329
332
 
330
333
  if obj
@@ -335,15 +338,18 @@ module Gloo
335
338
  s.run
336
339
  else
337
340
  if cmd == '?'
341
+ @engine.log.debug 'Showing options'
338
342
  show_options
339
343
  elsif cmd == 'q!'
340
- @engine.log.info 'Quitting Gloo'
344
+ @engine.log.debug 'Quitting Gloo'
341
345
  @engine.stop_running
342
346
  elsif cmd == 'qq'
347
+ @engine.log.debug 'Quitting to top level menu'
343
348
  pop_to_top_level_menu
344
349
  elsif cmd.starts_with? ':'
345
350
  gloo_cmd = cmd[1..-1].strip
346
351
  if gloo_cmd.blank?
352
+ @engine.log.debug 'Quitting all menus and dropping into Gloo'
347
353
  quit_all_menus
348
354
  else
349
355
  @engine.log.debug "Running Gloo command: #{gloo_cmd}"
@@ -90,22 +90,42 @@ module Gloo
90
90
  @engine.heap.it.set_to true
91
91
  end
92
92
 
93
+
93
94
  # ---------------------------------------------------------------------
94
95
  # DB functions (all database connections)
95
96
  # ---------------------------------------------------------------------
96
97
 
98
+ #
99
+ # Get the client object.
100
+ # It might be cached, so check first.
101
+ # If it is not cached, create a new one.
102
+ #
103
+ def get_client
104
+ app = @engine.running_app
105
+
106
+ client = app.db_client_for_obj( self ) if app
107
+
108
+ unless client
109
+ h = {
110
+ host: host_value,
111
+ database: db_value,
112
+ username: user_value,
113
+ password: passwd_value
114
+ }
115
+ client = Mysql2::Client.new( h )
116
+
117
+ app.cache_db_client( self, client ) if app
118
+ end
119
+
120
+ return client
121
+ end
122
+
97
123
  #
98
124
  # Open a connection and execute the SQL statement.
99
125
  # Return the resulting data.
100
126
  #
101
127
  def query( sql, params = nil )
102
- h = {
103
- host: host_value,
104
- database: db_value,
105
- username: user_value,
106
- password: passwd_value
107
- }
108
- client = Mysql2::Client.new( h )
128
+ client = get_client
109
129
 
110
130
  heads = []
111
131
  data = []
@@ -134,6 +154,14 @@ module Gloo
134
154
  return [ heads, data ]
135
155
  end
136
156
 
157
+ #
158
+ # Based on the result set, build a QueryResult object.
159
+ #
160
+ def get_query_result( result )
161
+ return QueryResult.new result[0], result[1]
162
+ end
163
+
164
+
137
165
  # ---------------------------------------------------------------------
138
166
  # Private functions
139
167
  # ---------------------------------------------------------------------
@@ -119,6 +119,14 @@ module Gloo
119
119
  return [ heads, data ]
120
120
  end
121
121
 
122
+ #
123
+ # Based on the result set, build a QueryResult object.
124
+ #
125
+ def get_query_result( result )
126
+ return QueryResult.new result[0], result[1]
127
+ end
128
+
129
+
122
130
  # ---------------------------------------------------------------------
123
131
  # Private functions
124
132
  # ---------------------------------------------------------------------
@@ -16,6 +16,7 @@ module Gloo
16
16
  SQL = 'sql'.freeze
17
17
  RESULT = 'result'.freeze
18
18
  PARAMS = 'params'.freeze
19
+ SIMPLE_LIST = 'simple_list'.freeze
19
20
 
20
21
  DB_MISSING_ERR = 'The database connection is missing!'.freeze
21
22
 
@@ -70,24 +71,69 @@ module Gloo
70
71
  end
71
72
 
72
73
  #
73
- # SSH to the host and execute the command, then update result.
74
+ # Run the query and process the results.
74
75
  #
75
76
  def msg_run
76
77
  db = db_obj
77
- unless db
78
- @engine.err DB_MISSING_ERR
78
+ return unless db
79
+
80
+ begin
81
+ result = db.query( sql_value, param_array )
82
+ process_result( result, db )
83
+ rescue => e
84
+ @engine.err e.message
79
85
  return
80
86
  end
87
+ end
88
+
89
+ #
90
+ # Run the query and return the results.
91
+ #
92
+ def run_query
93
+ db = db_obj
94
+ return unless db
81
95
 
82
96
  begin
97
+ log_query sql_value, param_array
98
+
99
+ db_start = ::Time.now
83
100
  result = db.query( sql_value, param_array )
84
- process_result result
101
+ db_done = ::Time.now
102
+ elapsed = ( ( db_done - db_start ) * 1000.0 ).round(2)
103
+
104
+ app = @engine.running_app
105
+ app.add_db_time elapsed if app
106
+ return result
85
107
  rescue => e
86
108
  @engine.err e.message
87
109
  return
88
110
  end
89
111
  end
90
112
 
113
+ #
114
+ # Write the query to the log.
115
+ #
116
+ def log_query sql, params
117
+ @engine.log.info "QUERY PARAMS: #{params}" if params
118
+ @engine.log.info "QUERY: #{sql}"
119
+ end
120
+
121
+
122
+ # ---------------------------------------------------------------------
123
+ # Output as simple list
124
+ # ---------------------------------------------------------------------
125
+
126
+ #
127
+ # Should the output be put in a simple list?
128
+ #
129
+ def simple_list?
130
+ o = find_child SIMPLE_LIST
131
+ return false unless o
132
+
133
+ return o.value
134
+ end
135
+
136
+
91
137
  # ---------------------------------------------------------------------
92
138
  # Private functions
93
139
  # ---------------------------------------------------------------------
@@ -99,6 +145,12 @@ module Gloo
99
145
  #
100
146
  def db_obj
101
147
  o = find_child DB
148
+
149
+ unless o
150
+ @engine.err DB_MISSING_ERR
151
+ return nil
152
+ end
153
+
102
154
  return Gloo::Objs::Alias.resolve_alias( @engine, o )
103
155
  end
104
156
 
@@ -118,21 +170,24 @@ module Gloo
118
170
  # If there's a result container, we'll create objects in it.
119
171
  # If not, we'll just show the output in the console.
120
172
  #
121
- def process_result( result )
173
+ def process_result( result, db )
122
174
  return if result.nil?
123
175
 
124
- heads = result[0]
125
- data = result[1]
126
- qr = QueryResult.new heads, data
127
- return unless qr.has_data_to_show?
176
+ query_result = db.get_query_result( result )
177
+ return unless query_result
178
+ return unless query_result.has_data_to_show?
128
179
 
129
180
  result_can = find_child RESULT
130
181
  result_can = Gloo::Objs::Alias.resolve_alias( @engine, result_can )
131
182
 
132
183
  if result_can
133
- qr.update_result_container result_can
184
+ if simple_list?
185
+ query_result.update_result_container_simple result_can
186
+ else
187
+ query_result.update_result_container result_can
188
+ end
134
189
  else
135
- qr.show
190
+ query_result.show
136
191
  end
137
192
  end
138
193
 
@@ -98,6 +98,14 @@ module Gloo
98
98
  single_row_result? ? update_single_row : update_rows
99
99
  end
100
100
 
101
+ #
102
+ # Update the result container with the data from the query.
103
+ #
104
+ def update_result_container_simple( in_can )
105
+ @result_can = in_can
106
+ single_row_result? ? update_single_row : update_rows_simple
107
+ end
108
+
101
109
  #
102
110
  # The result has a single row.
103
111
  # Map values from the result set to objects that are present.
@@ -122,7 +130,20 @@ module Gloo
122
130
  end
123
131
  end
124
132
  end
125
-
133
+
134
+ #
135
+ # Put all rows in the result object.
136
+ #
137
+ def update_rows_simple
138
+ @data.each do |row|
139
+ row.each do |val|
140
+ o = @result_can.find_add_child( val, 'untyped' )
141
+ o.set_value val
142
+ end
143
+ end
144
+ end
145
+
146
+
126
147
  # ---------------------------------------------------------------------
127
148
  # Private functions
128
149
  # ---------------------------------------------------------------------
@@ -116,10 +116,25 @@ module Gloo
116
116
  end
117
117
 
118
118
  db = SQLite3::Database.open name
119
- db.results_as_hash = true
120
- return db.query( sql, params )
119
+ # db.results_as_hash = true
120
+ results = db.query( sql, params )
121
+
122
+ return results
123
+ end
124
+
125
+ #
126
+ # Based on the result set, build a QueryResult object.
127
+ #
128
+ def get_query_result( result )
129
+ rows = []
130
+ while ( row = result.next ) do
131
+ rows << row
132
+ end
133
+
134
+ return QueryResult.new( result.columns, rows )
121
135
  end
122
136
 
137
+
123
138
  # ---------------------------------------------------------------------
124
139
  # Private functions
125
140
  # ---------------------------------------------------------------------