Module: Pakyow
- Extended by:
- Support::ClassState, Support::DeepFreeze
- Includes:
- Behavior::Initializers, Behavior::InputParsing, Behavior::Plugins, Behavior::Restarting, Behavior::Running, Behavior::Silencing, Behavior::Timezone, Behavior::Verifier, Behavior::Watching, Config, Support::Configurable, Support::Hookable, Support::Pipeline
- Defined in:
- lib/pakyow/environment.rb,
lib/pakyow/cli.rb,
lib/pakyow/info.rb,
lib/pakyow/task.rb,
lib/pakyow/error.rb,
lib/pakyow/types.rb,
lib/pakyow/config.rb,
lib/pakyow/errors.rb,
lib/pakyow/helper.rb,
lib/pakyow/loader.rb,
lib/pakyow/logger.rb,
lib/pakyow/plugin.rb,
lib/pakyow/version.rb,
lib/pakyow/verifier.rb,
lib/pakyow/endpoints.rb,
lib/pakyow/framework.rb,
lib/pakyow/generator.rb,
lib/pakyow/operation.rb,
lib/pakyow/validator.rb,
lib/pakyow/connection.rb,
lib/pakyow/application.rb,
lib/pakyow/plugin/state.rb,
lib/pakyow/plugin/lookup.rb,
lib/pakyow/actions/logger.rb,
lib/pakyow/process_manager.rb,
lib/pakyow/processes/proxy.rb,
lib/pakyow/actions/dispatch.rb,
lib/pakyow/behavior/plugins.rb,
lib/pakyow/behavior/running.rb,
lib/pakyow/logger/colorizer.rb,
lib/pakyow/logger/formatter.rb,
lib/pakyow/processes/server.rb,
lib/pakyow/behavior/timezone.rb,
lib/pakyow/behavior/verifier.rb,
lib/pakyow/behavior/watching.rb,
lib/pakyow/connection/params.rb,
lib/pakyow/logger/timekeeper.rb,
lib/pakyow/validations/email.rb,
lib/pakyow/actions/normalizer.rb,
lib/pakyow/application/config.rb,
lib/pakyow/behavior/silencing.rb,
lib/pakyow/generators/project.rb,
lib/pakyow/logger/destination.rb,
lib/pakyow/logger/multiplexed.rb,
lib/pakyow/rack/compatibility.rb,
lib/pakyow/validations/inline.rb,
lib/pakyow/validations/length.rb,
lib/pakyow/behavior/restarting.rb,
lib/pakyow/connection/statuses.rb,
lib/pakyow/logger/thread_local.rb,
lib/pakyow/actions/input_parser.rb,
lib/pakyow/plugin/helper_caller.rb,
lib/pakyow/validations/presence.rb,
lib/pakyow/behavior/initializers.rb,
lib/pakyow/behavior/verification.rb,
lib/pakyow/application/connection.rb,
lib/pakyow/behavior/input_parsing.rb,
lib/pakyow/logger/formatters/json.rb,
lib/pakyow/validations/acceptance.rb,
lib/pakyow/application/helpers/app.rb,
lib/pakyow/connection/query_parser.rb,
lib/pakyow/logger/formatters/human.rb,
lib/pakyow/logger/formatters/logfmt.rb,
lib/pakyow/connection/multipart_input.rb,
lib/pakyow/connection/multipart_parser.rb,
lib/pakyow/application/behavior/aspects.rb,
lib/pakyow/application/behavior/helpers.rb,
lib/pakyow/application/behavior/plugins.rb,
lib/pakyow/application/behavior/pipeline.rb,
lib/pakyow/application/behavior/rescuing.rb,
lib/pakyow/application/behavior/sessions.rb,
lib/pakyow/application/behavior/endpoints.rb,
lib/pakyow/application/behavior/isolating.rb,
lib/pakyow/application/helpers/connection.rb,
lib/pakyow/application/behavior/frameworks.rb,
lib/pakyow/application/behavior/operations.rb,
lib/pakyow/application/behavior/restarting.rb,
lib/pakyow/application/behavior/initializers.rb,
lib/pakyow/application/connection/session/base.rb,
lib/pakyow/application/connection/session/cookie.rb,
lib/pakyow/application/connection/behavior/values.rb,
lib/pakyow/application/connection/behavior/session.rb,
lib/pakyow/application/connection/behavior/verifier.rb
Overview
Pakyow environment for running one or more rack apps. Multiple apps can be mounted in the environment, each one handling requests at some path.
Pakyow.configure do
mount Pakyow::Application, at: "/"
end
Configuration
The environment can be configured
Pakyow.configure do
config.server.port = 2001
end
It’s possible to configure environments differently.
Pakyow.configure :development do
config.server.host = "pakyow.dev"
end
Hooks
Hooks can be defined for the following events:
- load
- configure
- setup
- boot
- shutdown
- run
Here’s how to log a message after boot:
Pakyow.after "boot" do
logger.info "booted"
end
Logging
The environment contains a global general-purpose logger. It also provides a RequestLogger instance to each app for logging during a request.
Setup & Running
The environment can be setup and then run.
Pakyow.setup(env: :development).run
Defined Under Namespace
Modules: Actions, Behavior, Config, Generators, Helper, Processes, Rack, Types, Validations Classes: Application, CLI, Connection, Endpoint, Endpoints, Error, Framework, Generator, InvalidData, Loader, Logger, Operation, Plugin, ProcessManager, Task, UnknownCommand, UnknownFramework, UnknownHelperContext, UnknownPlugin, UnknownType, UnknownValidationError, Validator, Verifier
Constant Summary collapse
- VERSION =
Pakyow’s current version.
"1.0.6"
Class Attribute Summary collapse
-
.env ⇒ Object
readonly
Name of the environment.
-
.error ⇒ Object
readonly
Any error encountered during the boot process.
Class Method Summary collapse
- .app(app_name, path: "/", without: [], only: nil, mount: true, &block) ⇒ Object
-
.boot(unsafe: false) ⇒ Object
Boots the environment without running it.
-
.booted? ⇒ Boolean
Returns true if the environment has booted.
- .call(input) ⇒ Object
- .env?(name) ⇒ Boolean
-
.global_logger ⇒ Object
Global log output.
-
.info ⇒ Object
Returns information about the environment.
- .initialize_app_for_mount(mount) ⇒ Object private
-
.load ⇒ Object
Loads the Pakyow environment for the current project.
-
.load_apps ⇒ Object
Loads apps located in the current project.
- .load_tasks ⇒ Object private
-
.logger ⇒ Object
Logger instance for the environment.
-
.mount(app, at:, &block) ⇒ Object
Mounts an app at a path.
- .register_framework(framework_name, framework_module) ⇒ Object
-
.setup(env: nil) ⇒ Object
Prepares the environment for booting.
Class Attribute Details
.env ⇒ Object (readonly)
Name of the environment
137 138 139 |
# File 'lib/pakyow/environment.rb', line 137 def env @env end |
.error ⇒ Object (readonly)
Any error encountered during the boot process
141 142 143 |
# File 'lib/pakyow/environment.rb', line 141 def error @error end |
Class Method Details
.app(app_name, path: "/", without: [], only: nil, mount: true, &block) ⇒ Object
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 |
# File 'lib/pakyow/environment.rb', line 289 def app(app_name, path: "/", without: [], only: nil, mount: true, &block) app_name = app_name.to_sym if booted? @apps.find { |app| app.config.name == app_name } else local_frameworks = (only || frameworks.keys) - Array.ensure(without) Pakyow::Application.make(Support::ObjectName.namespace(app_name, "application")) { config.name = app_name include_frameworks(*local_frameworks) }.tap do |app| app.define(&block) if block_given? mount(app, at: path) if mount end end end |
.boot(unsafe: false) ⇒ Object
Boots the environment without running it.
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/pakyow/environment.rb', line 248 def boot(unsafe: false) ensure_setup_succeeded performing :boot do # Tasks should only be available before boot. # @tasks = [] unless unsafe # Mount each app. # @apps = mounts.map { |mount| initialize_app_for_mount(mount) } # Create the callable pipeline. # @pipeline = Pakyow.__pipeline.callable(self) # Set the environment as booted ahead of telling each app that it is booted. This allows an # app's after boot hook to access the booted app through `Pakyow.app`. # @booted = true # Now tell each app that it has been booted. # @apps.select { |app| app.respond_to?(:booted) }.each(&:booted) end if config.freeze_on_boot deep_freeze unless unsafe end self rescue StandardError => error handle_boot_failure(error) end |
.booted? ⇒ Boolean
Returns true if the environment has booted.
242 243 244 |
# File 'lib/pakyow/environment.rb', line 242 def booted? @booted == true end |
.call(input) ⇒ Object
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/pakyow/environment.rb', line 313 def call(input) config.connection_class.new(input).yield_self { |connection| Async(logger: connection.logger) { # Set the request logger as a thread-local variable for when there's no other way to access # it. This originated when looking for a way to log queries with the request logger. By # setting the request logger for the current connection as thread-local we can create a # connection pointing to `Pakyow.logger`, an instance of `Pakyow::Logger::ThreadLocal`. The # thread local logger decides at the time of logging which logger to use based on an # available context, falling back to `Pakyow.global_logger`. This gets us around needing to # configure a connection per request, altering Sequel's internals, and other oddities. # # Pakyow is designed so that the connection object and its logger should always be available # anywhere you need it. If it isn't, reconsider the design before using the thread local. # Thread.current[:pakyow_logger] = connection.logger catch :halt do @pipeline.call(connection) end }.wait }.finalize rescue StandardError => error Pakyow.logger.houston(error) Async::HTTP::Protocol::Response.new( nil, 500, {}, Async::HTTP::Body::Buffered.wrap( StringIO.new("500 Low-Level Server Error") ) ) end |
.env?(name) ⇒ Boolean
309 310 311 |
# File 'lib/pakyow/environment.rb', line 309 def env?(name) env == name.to_sym end |
.global_logger ⇒ Object
Global log output.
Builds and returns a default global output that’s replaced in ‘setup`.
147 148 149 150 151 152 153 154 155 156 |
# File 'lib/pakyow/environment.rb', line 147 def global_logger unless defined?(@global_logger) require "pakyow/logger/formatters/human" @global_logger = Logger::Formatters::Human.new( Logger::Destination.new(:stdout, $stdout) ) end @global_logger end |
.info ⇒ Object
Returns information about the environment.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/pakyow/info.rb', line 8 def self.info { versions: { ruby: "v#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})", pakyow: "v#{VERSION}" }, apps: Pakyow.mounts.map { |mount| { mount_path: mount[:path], class: mount[:app].to_s, reference: mount[:app].config.name.inspect, frameworks: mount[:app].config.loaded_frameworks, app_root: File.(mount[:app].config.root) } } } end |
.initialize_app_for_mount(mount) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
357 358 359 360 361 362 363 |
# File 'lib/pakyow/environment.rb', line 357 def initialize_app_for_mount(mount) if mount[:app].ancestors.include?(Pakyow::Application) mount[:app].new(env, mount_path: mount[:path], &mount[:block]) else mount[:app].new end end |
.load ⇒ Object
Loads the Pakyow environment for the current project.
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/pakyow/environment.rb', line 180 def load performing :load do if File.exist?(config.loader_path + ".rb") require config.loader_path else require "pakyow/integrations/bundler/setup" require "pakyow/integrations/bootsnap" require "pakyow/integrations/bundler/require" require "pakyow/integrations/dotenv" require config.environment_path load_apps end end end |
.load_apps ⇒ Object
Loads apps located in the current project.
200 201 202 |
# File 'lib/pakyow/environment.rb', line 200 def load_apps require File.join(config.root, "config/application") end |
.load_tasks ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
345 346 347 348 349 350 351 352 353 354 |
# File 'lib/pakyow/environment.rb', line 345 def load_tasks require "rake" require "pakyow/task" @tasks = config.tasks.paths.uniq.each_with_object([]) do |tasks_path, tasks| Dir.glob(File.join(File.(tasks_path), "**/*.rake")).each do |task_path| tasks.concat(Pakyow::Task::Loader.new(task_path).__tasks) end end end |
.logger ⇒ Object
Logger instance for the environment.
Builds and returns a default logger that’s replaced in ‘setup`.
162 163 164 |
# File 'lib/pakyow/environment.rb', line 162 def logger @logger ||= Logger.new("dflt", output: global_logger, level: :all) end |
.mount(app, at:, &block) ⇒ Object
Mounts an app at a path.
The app can be any rack endpoint, but must implement an initializer like Pakyow::Application#initialize.
174 175 176 |
# File 'lib/pakyow/environment.rb', line 174 def mount(app, at:, &block) mounts << { app: app, block: block, path: at } end |
.register_framework(framework_name, framework_module) ⇒ Object
285 286 287 |
# File 'lib/pakyow/environment.rb', line 285 def register_framework(framework_name, framework_module) @frameworks[framework_name] = framework_module end |
.setup(env: nil) ⇒ Object
Prepares the environment for booting.
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/pakyow/environment.rb', line 208 def setup(env: nil) @env = (env ||= config.default_env).to_sym load performing :configure do configure!(env) $LOAD_PATH.unshift(config.lib) end performing :setup do destinations = Logger::Multiplexed.new( *config.logger.destinations.map { |destination, io| io.sync = config.logger.sync Logger::Destination.new(destination, io) } ) @global_logger = config.logger.formatter.new(destinations) @logger = Logger::ThreadLocal.new( Logger.new("pkyw", output: @global_logger, level: config.logger.level) ) Console.logger = Logger.new("asnc", output: @global_logger, level: :warn) end self rescue => error @setup_error = error; self end |