ru.Bee 1.5.4 → 1.7.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 +4 -4
- data/bin/rubee +6 -295
- data/lib/app/views/index.html +1 -1
- data/lib/config/base_configuration.rb +25 -7
- data/lib/db/create_addresses.rb +17 -0
- data/lib/inits/charged_hash.rb +16 -0
- data/lib/inits/charged_string.rb +12 -0
- data/lib/js/app.js +3 -3
- data/lib/package.json +1 -1
- data/lib/rubee/async/fiber_queue.rb +27 -0
- data/lib/rubee/async/thread_async.rb +1 -1
- data/lib/rubee/async/thread_pool.rb +32 -34
- data/lib/rubee/autoload.rb +86 -0
- data/lib/rubee/cli/attach.rb +124 -0
- data/lib/rubee/cli/command.rb +41 -0
- data/lib/rubee/cli/console.rb +39 -0
- data/lib/rubee/cli/db.rb +105 -0
- data/lib/rubee/cli/generate.rb +33 -0
- data/lib/rubee/cli/project.rb +124 -0
- data/lib/rubee/cli/react.rb +28 -0
- data/lib/rubee/cli/routes.rb +18 -0
- data/lib/rubee/cli/server.rb +52 -0
- data/lib/rubee/cli/test.rb +24 -0
- data/lib/rubee/cli/version.rb +15 -0
- data/lib/rubee/configuration.rb +83 -0
- data/lib/rubee/controllers/base_controller.rb +12 -6
- data/lib/rubee/controllers/extensions/auth_tokenable.rb +2 -2
- data/lib/rubee/extensions/hookable.rb +9 -2
- data/lib/rubee/generator.rb +160 -0
- data/lib/rubee/logger.rb +83 -0
- data/lib/rubee/models/database_objectable.rb +1 -1
- data/lib/rubee/models/sequel_object.rb +3 -3
- data/lib/rubee/router.rb +40 -0
- data/lib/rubee.rb +13 -317
- data/lib/tests/async/thread_async_test.rb +9 -5
- data/lib/tests/cli/attach_test.rb +36 -0
- data/lib/tests/{auth_tokenable_test.rb → controllers/auth_tokenable_test.rb} +2 -2
- data/lib/tests/controllers/base_controller_test.rb +23 -0
- data/lib/tests/controllers/hookable_test.rb +220 -0
- data/lib/tests/{rubeeapp_test.rb → controllers/rubeeapp_test.rb} +3 -2
- data/lib/tests/example_models/address.rb +5 -0
- data/lib/tests/example_models/user.rb +1 -0
- data/lib/tests/logger_test.rb +76 -0
- data/lib/tests/{account_model_test.rb → models/account_model_test.rb} +1 -1
- data/lib/tests/{comment_model_test.rb → models/comment_model_test.rb} +13 -1
- data/lib/tests/models/db_objectable_test.rb +21 -0
- data/lib/tests/models/seralizable_test.rb +36 -0
- data/lib/tests/{user_model_test.rb → models/user_model_test.rb} +32 -1
- data/lib/tests/rubee_attach_test.rb +0 -0
- data/lib/tests/test.db +0 -0
- data/lib/tests/test_helper.rb +20 -2
- data/readme.md +174 -15
- metadata +34 -9
- data/lib/app/views/apples_.erb +0 -1
- data/lib/app/views/s_.erb +0 -1
- /data/lib/app/views/{app.tsx → App.tsx} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4ecb77e79daf38768a10a5da26f7f1e3013734c864774e128ffb767d5d6d9a1
|
4
|
+
data.tar.gz: 1f9a6de22160db7ac4deb411278f4bb53bb94ee0a58893a9089a5eb99fd061fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 312f2143e4244dec12bdd6e40a815eeb9a2cf70af31bea3ef2c5211ae4a491dc8532931ca4d0ef4529979d579f2c17e3ade73fd09c3f9f75a0b79697e3c93200
|
7
|
+
data.tar.gz: d53621c81d31e8b7e48b030762d5f58726756e3946da14a2774fd8c6239f96ccb87a4f8d4c533b862981a792a5c90a0755d22a66d6b5b5428d4df75d46ac8265
|
data/bin/rubee
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'fileutils'
|
4
|
-
|
4
|
+
require 'rubygems'
|
5
5
|
require_relative '../lib/inits/print_colors'
|
6
6
|
require_relative '../lib/rubee'
|
7
7
|
|
@@ -19,299 +19,10 @@ LOGO = <<-'LOGO'
|
|
19
19
|
Ver: %s
|
20
20
|
LOGO
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
def print_logo
|
25
|
-
puts "\e[36m#{LOGO % Rubee::VERSION}\e[0m" # Cyan color
|
26
|
-
end
|
27
|
-
|
28
|
-
if command =~ /^(start)$|^(start:(\d+))$/
|
29
|
-
_, port = ARGV.first&.split(':')
|
30
|
-
|
31
|
-
port ||= '7000'
|
32
|
-
print_logo
|
33
|
-
color_puts "Starting takeoff of ruBee server on port #{port}...", color: :yellow
|
34
|
-
exec("rackup #{ENV['RACKUP_FILE']} -p #{port}")
|
35
|
-
elsif command =~ /^(start_dev)$|^(start_dev:(\d+))$/
|
36
|
-
_, port = ARGV.first&.split(':')
|
37
|
-
|
38
|
-
port ||= '7000'
|
39
|
-
print_logo
|
40
|
-
|
41
|
-
color_puts "Starting takeoff of ruBee server on port #{port} in dev mode...", color: :yellow
|
42
|
-
|
43
|
-
exec("rerun -- rackup --port #{port} #{ENV['RACKUP_FILE']}")
|
44
|
-
elsif command == 'stop'
|
45
|
-
exec('pkill -f rubee')
|
46
|
-
elsif command == 'status'
|
47
|
-
exec('ps aux | grep rubee')
|
48
|
-
elsif command == 'react'
|
49
|
-
case ARGV[1]
|
50
|
-
when 'prepare'
|
51
|
-
if Rubee::PROJECT_NAME == 'rubee'
|
52
|
-
exec('cd ./lib && npm run prepare')
|
53
|
-
else
|
54
|
-
exec('npm run prepare')
|
55
|
-
end
|
56
|
-
when 'watch'
|
57
|
-
if Rubee::PROJECT_NAME == 'rubee'
|
58
|
-
exec('cd ./lib && npm run watch')
|
59
|
-
else
|
60
|
-
exec('npm run watch')
|
61
|
-
end
|
62
|
-
else
|
63
|
-
color_puts("Unknown command: #{command}", color: :red)
|
64
|
-
exit(1)
|
65
|
-
end
|
66
|
-
elsif command == 'project'
|
67
|
-
project_name = ARGV[1]
|
68
|
-
if project_name.nil?
|
69
|
-
color_puts 'Please indicate project name.', color: :red
|
70
|
-
exit 1
|
71
|
-
end
|
72
|
-
|
73
|
-
if project_name == 'rubee'
|
74
|
-
color_puts "Error: Project 'rubee' is reserved", color: :red
|
75
|
-
exit 1
|
76
|
-
end
|
77
|
-
|
78
|
-
source_dir = File.expand_path('../lib', __dir__)
|
79
|
-
target_dir = File.expand_path("./#{project_name}", Dir.pwd)
|
80
|
-
|
81
|
-
if Dir.exist?(target_dir)
|
82
|
-
color_puts "Error: Project #{project_name} already exists!", color: :red
|
83
|
-
exit 1
|
84
|
-
end
|
85
|
-
|
86
|
-
# Create target directory
|
87
|
-
FileUtils.mkdir_p(target_dir)
|
88
|
-
|
89
|
-
# Define blacklist
|
90
|
-
blacklist_files = %w[rubee.rb print_colors.rb version.rb config.ru test_helper.rb Gemfile.lock test.yml test.db
|
91
|
-
development.db production.db]
|
92
|
-
blacklist_dirs = %w[rubee tests .git .github .idea node_modules db]
|
93
|
-
|
94
|
-
# Copy files, excluding blacklisted ones
|
95
|
-
Dir.glob("#{source_dir}/**/*", File::FNM_DOTMATCH).each do |file|
|
96
|
-
relative_path = file.sub("#{source_dir}/", '')
|
97
|
-
|
98
|
-
# Skip blacklisted directories
|
99
|
-
next if blacklist_dirs.any? { |dir| relative_path.split('/').include?(dir) }
|
100
|
-
|
101
|
-
# Skip blacklisted files
|
102
|
-
next if blacklist_files.include?(File.basename(file))
|
103
|
-
|
104
|
-
target_path = File.join(target_dir, relative_path)
|
105
|
-
|
106
|
-
if File.directory?(file)
|
107
|
-
FileUtils.mkdir_p(target_path)
|
108
|
-
else
|
109
|
-
FileUtils.cp(file, target_path)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# create tests dir and copy test_helper.rb and user_model_test.rb
|
114
|
-
FileUtils.mkdir_p("#{target_dir}/tests")
|
115
|
-
FileUtils.cp("#{source_dir}/tests/user_model_test.rb", "#{target_dir}/tests/user_model_test.rb")
|
116
|
-
|
117
|
-
# create db dir
|
118
|
-
FileUtils.mkdir_p("#{target_dir}/db")
|
119
|
-
FileUtils.cp("#{source_dir}/db/structure.rb", "#{target_dir}/db/structure.rb")
|
120
|
-
FileUtils.cp("#{source_dir}/db/create_users.rb", "#{target_dir}/db/create_users.rb")
|
121
|
-
|
122
|
-
# create a gemfile context
|
123
|
-
gemfile = <<~GEMFILE
|
124
|
-
source 'https://rubygems.org'
|
125
|
-
|
126
|
-
gem 'ru.Bee'
|
127
|
-
gem 'sequel'
|
128
|
-
gem 'sqlite3'
|
129
|
-
gem 'rake'
|
130
|
-
gem 'rack'
|
131
|
-
gem 'rackup'
|
132
|
-
gem 'pry'
|
133
|
-
gem 'pry-byebug'
|
134
|
-
gem 'puma'
|
135
|
-
gem 'json'
|
136
|
-
|
137
|
-
group :development do
|
138
|
-
gem 'rerun'
|
139
|
-
gem 'minitest'
|
140
|
-
gem 'rack-test'
|
141
|
-
end
|
142
|
-
GEMFILE
|
143
|
-
# create a gemfile
|
144
|
-
File.open("#{target_dir}/Gemfile", 'w') do |file|
|
145
|
-
file.puts gemfile
|
146
|
-
end
|
147
|
-
|
148
|
-
# create test_helper.rb file
|
149
|
-
test_helper = <<~TESTHELPER
|
150
|
-
require "bundler/setup"
|
151
|
-
Bundler.require(:test)
|
152
|
-
|
153
|
-
require 'minitest/autorun'
|
154
|
-
require 'rack/test'
|
155
|
-
require 'rubee'
|
156
|
-
|
157
|
-
Rubee::Autoload.call
|
158
|
-
TESTHELPER
|
159
|
-
|
160
|
-
File.open("#{target_dir}/tests/test_helper.rb", 'w') do |file|
|
161
|
-
file.puts test_helper
|
162
|
-
end
|
163
|
-
|
164
|
-
color_puts "Project #{project_name} created successfully at #{target_dir}", color: :green
|
165
|
-
|
166
|
-
elsif command == 'version'
|
167
|
-
color_puts "ruBee v#{Rubee::VERSION}", color: :yellow
|
168
|
-
elsif command == 'routes'
|
169
|
-
file = Rubee::PROJECT_NAME == 'rubee' ? File.join('/lib', 'config/routes.rb') : 'config/routes.rb'
|
170
|
-
routes = eval(File.read(file))
|
171
|
-
|
172
|
-
puts routes
|
173
|
-
elsif command == 'test'
|
174
|
-
|
175
|
-
ENV['RACK_ENV'] = 'test'
|
176
|
-
file_name = ARGV[1] # Get the first argument
|
177
|
-
lib = Rubee::PROJECT_NAME == 'rubee' ? '/lib' : ''
|
178
|
-
if file_name
|
179
|
-
color_puts "Running #{file_name} test ...", color: :yellow
|
180
|
-
exec("ruby -Itest -e \"require '.#{lib}/tests/#{file_name}'\"")
|
181
|
-
else
|
182
|
-
color_puts 'Running all tests ...', color: :yellow
|
183
|
-
exec("ruby -Itest -e \"Dir.glob('.#{lib}/tests/**/*_test.rb').each { |file| require file }\"")
|
184
|
-
end
|
185
|
-
elsif %w[generate gen].include?(command)
|
186
|
-
method, path = ARGV[1..2]
|
187
|
-
ENV['RACK_ENV'] ||= 'development'
|
188
|
-
file = Rubee::PROJECT_NAME == 'rubee' ? File.join('/lib', 'config/routes.rb') : 'config/routes.rb'
|
189
|
-
routes = eval(File.read(file))
|
190
|
-
route = routes.find { |route| route[:path] == path.to_s && route[:method] == method.to_sym }
|
191
|
-
color_puts("Route not found with path: #{path} and method: #{method}", color: :red) unless route
|
192
|
-
Rubee::Generator.new(
|
193
|
-
route[:model]&.[](:name),
|
194
|
-
route[:model]&.[](:attributes),
|
195
|
-
"#{route[:controller]&.capitalize}Controller",
|
196
|
-
route[:action],
|
197
|
-
react: route[:react]
|
198
|
-
).call
|
199
|
-
elsif command == 'db'
|
200
|
-
Rubee::Autoload.call
|
201
|
-
ENV['RACK_ENV'] ||= 'development'
|
202
|
-
|
203
|
-
command, file_name = ARGV[1]&.split(':')
|
204
|
-
if Rubee::PROJECT_NAME == 'rubee'
|
205
|
-
Rubee::Configuration.setup(env = :test) do |config|
|
206
|
-
config.database_url = { url: 'sqlite://lib/tests/test.db', env: }
|
207
|
-
end
|
208
|
-
Rubee::SequelObject.reconnect! unless command == 'init'
|
209
|
-
end
|
210
|
-
|
211
|
-
def ensure_database_exists(db_url)
|
212
|
-
uri = URI.parse(db_url)
|
213
|
-
case uri.scheme
|
214
|
-
when 'sqlite'
|
215
|
-
begin
|
216
|
-
Sequel.connect(db_url)
|
217
|
-
color_puts("Database #{ENV['RACK_ENV']} exists", color: :cyan)
|
218
|
-
rescue Exception
|
219
|
-
if File.exist?(db_path = db_url.sub(%r{^sqlite://}, ''))
|
220
|
-
color_puts("Database #{ENV['RACK_ENV']} exists", color: :cyan)
|
221
|
-
else
|
222
|
-
Sequel.sqlite(db_path)
|
223
|
-
color_puts("Database #{ENV['RACK_ENV']} created", color: :green)
|
224
|
-
end
|
225
|
-
end
|
226
|
-
when 'postgres'
|
227
|
-
begin
|
228
|
-
Sequel.connect(db_url)
|
229
|
-
color_puts("Database #{ENV['RACK_ENV']} exists", color: :cyan)
|
230
|
-
rescue StandardError => _e
|
231
|
-
con = Sequel.connect(Rubee::Configuration.get_database_url.gsub(%r{(/test|/development|/production)}, ''))
|
232
|
-
con.run("CREATE DATABASE #{ENV['RACK_ENV']}")
|
233
|
-
color_puts("Database #{ENV['RACK_ENV']} created", color: :green)
|
234
|
-
end
|
235
|
-
else
|
236
|
-
color_puts("Unsupported database type: #{db_url}", color: :red)
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
def generate_structure
|
241
|
-
schema_hash = {}
|
242
|
-
|
243
|
-
Rubee::SequelObject::DB.tables.each do |table|
|
244
|
-
schema_hash[table] = {}
|
245
|
-
|
246
|
-
Rubee::SequelObject::DB.schema(table).each do |column, details|
|
247
|
-
schema_hash[table][column] = details
|
248
|
-
end
|
249
|
-
end
|
250
|
-
formatted_hash = JSON.pretty_generate(schema_hash)
|
251
|
-
.gsub(/"(\w+)":/, '\1:') # Convert keys to symbols
|
252
|
-
.gsub(': null', ': nil') # Convert `null` to `nil`
|
253
|
-
|
254
|
-
File.open('db/structure.rb', 'w') do |file|
|
255
|
-
file.puts "STRUCTURE = #{formatted_hash}"
|
256
|
-
end
|
257
|
-
|
258
|
-
color_puts('db/structure.rb updated', color: :green)
|
259
|
-
end
|
260
|
-
|
261
|
-
case command
|
262
|
-
when 'run'
|
263
|
-
Rubee::Autoload.call
|
264
|
-
file_names = if file_name == 'all'
|
265
|
-
lib = Rubee::PROJECT_NAME == 'rubee' ? '/lib' : ''
|
266
|
-
Dir.glob(".#{lib}/db/*.rb").map do |file|
|
267
|
-
File.basename(file, '.rb')
|
268
|
-
end.reject { |file| file == 'structure' }
|
269
|
-
else
|
270
|
-
[file_name]
|
271
|
-
end
|
272
|
-
Rubee::Configuration.envs.each do |env|
|
273
|
-
ENV['RACK_ENV'] = env.to_s
|
274
|
-
file_names.each do |file_name|
|
275
|
-
color_puts("Run #{file_name} file for #{env} env", color: :cyan)
|
276
|
-
Object.const_get(file_name.split('_').map(&:capitalize).join).new.call
|
277
|
-
end
|
278
|
-
end
|
279
|
-
color_puts("Migration for #{file_name} completed", color: :green)
|
280
|
-
unless Rubee::PROJECT_NAME == 'rubee'
|
281
|
-
color_puts('Regenerate schema file', color: :cyan)
|
282
|
-
generate_structure
|
283
|
-
end
|
284
|
-
when 'init'
|
285
|
-
ensure_database_exists(Rubee::Configuration.get_database_url)
|
286
|
-
when 'structure'
|
287
|
-
generate_structure
|
288
|
-
else
|
289
|
-
color_puts("Unknown command: #{command}", color: :red)
|
290
|
-
end
|
291
|
-
elsif ['console'].include?(command)
|
292
|
-
ARGV.clear
|
293
|
-
ENV['RACK_ENV'] ||= 'development'
|
294
|
-
|
295
|
-
Rubee::Autoload.call
|
296
|
-
if Rubee::PROJECT_NAME == 'rubee'
|
297
|
-
Rubee::Configuration.setup(env = :test) do |config|
|
298
|
-
config.database_url = { url: 'sqlite://lib/tests/test.db', env: }
|
299
|
-
end
|
300
|
-
Rubee::Autoload.call
|
301
|
-
Rubee::SequelObject.reconnect!
|
302
|
-
end
|
303
|
-
|
304
|
-
def reload
|
305
|
-
app_files = Dir["./#{Rubee::APP_ROOT}/**/*.rb"]
|
306
|
-
app_files.each { |file| load(file) }
|
307
|
-
color_puts('Reloaded ..', color: :green)
|
308
|
-
end
|
309
|
-
begin
|
310
|
-
# Start IRB
|
311
|
-
IRB.start
|
312
|
-
rescue Exception
|
313
|
-
IRB.start
|
314
|
-
end
|
22
|
+
if ['version', 'react', 'project'].include?(ARGV[0])
|
23
|
+
Rubee::Autoload.call([], white_list_dirs: ['rubee/cli'])
|
315
24
|
else
|
316
|
-
|
25
|
+
Rubee::Autoload.call
|
317
26
|
end
|
27
|
+
|
28
|
+
Rubee::CLI::Command.new(ARGV).call
|
data/lib/app/views/index.html
CHANGED
@@ -1,23 +1,41 @@
|
|
1
1
|
Rubee::Configuration.setup(env = :development) do |config|
|
2
2
|
config.database_url = { url: 'sqlite://db/development.db', env: }
|
3
|
-
config.thread_pool_limit = { env:, value: 5 }
|
4
3
|
|
5
|
-
|
6
|
-
# config.
|
4
|
+
## configure hybrid thread pooling params
|
5
|
+
# config.threads_limit = { env:, value: 4 }
|
6
|
+
# config.fibers_limit = { env:, value: 4 }
|
7
|
+
|
8
|
+
# Flag on react as a view
|
9
|
+
# config.react = { on: true, env: } # required if you want to use react
|
10
|
+
|
11
|
+
## configure logger
|
12
|
+
# config.logger = { logger: MyLogger, env: }
|
7
13
|
end
|
8
14
|
|
9
15
|
Rubee::Configuration.setup(env = :test) do |config|
|
10
16
|
config.database_url = { url: 'sqlite://db/test.db', env: }
|
11
|
-
config.thread_pool_limit = { env:, value: 5 }
|
12
17
|
|
13
|
-
|
18
|
+
## configure hybrid thread pooling params
|
19
|
+
# config.threads_limit = { env:, value: 4 }
|
20
|
+
# config.fibers_limit = { env:, value: 4 }
|
21
|
+
|
22
|
+
## Flag on react as a view
|
14
23
|
# config.react = { on: true, env: } # required if you want to use react
|
24
|
+
|
25
|
+
## configure logger
|
26
|
+
# config.logger = { logger: MyLogger, env: }
|
15
27
|
end
|
16
28
|
|
17
29
|
Rubee::Configuration.setup(env = :production) do |config|
|
18
30
|
config.database_url = { url: 'sqlite://db/production.db', env: }
|
19
|
-
config.thread_pool_limit = { env:, value: 5 }
|
20
31
|
|
21
|
-
|
32
|
+
## configure hybrid thread pooling params
|
33
|
+
# config.threads_limit = { env:, value: 4 }
|
34
|
+
# config.fibers_limit = { env:, value: 4 }
|
35
|
+
|
36
|
+
## Flag on react as a view
|
22
37
|
# config.react = { on: true, env: } # required if you want to use react
|
38
|
+
|
39
|
+
## configure logger
|
40
|
+
# config.logger = { logger: MyLogger, env: }
|
23
41
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class CreateAddresses
|
2
|
+
def call
|
3
|
+
return if Rubee::SequelObject::DB.tables.include?(:addresses)
|
4
|
+
|
5
|
+
Rubee::SequelObject::DB.create_table(:addresses) do
|
6
|
+
primary_key(:id)
|
7
|
+
String(:city)
|
8
|
+
String(:state)
|
9
|
+
String(:zip)
|
10
|
+
String(:street)
|
11
|
+
String(:apt)
|
12
|
+
foreign_key(:user_id, :users)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Address.create(street: '13th Ave', city: 'NY', state: 'NY', zip: '55555', user_id: User.all.first.id)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ChargedHash
|
2
|
+
refine Hash do
|
3
|
+
def [](key)
|
4
|
+
return wrap(super(key)) if key?(key)
|
5
|
+
|
6
|
+
alt_key = key.is_a?(Symbol) ? key.to_s : key.to_sym
|
7
|
+
wrap(super(alt_key))
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def wrap(value)
|
13
|
+
value.is_a?(Hash) ? value.extend(ChargedHash) : value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/inits/charged_string.rb
CHANGED
@@ -20,6 +20,18 @@ module ChargedString
|
|
20
20
|
!plural?
|
21
21
|
end
|
22
22
|
|
23
|
+
def camelize
|
24
|
+
self.split('_').map { _1.capitalize }.join
|
25
|
+
end
|
26
|
+
|
27
|
+
def snakeize
|
28
|
+
self.gsub(/::/, '_')
|
29
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
30
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
31
|
+
.tr('-', '_')
|
32
|
+
.downcase
|
33
|
+
end
|
34
|
+
|
23
35
|
def singularize
|
24
36
|
if end_with?('ies') && length > 3
|
25
37
|
"#{self[0..-4]}y" # Convert "ies" to "y"
|
data/lib/js/app.js
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
import React from "react";
|
2
2
|
import { createRoot } from "react-dom/client";
|
3
|
-
import { App } from "../app/views/
|
3
|
+
import { App } from "../app/views/App.tsx";
|
4
4
|
|
5
5
|
document.addEventListener("DOMContentLoaded", () => {
|
6
|
-
const container = document.getElementById("
|
6
|
+
const container = document.getElementById("App");
|
7
7
|
if (container) {
|
8
8
|
const root = createRoot(container);
|
9
9
|
root.render(<App />);
|
10
10
|
} else {
|
11
|
-
console.error('React root element "#
|
11
|
+
console.error('React root element "#App" not found in DOM.');
|
12
12
|
}
|
13
13
|
});
|
data/lib/package.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"scripts": {
|
3
3
|
"build": "node esbuild.config.js",
|
4
4
|
"watch": "node esbuild.config.js --watch",
|
5
|
-
"prepare": "npm install react react-dom react-router-dom esbuild-plugin-inline-css"
|
5
|
+
"prepare": "npm install esbuild react react-dom react-router-dom esbuild-plugin-inline-css"
|
6
6
|
},
|
7
7
|
"dependencies": {
|
8
8
|
"react": "^18.3.1",
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class FiberQueue
|
2
|
+
def initialize
|
3
|
+
@fibers = []
|
4
|
+
end
|
5
|
+
|
6
|
+
def add(task, args = {})
|
7
|
+
fiber = Fiber.new do
|
8
|
+
task.new.perform(**args)
|
9
|
+
rescue => e
|
10
|
+
puts "Fiber Error: #{e.message}"
|
11
|
+
end
|
12
|
+
@fibers << fiber
|
13
|
+
end
|
14
|
+
|
15
|
+
def fan_out!
|
16
|
+
while @fibers.any?(&:alive?)
|
17
|
+
@fibers.each do |fiber|
|
18
|
+
fiber.resume if fiber.alive?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def done?
|
24
|
+
@fibers.none?(&:alive?)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Rubee
|
2
2
|
class ThreadAsync
|
3
3
|
def perform_async(**args)
|
4
|
-
color_puts('WARN: ThreadAsync engine is
|
4
|
+
color_puts('WARN: ThreadAsync engine is experimental!', color: :yellow)
|
5
5
|
ThreadPool.instance.enqueue(args[:_class], args[:options])
|
6
6
|
end
|
7
7
|
end
|
@@ -3,58 +3,56 @@ require 'singleton'
|
|
3
3
|
module Rubee
|
4
4
|
class ThreadPool
|
5
5
|
include Singleton
|
6
|
-
|
6
|
+
THREADS_LIMIT = Rubee::Configuration.get_threads_limit || 4 unless defined?(THREADS_LIMIT)
|
7
|
+
FIBERS_LIMIT = Rubee::Configuration.get_fibers_limit || 4 unless defined?(FIBERS_LIMIT)
|
7
8
|
|
8
9
|
def initialize
|
9
|
-
@
|
10
|
-
@
|
10
|
+
@tasks = Queue.new
|
11
|
+
@threads = []
|
11
12
|
@running = true
|
12
|
-
|
13
|
-
end
|
13
|
+
@mutex = Mutex.new
|
14
14
|
|
15
|
-
|
16
|
-
@queue << { task: task, args: args }
|
17
|
-
run_next
|
15
|
+
spawn_workers
|
18
16
|
end
|
19
17
|
|
20
|
-
def
|
21
|
-
@
|
22
|
-
run_next
|
18
|
+
def enqueue(task, args = {})
|
19
|
+
@tasks << [task, args]
|
23
20
|
end
|
24
21
|
|
25
22
|
def shutdown
|
26
23
|
@running = false
|
27
|
-
@
|
24
|
+
THREADS_LIMIT.times { @tasks << :shutdown } # Unblock threads
|
25
|
+
@threads.each(&:join)
|
28
26
|
end
|
29
27
|
|
30
28
|
private
|
31
29
|
|
32
|
-
def run_next
|
33
|
-
@workers.each do |fiber|
|
34
|
-
fiber.resume if fiber.alive? && !@queue.empty?
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
30
|
def spawn_workers
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
31
|
+
THREADS_LIMIT.times do
|
32
|
+
@threads << Thread.new do
|
33
|
+
while @running && (task = @tasks.pop)
|
34
|
+
break if task == :shutdown
|
35
|
+
|
36
|
+
fiber_queue = FiberQueue.new
|
37
|
+
fiber_queue.add(*task)
|
38
|
+
|
39
|
+
# pull more to fill the chunk
|
40
|
+
FIBERS_LIMIT.times do
|
41
|
+
next_task = begin
|
42
|
+
@mutex.synchronize { @tasks.pop(true) }
|
43
|
+
rescue
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
fiber_queue.add(*next_task) if next_task
|
47
|
+
end
|
48
|
+
|
49
|
+
until fiber_queue.done?
|
50
|
+
fiber_queue.fan_out!
|
53
51
|
end
|
52
|
+
|
53
|
+
sleep(0.05)
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
57
|
-
@workers << fiber
|
58
56
|
end
|
59
57
|
end
|
60
58
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Rubee
|
2
|
+
class Autoload
|
3
|
+
class << self
|
4
|
+
def call(black_list = [], **options)
|
5
|
+
load_whitelisted(options[:white_list_dirs]) && return if options[:white_list_dirs]
|
6
|
+
# autoload all rbs
|
7
|
+
root_directory = File.join(Rubee::ROOT_PATH, '/lib')
|
8
|
+
priority_order_require(root_directory, black_list)
|
9
|
+
# ensure sequel object is connected
|
10
|
+
Rubee::SequelObject.reconnect!
|
11
|
+
|
12
|
+
Dir.glob(File.join(Rubee::APP_ROOT, '**', '*.rb')).sort.each do |file|
|
13
|
+
base_name = File.basename(file)
|
14
|
+
|
15
|
+
unless base_name.end_with?('_test.rb') || (black_list + ['rubee.rb', 'test_helper.rb']).include?(base_name)
|
16
|
+
require_relative file
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def load_whitelisted(white_list_dirs)
|
22
|
+
white_list_dirs.each do |dir|
|
23
|
+
Dir[File.join(Rubee::ROOT_PATH, '/lib', "#{dir}/**", '*.rb')].each do |file|
|
24
|
+
require_relative file
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def priority_order_require(root_directory, black_list)
|
30
|
+
# rubee inits
|
31
|
+
Dir[File.join(root_directory, 'inits/**', '*.rb')].each do |file|
|
32
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
33
|
+
end
|
34
|
+
# app inits
|
35
|
+
Dir[File.join(Rubee::APP_ROOT, 'inits/**', '*.rb')].each do |file|
|
36
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
37
|
+
end
|
38
|
+
# rubee async
|
39
|
+
Dir[File.join(root_directory, 'rubee/async/**', '*.rb')].each do |file|
|
40
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
41
|
+
end
|
42
|
+
# app config and routes
|
43
|
+
unless black_list.include?('base_configuration.rb')
|
44
|
+
require_relative File.join(Rubee::APP_ROOT, Rubee::LIB,
|
45
|
+
'config/base_configuration')
|
46
|
+
end
|
47
|
+
# This is necessary prerequisitedb init step
|
48
|
+
if Rubee::PROJECT_NAME == 'rubee'
|
49
|
+
Rubee::Configuration.setup(env = :test) do |config|
|
50
|
+
config.database_url = { url: 'sqlite://lib/tests/test.db', env: }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
require_relative File.join(Rubee::APP_ROOT, Rubee::LIB, 'config/routes') unless black_list.include?('routes.rb')
|
55
|
+
# rubee extensions
|
56
|
+
Dir[File.join(root_directory, 'rubee/extensions/**', '*.rb')].each do |file|
|
57
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
58
|
+
end
|
59
|
+
# rubee controllers
|
60
|
+
Dir[File.join(root_directory, 'rubee/controllers/middlewares/**', '*.rb')].each do |file|
|
61
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
62
|
+
end
|
63
|
+
Dir[File.join(root_directory, 'rubee/controllers/extensions/**', '*.rb')].each do |file|
|
64
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
65
|
+
end
|
66
|
+
unless black_list.include?('base_controller.rb')
|
67
|
+
require_relative File.join(root_directory,
|
68
|
+
'rubee/controllers/base_controller')
|
69
|
+
end
|
70
|
+
# rubee models
|
71
|
+
unless black_list.include?('database_objectable.rb')
|
72
|
+
require_relative File.join(root_directory,
|
73
|
+
'rubee/models/database_objectable')
|
74
|
+
end
|
75
|
+
return if black_list.include?('sequel_object.rb')
|
76
|
+
|
77
|
+
require_relative File.join(root_directory,
|
78
|
+
'rubee/models/sequel_object')
|
79
|
+
|
80
|
+
Dir[File.join(root_directory, 'rubee/cli/**', '*.rb')].each do |file|
|
81
|
+
require_relative file
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|