Browse Source

fix hot contants

main
pvincent 3 months ago
parent
commit
d7e28381c3
  1. 25
      config/initializers/content_security_policy.rb
  2. 16
      config/initializers/inflections.rb
  3. 14
      config/initializers/monkey_patcher.rb
  4. 13
      config/initializers/permissions_policy.rb
  5. 3
      config/initializers/rails_live_reload.rb
  6. 155
      lib/hot/constants.rb
  7. 20
      lib/monkey_patches/rails_live_reload/watcher.rb

25
config/initializers/content_security_policy.rb

@ -1,25 +0,0 @@
# Be sure to restart your server when you modify this file.
# Define an application-wide content security policy.
# See the Securing Rails Applications Guide for more information:
# https://guides.rubyonrails.org/security.html#content-security-policy-header
# Rails.application.configure do
# config.content_security_policy do |policy|
# policy.default_src :self, :https
# policy.font_src :self, :https, :data
# policy.img_src :self, :https, :data
# policy.object_src :none
# policy.script_src :self, :https
# policy.style_src :self, :https
# # Specify URI for violation reports
# # policy.report_uri "/csp-violation-report-endpoint"
# end
#
# # Generate session nonces for permitted importmap, inline scripts, and inline styles.
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
# config.content_security_policy_nonce_directives = %w(script-src style-src)
#
# # Report violations without enforcing the policy.
# # config.content_security_policy_report_only = true
# end

16
config/initializers/inflections.rb

@ -1,16 +0,0 @@
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, "\\1en"
# inflect.singular /^(ox)en/i, "\\1"
# inflect.irregular "person", "people"
# inflect.uncountable %w( fish sheep )
# end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym "RESTful"
# end

14
config/initializers/monkey_patcher.rb

@ -1,14 +1,14 @@
return unless Rails.application.server?
puts 'MonkeyPatcher runs:'
# puts 'MonkeyPatcher runs:'
patches = Dir.glob(Rails.root.join('lib', 'monkey_patches', '**', '*.rb'))
patches.each do |file|
puts "🐵 patching... #{Pathname.new(file).relative_path_from Rails.root}"
# puts "🐵 patching... #{Pathname.new(file).relative_path_from Rails.root}"
require file
end
puts case patches.count
when 0 then 'No patch found'
when 1 then '1 successful patch applied'
else "#{patches.count} successful patches applied"
end
# puts case patches.count
# when 0 then 'No patch found'
# when 1 then '1 successful patch applied'
# else "#{patches.count} successful patches applied"
# end

13
config/initializers/permissions_policy.rb

@ -1,13 +0,0 @@
# Be sure to restart your server when you modify this file.
# Define an application-wide HTTP permissions policy. For further
# information see: https://developers.google.com/web/updates/2018/06/feature-policy
# Rails.application.config.permissions_policy do |policy|
# policy.camera :none
# policy.gyroscope :none
# policy.microphone :none
# policy.usb :none
# policy.fullscreen :self
# policy.payment :self, "https://secure.example.com"
# end

3
config/initializers/rails_live_reload.rb

@ -1,6 +1,5 @@
# frozen_string_literal: true
if defined?(RailsLiveReload) && Rails.env.development?
RailsLiveReload.configure do |config|
# HOT Constants
config.watch(%r{/\.env$}, reload: :always)

155
lib/hot/constants.rb

@ -1,101 +1,104 @@
require 'dotenv'
# Hot Live Constants
module Hot::Constants
HOTENV = {} # rubocop:disable Style/MutableConstant
LISTENERS = {} # rubocop:disable Style/MutableConstant
LOGGER = SemanticLogger[self]
TOTO = 'titi'
class << self
def initialize
@old_definitions = {}
@hot_definitions = {}
load_definitions
load_values
end
module Hot
# Hot Live Constants
module Constants
include SemanticLogger::Loggable
HOTENV = {} # rubocop:disable Style/MutableConstant
LISTENERS = {} # rubocop:disable Style/MutableConstant
class << self
def initialize
@old_definitions = {}
@hot_definitions = {}
logger.level = :fatal
load_definitions
load_values
logger.level = :info
end
def load_definitions
LOGGER.debug('--load_definitions3')
def load_definitions
logger.debug('--load_definitions3')
new_definitions = Dotenv.parse('.env.sample')
new_definitions = Dotenv.parse('.env.sample')
definitions_to_actualize = {}
@old_definitions.merge(new_definitions) do |key, old_value, new_value|
definitions_to_actualize[key] = new_value if new_value != old_value
end
definitions_to_actualize.each { |key, value| define_method(:actualize, key, value) }
definitions_to_actualize = {}
@old_definitions.merge(new_definitions) do |key, old_value, new_value|
definitions_to_actualize[key] = new_value if new_value != old_value
end
definitions_to_actualize.each { |key, value| define_method(:actualize, key, value) }
@old_definitions = new_definitions
@old_definitions = new_definitions
definitions_to_remove = @hot_definitions.except(*new_definitions.keys)
definitions_to_remove.each_pair do |key, dkey|
logger.info("remove method <#{dkey}>")
singleton_class.undef_method(dkey)
@hot_definitions.delete(key)
end
definitions_to_remove = @hot_definitions.except(*new_definitions.keys)
definitions_to_remove.each_pair do |key, dkey|
LOGGER.info("remove method <#{dkey}>")
singleton_class.undef_method(dkey)
@hot_definitions.delete(key)
definitions_to_add = new_definitions.except(*@hot_definitions.keys)
definitions_to_add.each { |key, value| define_method(:add, key, value) }
end
definitions_to_add = new_definitions.except(*@hot_definitions.keys)
definitions_to_add.each { |key, value| define_method(:add, key, value) }
end
def load_values
logger.debug('--load_values')
def load_values
LOGGER.debug('--load_values')
new_env = Dotenv.parse
constants_to_delete = HOTENV.except(*new_env.keys)
constants_to_delete.each do |name, _|
# FIXME: default should read default and type from @old_definitions
type, default = @old_definitions[name]
logger.info("constant <#{name}> reverts to default value <#{default}> of type <#{type}>")
end
new_env = Dotenv.parse
constants_to_delete = HOTENV.except(*new_env.keys)
constants_to_delete.each do |name, _|
# FIXME: default should read default and type from @old_definitions
type, default = @old_definitions[name]
LOGGER.info("constant <#{name}> reverts to default value <#{default}> of type <#{type}>")
end
constants_to_add = new_env.except(*HOTENV.keys)
constants_to_add.each do |constant|
logger.info("constant to add <#{constant}>")
end
constants_to_add = new_env.except(*HOTENV.keys)
constants_to_add.each do |constant|
LOGGER.info("constant to add <#{constant}>")
HOTENV.replace new_env
# LISTENERS.each_pair { |k, b| perform_change(k, b) }
end
HOTENV.replace new_env
# LISTENERS.each_pair { |k, b| perform_change(k, b) }
end
def on_change(key, &block)
LISTENERS[key.downcase.to_sym] = block
perform_change(key, block)
end
def on_change(key, &block)
LISTENERS[key.downcase.to_sym] = block
perform_change(key, block)
end
private
private
def define_method(mode, key, value)
dkey = key.downcase
method = infer_method_from_value(value)
def define_method(mode, key, value)
dkey = key.downcase
method = infer_method_from_value(value)
inferred_type = method.name.to_s.split('_')[1]
LOGGER.info("#{mode} method <#{dkey}> of type <#{inferred_type}> with default value <#{value}> ")
inferred_type = method.name.to_s.split('_')[1]
logger.info("#{mode} method <#{dkey}> of type <#{inferred_type}> with default value <#{value}> ")
singleton_class.define_method(dkey) { method.call(key, value) }
@hot_definitions.store(key, dkey)
end
singleton_class.define_method(dkey) { method.call(key, value) }
@hot_definitions.store(key, dkey)
end
def perform_change(key, block)
old_value = nil # TODO: remember last previous value
new_value = method(key).call
block.call(new_value, old_value)
end
def perform_change(key, block)
old_value = nil # TODO: remember last previous value
new_value = method(key).call
block.call(new_value, old_value)
end
def load_boolean(key, default) = HOTENV.fetch(key, default).to_s.downcase == 'true'
def load_integer(key, default) = HOTENV.fetch(key, default).to_i
def load_string(key, default) = HOTENV.fetch(key, default)
def load_boolean(key, default) = HOTENV.fetch(key, default).to_s.downcase == 'true'
def load_integer(key, default) = HOTENV.fetch(key, default).to_i
def load_string(key, default) = HOTENV.fetch(key, default)
def infer_method_from_value(value)
case value.downcase
when /^(true|false)$/ then method(:load_boolean)
when /^\d+$/ then method(:load_integer)
else method(:load_string)
def infer_method_from_value(value)
case value.downcase
when /^(true|false)$/ then method(:load_boolean)
when /^\d+$/ then method(:load_integer)
else method(:load_string)
end
end
end
end
initialize # done once on first require, cause this is just a module (not a class!)
initialize # done once on first require, cause this is just a module (not a class!)
end
end

20
lib/monkey_patches/rails_live_reload/watcher.rb

@ -2,10 +2,24 @@ module RailsLiveReload
ENV_FILE = Rails.root.join('.env').to_s
ENV_SAMPLE_FILE = Rails.root.join('.env.sample').to_s
INITIALIZER = Rails.root.join('config/initializers/hot_changes.rb').to_s
CHECKSUMS = {}
CHECKSUMS = {} # rubocop:disable Style/MutableConstant
# MonkeyPath Watcher
class Watcher
def initialize
@files = {}
@sockets = []
# puts "Watching: #{root}"
# RailsLiveReload.patterns.each do |pattern, rule|
# puts " #{pattern} => #{rule}"
# end
build_tree
start_socket
start_listener
end
def reload_all
before_reload(files)
data = { event: RailsLiveReload::INTERNAL[:socket_events][:reload], files: }.to_json
@ -15,8 +29,8 @@ module RailsLiveReload
private
def before_reload(files)
perform_when_change(files, ENV_SAMPLE_FILE) { HotConstants.load_definitions }
perform_when_change(files, ENV_FILE) { HotConstants.load_values }
perform_when_change(files, ENV_SAMPLE_FILE) { Hot::Constants.load_definitions }
perform_when_change(files, ENV_FILE) { Hot::Constants.load_values }
perform_when_change(files, INITIALIZER) { load Rails.root.join('config', 'initializers', 'hot_changes.rb') }
end

Loading…
Cancel
Save