M .crystal-version => .crystal-version +1 -1
@@ 1,1 1,1 @@
-0.36.1
+1.2.1
M .tool-versions => .tool-versions +1 -1
@@ 1,2 1,2 @@
nodejs 12.14.1
-crystal 1.0.0
+crystal 1.2.1
A config/application.cr => config/application.cr +9 -0
@@ 0,0 1,9 @@
+module Application
+ Habitat.create do
+ setting name : String
+ end
+end
+
+Application.configure do |settings|
+ settings.name = "Scribe"
+end
M config/authentic.cr => config/authentic.cr +2 -1
@@ 3,7 3,8 @@ require "./server"
Authentic.configure do |settings|
settings.secret_key = Lucky::Server.settings.secret_key_base
- unless Lucky::Env.production?
+ unless LuckyEnv.production?
+ # This value can be between 4 and 31
fastest_encryption_possible = 4
settings.encryption_cost = fastest_encryption_possible
end
M config/colors.cr => config/colors.cr +1 -1
@@ 1,4 1,4 @@
# This enables the color output when in development or test
# Check out the Colorize docs for more information
# https://crystal-lang.org/api/Colorize.html
-Colorize.enabled = Lucky::Env.development? || Lucky::Env.test?
+Colorize.enabled = LuckyEnv.development? || LuckyEnv.test?
M config/database.cr => config/database.cr +7 -3
@@ 1,7 1,7 @@
-database_name = "scribe_#{Lucky::Env.name}"
+database_name = "scribe_#{LuckyEnv.environment}"
AppDatabase.configure do |settings|
- if Lucky::Env.production?
+ if LuckyEnv.production?
settings.credentials = Avram::Credentials.parse(ENV["DATABASE_URL"])
else
settings.credentials = Avram::Credentials.parse?(ENV["DATABASE_URL"]?) || Avram::Credentials.new(
@@ 16,5 16,9 @@ end
Avram.configure do |settings|
settings.database_to_migrate = AppDatabase
- settings.lazy_load_enabled = Lucky::Env.production?
+ settings.lazy_load_enabled = LuckyEnv.production?
+
+ # Always parse `Time` values with these specific formats.
+ # Used for both database values, and datetime input fields.
+ # settings.time_formats << "%F"
end
M config/env.cr => config/env.cr +3 -24
@@ 1,24 1,3 @@
-module Lucky::Env
- extend self
-
- {% for env in [:development, :test, :production] %}
- def {{ env.id }}?
- name == {{ env.id.stringify }}
- end
- {% end %}
-
- def name
- ENV["LUCKY_ENV"]? || "development"
- end
-
- # Returns true if a task is being run through the `lucky` cli
- #
- # Use this method to only run (or avoid running) code when a task is executed.
- def task?
- ENV["LUCKY_TASK"]? == "true"
- end
-
- def use_local?
- ENV.fetch("USE_LOCAL", "false") == "true"
- end
-end
+# Environments are managed using `LuckyEnv`. By default, development, production
+# and test are supported. See
+# https://luckyframework.org/guides/getting-started/configuration for details.
M config/error_handler.cr => config/error_handler.cr +1 -1
@@ 1,3 1,3 @@
Lucky::ErrorHandler.configure do |settings|
- settings.show_debug_output = !Lucky::Env.production?
+ settings.show_debug_output = !LuckyEnv.production?
end
M config/html_page.cr => config/html_page.cr +1 -1
@@ 1,3 1,3 @@
Lucky::HTMLPage.configure do |settings|
- settings.render_component_comments = !Lucky::Env.production?
+ settings.render_component_comments = !LuckyEnv.production?
end
M config/log.cr => config/log.cr +3 -3
@@ 1,13 1,13 @@
require "file_utils"
-if Lucky::Env.test?
+if LuckyEnv.test?
# Logs to `tmp/test.log`
FileUtils.mkdir_p("tmp")
backend = Log::IOBackend.new(File.new("tmp/test.log", mode: "w"))
backend.formatter = Lucky::PrettyLogFormatter.proc
Log.dexter.configure(:debug, backend)
-elsif Lucky::Env.production?
+elsif LuckyEnv.production?
backend = Log::IOBackend.new
backend.formatter = Dexter::JSONLogFormatter.proc
Log.dexter.configure(:info, backend)
@@ 26,7 26,7 @@ Avram::QueryLog.dexter.configure(:none)
# Skip logging static assets requests in development
Lucky::LogHandler.configure do |settings|
- if Lucky::Env.development?
+ if LuckyEnv.development?
settings.skip_if = ->(context : HTTP::Server::Context) {
context.request.method.downcase == "get" &&
context.request.resource.starts_with?(/\/css\/|\/js\/|\/assets\/|\/favicon\.ico/)
M config/route_helper.cr => config/route_helper.cr +1 -1
@@ 1,5 1,5 @@
Lucky::RouteHelper.configure do |settings|
- if Lucky::Env.production?
+ if LuckyEnv.production?
# Example: https://my_app.com
settings.base_uri = ENV.fetch("APP_DOMAIN")
else
M config/server.cr => config/server.cr +12 -2
@@ 1,5 1,5 @@
Lucky::Server.configure do |settings|
- if Lucky::Env.production?
+ if LuckyEnv.production?
settings.secret_key_base = secret_key_from_env
settings.host = "0.0.0.0"
settings.port = ENV["PORT"].to_i
@@ 19,13 19,23 @@ Lucky::ForceSSLHandler.configure do |settings|
# To force SSL in production, uncomment the lines below.
# This will cause http requests to be redirected to https:
#
- # settings.enabled = Lucky::Env.production?
+ # settings.enabled = LuckyEnv.production?
# settings.strict_transport_security = {max_age: 1.year, include_subdomains: true}
#
# Or, leave it disabled:
settings.enabled = false
end
+# Set a uniuqe ID for each HTTP request.
+Lucky::RequestIdHandler.configure do |settings|
+ # To enable the request ID, uncomment the lines below.
+ # You can set your own custom String, or use a random UUID.
+ #
+ # settings.set_request_id = ->(context : HTTP::Server::Context) {
+ # UUID.random.to_s
+ # }
+end
+
private def secret_key_from_env
ENV["SECRET_KEY_BASE"]? || raise_missing_secret_key_in_production
end
M package.json => package.json +4 -4
@@ 5,16 5,16 @@
"@rails/ujs": "^6.0.0",
"compression-webpack-plugin": "^8.0.1",
"laravel-mix": "^6.0.28",
- "normalize-scss": "^7.0.1",
+ "modern-normalize": "^1.1.0",
"postcss": "^8.3.6",
"tufte-css": "^1.8.0",
"turbolinks": "^5.2.0"
},
"scripts": {
"heroku-postbuild": "yarn prod",
- "dev": "mix",
- "watch": "mix watch",
- "prod": "mix --production"
+ "dev": "yarn run mix",
+ "watch": "yarn run mix watch",
+ "prod": "yarn run mix --production"
},
"devDependencies": {
"@babel/compat-data": "^7.9.0",
M shard.lock => shard.lock +27 -19
@@ 2,15 2,19 @@ version: 2.0
shards:
authentic:
git: https://github.com/luckyframework/authentic.git
- version: 0.7.3
+ version: 0.8.1
avram:
git: https://github.com/luckyframework/avram.git
- version: 0.20.0
+ version: 0.22.0
+
+ backtracer:
+ git: https://github.com/sija/backtracer.cr.git
+ version: 1.2.1
carbon:
git: https://github.com/luckyframework/carbon.git
- version: 0.1.4
+ version: 0.2.0
cry:
git: https://github.com/luckyframework/cry.git
@@ 28,17 32,9 @@ shards:
git: https://github.com/luckyframework/dexter.git
version: 0.3.3
- dotenv:
- git: https://github.com/gdotdesign/cr-dotenv.git
- version: 1.0.0
-
exception_page:
git: https://github.com/crystal-loot/exception_page.git
- version: 0.1.5
-
- future:
- git: https://github.com/crystal-community/future.cr.git
- version: 1.0.0+git.commit.9fe168418c6884cb3552c13b004763eb4815ceb9
+ version: 0.2.1
habitat:
git: https://github.com/luckyframework/habitat.git
@@ 46,7 42,15 @@ shards:
lucky:
git: https://github.com/luckyframework/lucky.git
- version: 0.27.2
+ version: 0.29.0
+
+ lucky_cache:
+ git: https://github.com/luckyframework/lucky_cache.git
+ version: 0.1.0
+
+ lucky_env:
+ git: https://github.com/luckyframework/lucky_env.git
+ version: 0.1.4
lucky_flow:
git: https://github.com/luckyframework/lucky_flow.git
@@ 54,11 58,11 @@ shards:
lucky_router:
git: https://github.com/luckyframework/lucky_router.git
- version: 0.4.2
+ version: 0.5.1
lucky_task:
git: https://github.com/luckyframework/lucky_task.git
- version: 0.1.0
+ version: 0.1.1
monads:
git: https://github.com/alex-lairan/monads.git
@@ 66,7 70,7 @@ shards:
pg:
git: https://github.com/will/crystal-pg.git
- version: 0.23.2
+ version: 0.24.0
pulsar:
git: https://github.com/luckyframework/pulsar.git
@@ 78,11 82,15 @@ shards:
shell-table:
git: https://github.com/luckyframework/shell-table.cr.git
- version: 0.9.2+git.commit.ad72379f241ba28698ca2873d9b43785324a7932
+ version: 0.9.3
+
+ splay_tree_map:
+ git: https://github.com/wyhaines/splay_tree_map.cr.git
+ version: 0.2.2
teeplate:
git: https://github.com/luckyframework/teeplate.git
- version: 0.8.3
+ version: 0.8.5
webdrivers:
git: https://github.com/matthewmcgarvey/webdrivers.cr.git
@@ 90,5 98,5 @@ shards:
wordsmith:
git: https://github.com/luckyframework/wordsmith.git
- version: 0.2.2
+ version: 0.3.0
M shard.yml => shard.yml +8 -8
@@ 1,5 1,5 @@
name: scribe
-version: 0.1.0
+version: 1.0.0
authors:
- Edward Loveall <edward@edwardloveall.com>
@@ 8,24 8,24 @@ targets:
scribe:
main: src/scribe.cr
-crystal: 1.0.0
+crystal: 1.2.1
dependencies:
lucky:
github: luckyframework/lucky
- version: ~> 0.27.0
+ version: ~> 0.29.0
authentic:
github: luckyframework/authentic
- version: ~> 0.7.3
+ version: ~> 0.8.1
carbon:
github: luckyframework/carbon
+ version: ~> 0.2.0
+ lucky_env:
+ github: luckyframework/lucky_env
version: ~> 0.1.4
- dotenv:
- github: gdotdesign/cr-dotenv
- version: ~> 1.0.0
lucky_task:
github: luckyframework/lucky_task
- version: ~> 0.1.0
+ version: ~> 0.1.1
monads:
github: alex-lairan/monads
development_dependencies:
M spec/setup/configure_lucky_flow.cr => spec/setup/configure_lucky_flow.cr +8 -0
@@ 1,5 1,13 @@
+# For more detailed documentation, visit
+# https://luckyframework.org/guides/testing/html-and-interactivity
+
LuckyFlow.configure do |settings|
settings.stop_retrying_after = 200.milliseconds
settings.base_uri = Lucky::RouteHelper.settings.base_uri
+
+ # By default, LuckyFlow is set in "headless" mode (no browser window shown).
+ # Uncomment this to enable running `LuckyFlow` in a Google Chrome window instead.
+ # Be sure to disable for CI.
+ # settings.driver = LuckyFlow::Drivers::Chrome
end
Spec.before_each { LuckyFlow::Server::INSTANCE.reset }
M src/actions/api_action.cr => src/actions/api_action.cr +4 -0
@@ 2,4 2,8 @@ abstract class ApiAction < Lucky::Action
# Remove this line if you want to send cookies in the response header.
disable_cookies
accepted_formats [:json]
+
+ # By default all actions are required to use underscores to separate words.
+ # Add 'include Lucky::SkipRouteStyleCheck' to your actions if you wish to ignore this check for specific routes.
+ include Lucky::EnforceUnderscoredRoute
end
M src/actions/articles/show.cr => src/actions/articles/show.cr +6 -2
@@ 12,7 12,7 @@ class Articles::Show < BrowserAction
html(
Errors::ShowPage,
message: "Error parsing the URL",
- status: 500,
+ status_code: 500,
)
end
end
@@ 39,10 39,14 @@ class Articles::Show < BrowserAction
end
def client_class
- if Lucky::Env.use_local?
+ if use_local?
LocalClient
else
MediumClient
end
end
+
+ def use_local?
+ ENV.fetch("USE_LOCAL", "false") == "true"
+ end
end
M src/actions/browser_action.cr => src/actions/browser_action.cr +3 -0
@@ 1,4 1,7 @@
abstract class BrowserAction < Lucky::Action
include Lucky::ProtectFromForgery
+ include Lucky::EnforceUnderscoredRoute
+ include Lucky::SecureHeaders::DisableFLoC
+
accepted_formats [:html, :json], default: :html
end
M src/actions/errors/show.cr => src/actions/errors/show.cr +1 -1
@@ 48,7 48,7 @@ class Errors::Show < Lucky::ErrorAction
private def error_html(message : String, status : Int)
context.response.status_code = status
- html Errors::ShowPage, message: message, status: status
+ html_with_status Errors::ShowPage, status, message: message, status_code: status
end
private def error_json(message : String, status : Int, details = nil, param = nil)
M src/app.cr => src/app.cr +4 -3
@@ 1,7 1,10 @@
require "./shards"
-Lucky::AssetHelpers.load_manifest
+# Load the asset manifest
+Lucky::AssetHelpers.load_manifest "public/mix-manifest.json"
+require "../config/server"
+require "../config/**"
require "./app_database"
require "./constants"
require "./models/base_model"
@@ 20,7 23,5 @@ require "./components/**"
require "./classes/**"
require "./clients/**"
require "./pages/**"
-require "../config/env"
-require "../config/**"
require "../db/migrations/**"
require "./app_server"
M src/app_server.cr => src/app_server.cr +2 -2
@@ 1,6 1,7 @@
class AppServer < Lucky::BaseAppServer
def middleware : Array(HTTP::Handler)
[
+ Lucky::RequestIdHandler.new,
Lucky::ForceSSLHandler.new,
Lucky::HttpMethodOverrideHandler.new,
Lucky::LogHandler.new,
@@ 18,7 19,6 @@ class AppServer < Lucky::BaseAppServer
end
def listen
- server.bind_tcp(host, port, reuse_port: false)
- server.listen
+ server.listen(host, port, reuse_port: false)
end
end
M src/components/shared/layout_head.cr => src/components/shared/layout_head.cr +0 -1
@@ 1,6 1,5 @@
class Shared::LayoutHead < BaseComponent
needs page_title : String
- needs context : HTTP::Server::Context
def render
head do
M src/pages/errors/show_page.cr => src/pages/errors/show_page.cr +2 -2
@@ 2,7 2,7 @@ class Errors::ShowPage
include Lucky::HTMLPage
needs message : String
- needs status : Int32
+ needs status_code : Int32
def render
html_doctype
@@ 17,7 17,7 @@ class Errors::ShowPage
body do
div class: "container" do
- h2 status, class: "status-code"
+ h2 status_code, class: "status-code"
h1 message, class: "message"
ul class: "helpful-links" do
M src/pages/home/index_page.cr => src/pages/home/index_page.cr +1 -1
@@ 1,6 1,6 @@
class Home::IndexPage < MainLayout
def page_title
- "Scribe"
+ Application.settings.name
end
def content
M src/pages/main_layout.cr => src/pages/main_layout.cr +1 -1
@@ 12,7 12,7 @@ abstract class MainLayout
html_doctype
html lang: "en" do
- mount Shared::LayoutHead, page_title: page_title, context: context
+ mount Shared::LayoutHead, page_title: page_title
body do
mount Shared::FlashMessages, context.flash
M src/shards.cr => src/shards.cr +2 -2
@@ 1,6 1,6 @@
# Load .env file before any other config or app code
-require "dotenv"
-Dotenv.load?
+require "lucky_env"
+LuckyEnv.load?(".env")
# Require your shards here
require "avram"
M src/start_server.cr => src/start_server.cr +1 -1
@@ 2,7 2,7 @@ require "./app"
Habitat.raise_if_missing_settings!
-if Lucky::Env.development?
+if LuckyEnv.development?
Avram::Migrator::Runner.new.ensure_migrated!
Avram::SchemaEnforcer.ensure_correct_column_mappings!
end
M yarn.lock => yarn.lock +5 -5
@@ 4036,6 4036,11 @@ mkdirp@^0.5.5:
dependencies:
minimist "^1.2.5"
+modern-normalize@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/modern-normalize/-/modern-normalize-1.1.0.tgz#da8e80140d9221426bd4f725c6e11283d34f90b7"
+ integrity sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA==
+
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ 4158,11 4163,6 @@ normalize-range@^0.1.2:
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=
-normalize-scss@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/normalize-scss/-/normalize-scss-7.0.1.tgz#74485e82bb5d0526371136422a09fdb868ffc1a4"
- integrity sha512-qj16bWnYs+9/ac29IgGjySg4R5qQTp1lXfm7ApFOZNVBYFY8RZ3f8+XQNDDLHeDtI3Ba7Jj4+LuPgz9v/fne2A==
-
normalize-url@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"