gloo 3.1.1 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
  # ---------------------------------------------------------------------