snowpack 1.0.0.alpha2

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.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +3 -0
  4. data/.tool-versions +1 -0
  5. data/.travis.yml +16 -0
  6. data/Brewfile +2 -0
  7. data/CHANGELOG.md +25 -0
  8. data/Gemfile +13 -0
  9. data/LICENSE +21 -0
  10. data/README.md +116 -0
  11. data/Rakefile +6 -0
  12. data/bin/bootstrap +25 -0
  13. data/exe/snowpack +7 -0
  14. data/lib/snowpack/application.rb +98 -0
  15. data/lib/snowpack/application_cli.rb +39 -0
  16. data/lib/snowpack/cli/application/cli.rb +32 -0
  17. data/lib/snowpack/cli/application/command.rb +53 -0
  18. data/lib/snowpack/cli/application/commands/assets/clobber.rb +31 -0
  19. data/lib/snowpack/cli/application/commands/assets/compile.rb +32 -0
  20. data/lib/snowpack/cli/application/commands/console.rb +55 -0
  21. data/lib/snowpack/cli/application/commands/db/create.rb +33 -0
  22. data/lib/snowpack/cli/application/commands/db/create_migration.rb +38 -0
  23. data/lib/snowpack/cli/application/commands/db/drop.rb +33 -0
  24. data/lib/snowpack/cli/application/commands/db/migrate.rb +47 -0
  25. data/lib/snowpack/cli/application/commands/db/reset.rb +28 -0
  26. data/lib/snowpack/cli/application/commands/db/rollback.rb +54 -0
  27. data/lib/snowpack/cli/application/commands/db/sample_data.rb +41 -0
  28. data/lib/snowpack/cli/application/commands/db/seed.rb +41 -0
  29. data/lib/snowpack/cli/application/commands/db/structure/dump.rb +38 -0
  30. data/lib/snowpack/cli/application/commands/db/utils/database.rb +76 -0
  31. data/lib/snowpack/cli/application/commands/db/utils/database_config.rb +49 -0
  32. data/lib/snowpack/cli/application/commands/db/version.rb +37 -0
  33. data/lib/snowpack/cli/application/commands/generate/slice.rb +32 -0
  34. data/lib/snowpack/cli/application/commands/routes/update.rb +35 -0
  35. data/lib/snowpack/cli/application/commands.rb +27 -0
  36. data/lib/snowpack/cli/command.rb +48 -0
  37. data/lib/snowpack/cli/standalone/cli.rb +14 -0
  38. data/lib/snowpack/cli/standalone/commands/new.rb +33 -0
  39. data/lib/snowpack/cli/standalone/commands.rb +13 -0
  40. data/lib/snowpack/components/formalist.rb +27 -0
  41. data/lib/snowpack/components/persistence.rb +56 -0
  42. data/lib/snowpack/components.rb +5 -0
  43. data/lib/snowpack/console/context.rb +32 -0
  44. data/lib/snowpack/console/plugins/relation_readers.rb +17 -0
  45. data/lib/snowpack/console/plugins/slice_readers.rb +33 -0
  46. data/lib/snowpack/generator.rb +57 -0
  47. data/lib/snowpack/generators/application/generator.rb +67 -0
  48. data/lib/snowpack/generators/application/templates/.env-example.tt +10 -0
  49. data/lib/snowpack/generators/application/templates/.env.test-example.tt +1 -0
  50. data/lib/snowpack/generators/application/templates/.gitignore +20 -0
  51. data/lib/snowpack/generators/application/templates/.rspec +2 -0
  52. data/lib/snowpack/generators/application/templates/Brewfile +4 -0
  53. data/lib/snowpack/generators/application/templates/Gemfile.tt +46 -0
  54. data/lib/snowpack/generators/application/templates/Guardfile +7 -0
  55. data/lib/snowpack/generators/application/templates/Procfile.dev +3 -0
  56. data/lib/snowpack/generators/application/templates/Procfile.support +1 -0
  57. data/lib/snowpack/generators/application/templates/README.md.tt +45 -0
  58. data/lib/snowpack/generators/application/templates/Rakefile +5 -0
  59. data/lib/snowpack/generators/application/templates/bin/run +7 -0
  60. data/lib/snowpack/generators/application/templates/config/application.rb.tt +19 -0
  61. data/lib/snowpack/generators/application/templates/config/puma.rb.tt +14 -0
  62. data/lib/snowpack/generators/application/templates/config/routes.rb.tt +15 -0
  63. data/lib/snowpack/generators/application/templates/config.ru +5 -0
  64. data/lib/snowpack/generators/application/templates/db/migrate/.keep +0 -0
  65. data/lib/snowpack/generators/application/templates/db/sample_data.rb +1 -0
  66. data/lib/snowpack/generators/application/templates/db/seed.rb +1 -0
  67. data/lib/snowpack/generators/application/templates/lib/__application_path__/operation.rb.tt +12 -0
  68. data/lib/snowpack/generators/application/templates/lib/__application_path__/persistence/relations/.keep +0 -0
  69. data/lib/snowpack/generators/application/templates/lib/__application_path__/types.rb.tt +11 -0
  70. data/lib/snowpack/generators/application/templates/lib/__application_path__/web/action.rb.tt +56 -0
  71. data/lib/snowpack/generators/application/templates/lib/__application_path__/web/view/context.rb.tt +31 -0
  72. data/lib/snowpack/generators/application/templates/lib/hanami/action/csrf_protection.rb +225 -0
  73. data/lib/snowpack/generators/application/templates/log/.keep +0 -0
  74. data/lib/snowpack/generators/application/templates/package.json.tt +25 -0
  75. data/lib/snowpack/generators/application/templates/public/.keep +0 -0
  76. data/lib/snowpack/generators/application/templates/script/bootstrap +32 -0
  77. data/lib/snowpack/generators/application/templates/script/console +26 -0
  78. data/lib/snowpack/generators/application/templates/script/server +13 -0
  79. data/lib/snowpack/generators/application/templates/script/setup +27 -0
  80. data/lib/snowpack/generators/application/templates/script/support +9 -0
  81. data/lib/snowpack/generators/application/templates/script/test +19 -0
  82. data/lib/snowpack/generators/application/templates/script/update +13 -0
  83. data/lib/snowpack/generators/application/templates/spec/spec_helper.rb +13 -0
  84. data/lib/snowpack/generators/application/templates/spec/suite/.keep +0 -0
  85. data/lib/snowpack/generators/application/templates/spec/support/suite.rb +9 -0
  86. data/lib/snowpack/generators/application/templates/system/__application_path__/import.rb.tt +5 -0
  87. data/lib/snowpack/generators/application/templates/system/boot/assets.rb.tt +17 -0
  88. data/lib/snowpack/generators/application/templates/system/boot/logger.rb.tt +10 -0
  89. data/lib/snowpack/generators/application/templates/system/boot/monitor.rb.tt +9 -0
  90. data/lib/snowpack/generators/application/templates/system/boot/persistence.rb.tt +9 -0
  91. data/lib/snowpack/generators/application/templates/system/boot/settings.rb.tt +18 -0
  92. data/lib/snowpack/generators/application/templates/system/boot/web.rb.tt +9 -0
  93. data/lib/snowpack/generators/slice/generator.rb +62 -0
  94. data/lib/snowpack/generators/slice/templates/lib/__slice_path__/.keep +0 -0
  95. data/lib/snowpack/generators/slice/templates/lib/__slice_path__/web/action.rb.tt +10 -0
  96. data/lib/snowpack/generators/slice/templates/lib/__slice_path__/web/actions/.keep +0 -0
  97. data/lib/snowpack/generators/slice/templates/lib/__slice_path__/web/view.rb.tt +17 -0
  98. data/lib/snowpack/generators/slice/templates/lib/__slice_path__/web/views/.keep +0 -0
  99. data/lib/snowpack/generators/slice/templates/system/__slice_path__/import.rb.tt +9 -0
  100. data/lib/snowpack/generators/slice/templates/system/__slice_path__/slice.rb.tt +10 -0
  101. data/lib/snowpack/instrumentation/appsignal/appsignal_ext.rb +13 -0
  102. data/lib/snowpack/instrumentation/appsignal/que.rb +70 -0
  103. data/lib/snowpack/instrumentation/appsignal/rack.rb +84 -0
  104. data/lib/snowpack/roda/web.rb +47 -0
  105. data/lib/snowpack/slice.rb +85 -0
  106. data/lib/snowpack/test/suite.rb +164 -0
  107. data/lib/snowpack/test/tasks.rake +40 -0
  108. data/lib/snowpack/test_tasks.rb +4 -0
  109. data/lib/snowpack/types.rb +9 -0
  110. data/lib/snowpack/version.rb +5 -0
  111. data/lib/snowpack/view/part_builder.rb +45 -0
  112. data/lib/snowpack/view/parts/pager.rb +107 -0
  113. data/lib/snowpack/view/parts/paginated.rb +22 -0
  114. data/lib/snowpack/web/application.rb +38 -0
  115. data/lib/snowpack/web/assets.rb +56 -0
  116. data/lib/snowpack/web/endpoint_resolver.rb +66 -0
  117. data/lib/snowpack/web/form.rb +38 -0
  118. data/lib/snowpack/web/plugin.rb +44 -0
  119. data/lib/snowpack/web/rack_logger.rb +73 -0
  120. data/lib/snowpack/web/router.rb +58 -0
  121. data/lib/snowpack/web.rb +20 -0
  122. data/lib/snowpack.rb +27 -0
  123. data/snowpack.gemspec +34 -0
  124. metadata +327 -0
@@ -0,0 +1,225 @@
1
+ # Standalone copy of Hanami::Action::CsrfProtection from Hanami gem, copied from
2
+ # https://raw.githubusercontent.com/hanami/hanami/unstable/lib/hanami/action/csrf_protection.rb
3
+ #
4
+ # This makes it possible for us to include CSRF protection without having to
5
+ # require the "hanami" gem, which brings in a lot of unnecessary dependencies.
6
+
7
+ require 'rack/utils'
8
+ require 'securerandom'
9
+
10
+ module Hanami
11
+ # @api private
12
+ class Action
13
+ # Invalid CSRF Token
14
+ #
15
+ # @since 0.4.0
16
+ class InvalidCSRFTokenError < ::StandardError
17
+ end
18
+
19
+ # CSRF Protection
20
+ #
21
+ # This security mechanism is enabled automatically if sessions are turned on.
22
+ #
23
+ # It stores a "challenge" token in session. For each "state changing request"
24
+ # (eg. <tt>POST</tt>, <tt>PATCH</tt> etc..), we should send a special param:
25
+ # <tt>_csrf_token</tt>.
26
+ #
27
+ # If the param matches with the challenge token, the flow can continue.
28
+ # Otherwise the application detects an attack attempt, it reset the session
29
+ # and <tt>Hanami::Action::InvalidCSRFTokenError</tt> is raised.
30
+ #
31
+ # We can specify a custom handling strategy, by overriding <tt>#handle_invalid_csrf_token</tt>.
32
+ #
33
+ # Form helper (<tt>#form_for</tt>) automatically sets a hidden field with the
34
+ # correct token. A special view method (<tt>#csrf_token</tt>) is available in
35
+ # case the form markup is manually crafted.
36
+ #
37
+ # We can disable this check on action basis, by overriding <tt>#verify_csrf_token?</tt>.
38
+ #
39
+ # @since 0.4.0
40
+ #
41
+ # @see https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29
42
+ # @see https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
43
+ #
44
+ # @example Custom Handling
45
+ # module Web::Controllers::Books
46
+ # class Create
47
+ # include Web::Action
48
+ #
49
+ # def call(params)
50
+ # # ...
51
+ # end
52
+ #
53
+ # private
54
+ #
55
+ # def handle_invalid_csrf_token
56
+ # Web::Logger.warn "CSRF attack: expected #{ session[:_csrf_token] }, was #{ params[:_csrf_token] }"
57
+ # # manual handling
58
+ # end
59
+ # end
60
+ # end
61
+ #
62
+ # @example Bypass Security Check
63
+ # module Web::Controllers::Books
64
+ # class Create
65
+ # include Web::Action
66
+ #
67
+ # def call(params)
68
+ # # ...
69
+ # end
70
+ #
71
+ # private
72
+ #
73
+ # def verify_csrf_token?
74
+ # false
75
+ # end
76
+ # end
77
+ # end
78
+ module CSRFProtection
79
+ # Session and params key for CSRF token.
80
+ #
81
+ # This key is shared with <tt>hanami-controller</tt> and <tt>hanami-helpers</tt>
82
+ #
83
+ # @since 0.4.0
84
+ # @api private
85
+ CSRF_TOKEN = :_csrf_token
86
+
87
+ # Idempotent HTTP methods
88
+ #
89
+ # By default, the check isn't performed if the request method is included
90
+ # in this list.
91
+ #
92
+ # @since 0.4.0
93
+ # @api private
94
+ IDEMPOTENT_HTTP_METHODS = Hash[
95
+ 'GET' => true,
96
+ 'HEAD' => true,
97
+ 'TRACE' => true,
98
+ 'OPTIONS' => true
99
+ ].freeze
100
+
101
+ # @since 0.4.0
102
+ # @api private
103
+ # def self.included(action)
104
+ # action.class_eval do
105
+ # before :set_csrf_token, :verify_csrf_token
106
+ # end unless Hanami.env?(:test)
107
+ # end
108
+
109
+ # NOTE: Modified to remove Hanami.env? check (we don't have a Hanami.env)
110
+ def self.included(action)
111
+ action.class_eval do
112
+ before :set_csrf_token, :verify_csrf_token
113
+ end
114
+ end
115
+
116
+ private
117
+ # Set CSRF Token in session
118
+ #
119
+ # @since 0.4.0
120
+ # @api private
121
+ def set_csrf_token(req, res)
122
+ res.session[CSRF_TOKEN] ||= generate_csrf_token
123
+ end
124
+
125
+ # Verify if CSRF token from params, matches the one stored in session.
126
+ # If not, it raises an error.
127
+ #
128
+ # Don't override this method.
129
+ #
130
+ # To bypass the security check, please override <tt>#verify_csrf_token?</tt>.
131
+ # For custom handling of an attack, please override <tt>#handle_invalid_csrf_token</tt>.
132
+ #
133
+ # @since 0.4.0
134
+ # @api private
135
+ def verify_csrf_token(req, res)
136
+ handle_invalid_csrf_token(req, res) if invalid_csrf_token?(req, res)
137
+ end
138
+
139
+ # Verify if CSRF token from params, matches the one stored in session.
140
+ #
141
+ # Don't override this method.
142
+ #
143
+ # @since 0.4.0
144
+ # @api private
145
+ def invalid_csrf_token?(req, res)
146
+ return false unless verify_csrf_token?(req, res)
147
+
148
+ missing_csrf_token?(req, res) ||
149
+ !::Rack::Utils.secure_compare(req.session[CSRF_TOKEN], req.params[CSRF_TOKEN])
150
+ end
151
+
152
+ # Verify the CSRF token was passed in params.
153
+ #
154
+ # @api private
155
+ def missing_csrf_token?(req, res)
156
+ Hanami::Utils::Blank.blank?(req.params[CSRF_TOKEN])
157
+ end
158
+
159
+ # Generates a random CSRF Token
160
+ #
161
+ # @since 0.4.0
162
+ # @api private
163
+ def generate_csrf_token
164
+ SecureRandom.hex(32)
165
+ end
166
+
167
+ # Decide if perform the check or not.
168
+ #
169
+ # Override and return <tt>false</tt> if you want to bypass security check.
170
+ #
171
+ # @since 0.4.0
172
+ #
173
+ # @example
174
+ # module Web::Controllers::Books
175
+ # class Create
176
+ # include Web::Action
177
+ #
178
+ # def call(params)
179
+ # # ...
180
+ # end
181
+ #
182
+ # private
183
+ #
184
+ # def verify_csrf_token?
185
+ # false
186
+ # end
187
+ # end
188
+ # end
189
+ def verify_csrf_token?(req, res)
190
+ !IDEMPOTENT_HTTP_METHODS[req.request_method]
191
+ end
192
+
193
+ # Handle CSRF attack.
194
+ #
195
+ # The default policy resets the session and raises an exception.
196
+ #
197
+ # Override this method, for custom handling.
198
+ #
199
+ # @raise [Hanami::Action::InvalidCSRFTokenError]
200
+ #
201
+ # @since 0.4.0
202
+ #
203
+ # @example
204
+ # module Web::Controllers::Books
205
+ # class Create
206
+ # include Web::Action
207
+ #
208
+ # def call(params)
209
+ # # ...
210
+ # end
211
+ #
212
+ # private
213
+ #
214
+ # def handle_invalid_csrf_token
215
+ # # custom invalid CSRF management goes here
216
+ # end
217
+ # end
218
+ # end
219
+ def handle_invalid_csrf_token(req, res)
220
+ res.session.clear
221
+ raise InvalidCSRFTokenError.new
222
+ end
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "<%= application_path %>",
3
+ "description": "Asset compilation with webpack",
4
+ "version": "1.0.0",
5
+ "author": "Icelab",
6
+ "repository": {},
7
+ "dependencies": {
8
+ "viewloader": "^2.0.0"
9
+ },
10
+ "devDependencies": {
11
+ "icelab-assets": "^2.0.1"
12
+ },
13
+ "engines": {
14
+ "node": ">= 6",
15
+ "npm": ">= 4"
16
+ },
17
+ "scripts": {
18
+ "start": "icelab-assets start --source-path=slices",
19
+ "build": "icelab-assets build --source-path=slices",
20
+ "build-production": "icelab-assets build --source-path=slices",
21
+ "test": "icelab-assets test --source-path=slices",
22
+ "create-entry": "icelab-assets create-entry",
23
+ "heroku-postbuild": "icelab-assets build --source-path=slices"
24
+ }
25
+ }
@@ -0,0 +1,32 @@
1
+ #!/bin/sh
2
+
3
+ # script/bootstrap: Resolve all dependencies that the application requires to
4
+ # run.
5
+
6
+ set -e
7
+
8
+ cd "$(dirname "$0")/.."
9
+
10
+ if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then
11
+ brew bundle check >/dev/null 2>&1 || {
12
+ echo "==> Installing Homebrew dependencies…"
13
+ brew bundle
14
+ }
15
+ fi
16
+
17
+ if [ -f ".tool-versions" ] && [ "$(uname -s)" = "Darwin" ]; then
18
+ echo "==> Installing package versions…"
19
+ brew bootstrap-asdf
20
+ fi
21
+
22
+ if [ -f "Gemfile" ]; then
23
+ echo "==> Installing gem dependencies…"
24
+ bundle check >/dev/null 2>&1 || {
25
+ bundle install --quiet --without production
26
+ }
27
+ fi
28
+
29
+ if [ -f "package.json" ]; then
30
+ echo "==> Installing node packages…"
31
+ yarn
32
+ fi
@@ -0,0 +1,26 @@
1
+ #!/bin/sh
2
+
3
+ # script/console: Launch a console for the application. Optionally allow an
4
+ # environment to be passed in to let the script handle the specific requirements
5
+ # for connecting to a console for that environment.
6
+
7
+ set -e
8
+
9
+ cd "$(dirname "$0")/.."
10
+
11
+ if [ -n "$1" ]; then
12
+ # Use first argument as an environment name. Use this to decide how to connect
13
+ # to the appropriate console.
14
+ if [ "$1" = "production" ]; then
15
+ heroku run ./bin/run console --app heroku-app-name
16
+ elif [ "$1" = "staging" ]; then
17
+ heroku run ./bin/run console --app heroku-app-name-staging
18
+ else
19
+ echo "Sorry, I don't know how to connect to the '$1' environment."
20
+ exit 1
21
+ fi
22
+ else
23
+ # No argument provided, so just run the local console in the development
24
+ # environment.
25
+ ./bin/run console
26
+ fi
@@ -0,0 +1,13 @@
1
+ #!/bin/sh
2
+
3
+ # script/server: Launch the application and any extra required processes
4
+ # locally.
5
+
6
+ set -e
7
+
8
+ cd "$(dirname "$0")/.."
9
+
10
+ test -z "$RACK_ENV" && RACK_ENV='development'
11
+
12
+ # Boot the app and any other necessary processes
13
+ overmind start -f Procfile.dev
@@ -0,0 +1,27 @@
1
+ #!/bin/sh
2
+
3
+ # script/setup: Set up application for the first time after cloning, or set it
4
+ # back to the initial first unused state.
5
+
6
+ set -e
7
+
8
+ cd "$(dirname "$0")/.."
9
+
10
+ script/bootstrap
11
+
12
+ echo "==> Copying config files"
13
+ if [ -f ".env-example" ] && [ ! -f ".env" ]; then
14
+ cp .env-example .env
15
+ fi
16
+ if [ -f ".env.test-example" ] && [ ! -f ".env.test" ]; then
17
+ cp .env.test-example .env.test
18
+ fi
19
+
20
+ echo "==> Setting up database…"
21
+ bin/run db create
22
+ bin/run db create -e test
23
+ bin/run db reset
24
+ bin/run db reset -e test
25
+ bin/run db seed
26
+
27
+ echo "==> App is now ready to go!"
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+
3
+ # script/support: Launch supporting services for the application.
4
+
5
+ set -e
6
+
7
+ cd "$(dirname "$0")/.."
8
+
9
+ overmind start -f Procfile.support -s .overmind.support.sock
@@ -0,0 +1,19 @@
1
+ #!/bin/sh
2
+
3
+ # script/test: Run test suite for application. Optionally pass in a path to an
4
+ # individual test file to run a single test.
5
+
6
+ set -e
7
+
8
+ cd "$(dirname "$0")/.."
9
+
10
+ [ -z "$DEBUG" ] || set -x
11
+
12
+ echo "==> Running tests…"
13
+
14
+ if [ -n "$1" ]; then
15
+ # Pass arguments to test call. This is useful for calling a single test.
16
+ bundle exec rspec "$1"
17
+ else
18
+ bundle exec rake spec
19
+ fi
@@ -0,0 +1,13 @@
1
+ #!/bin/sh
2
+
3
+ # script/update: Update application to run for its current checkout.
4
+
5
+ set -e
6
+
7
+ cd "$(dirname "$0")/.."
8
+
9
+ script/bootstrap
10
+
11
+ echo "==> Updating db…"
12
+ # run all database migrations to ensure everything is up to date.
13
+ bin/rake db:migrate
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV["RACK_ENV"] = "test"
4
+
5
+ require_relative "../config/application"
6
+ require_relative "support/suite"
7
+
8
+ SPEC_ROOT = Pathname(__dir__).freeze
9
+ FIXTURES_PATH = SPEC_ROOT.join("fixtures").freeze
10
+
11
+ suite = Test::Suite.instance
12
+
13
+ suite.start_coverage
@@ -0,0 +1,9 @@
1
+ require "snowpack/test/suite"
2
+
3
+ module Test
4
+ class Suite < Snowpack::Test::Suite
5
+ configure do |config|
6
+ # extra configuration here
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ require_relative "../../config/application"
2
+
3
+ module <%= application_module %>
4
+ Import = Application.injector
5
+ end
@@ -0,0 +1,17 @@
1
+ <%= application_module %>::Application.boot :assets do |container|
2
+ init do
3
+ require "snowpack/web/assets"
4
+ end
5
+
6
+ start do
7
+ use :settings
8
+
9
+ assets = Snowpack::Web::Assets.new(
10
+ root: container.root,
11
+ precompiled: container.config.env == :production || container[:settings].assets_precompiled,
12
+ server_url: container[:settings].assets_server_url,
13
+ )
14
+
15
+ register :assets, assets
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ <%= application_module %>::Application.boot :logger do |container|
2
+ start do
3
+ use :settings
4
+
5
+ if container[:settings].log_to_stdout
6
+ $stdout.sync = true
7
+ logger.reopen($stdout)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ <%= application_module %>::Application.boot :monitor do
2
+ init do
3
+ require "dry/monitor/sql/logger"
4
+ end
5
+
6
+ start do
7
+ Dry::Monitor::SQL::Logger.new(logger).subscribe(notifications)
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ <%= application_module %>::Application.boot :persistence, namespace: true, from: :snowpack do
2
+ configure do |config|
3
+ config.database_url = container[:settings].database_url
4
+ config.global_extensions = [:postgres]
5
+ config.connection_extensions = %i[error_sql pg_array pg_json pg_enum]
6
+ config.auto_registration_root = container.root.join("lib/<%= application_path %>/persistence").to_s
7
+ config.auto_registration_namespace = "<%= application_module %>::Persistence"
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ <%= application_module %>::Application.boot :settings, from: :system do
2
+ before :init do
3
+ require "<%= application_path %>/types"
4
+ end
5
+
6
+ settings do
7
+ # Web app
8
+ key :session_secret, <%= application_module %>::Types::Strict::String.constrained(filled: true)
9
+ key :log_to_stdout, <%= application_module %>::Types::Params::Bool
10
+
11
+ # Assets
12
+ key :assets_precompiled, <%= application_module %>::Types::Params::Bool
13
+ key :assets_server_url, <%= application_module %>::Types::Strict::String.constrained(filled: true).optional.default(nil)
14
+
15
+ # Persistence
16
+ key :database_url, <%= application_module %>::Types::Strict::String.constrained(filled: true)
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ <%= application_module %>::Application.boot :web, namespace: true do |container|
2
+ init do
3
+ require "hanami/controller"
4
+ end
5
+
6
+ start do
7
+ register "action.configuration", Hanami::Controller::Configuration.new
8
+ end
9
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/inflector"
4
+ require "securerandom"
5
+ require "shellwords"
6
+ require_relative "../../generator"
7
+
8
+ module Snowpack
9
+ module Generators
10
+ module Slice
11
+ class Generator < Snowpack::Generator
12
+ # FIXME: need to make templates_dir handling nicer, also support multiple dirs
13
+ def initialize(templates_dir: nil)
14
+ templates_dir ||= File.join(__dir__, "templates")
15
+ super(templates_dir: templates_dir)
16
+ end
17
+
18
+ def call(application:, slice_name:, web:)
19
+ slice_name = inflector.underscore(slice_name)
20
+
21
+ output_dir = application.config.root.join("slices", slice_name) # TODO: don't hardcode "slices"
22
+
23
+ super(
24
+ output_dir,
25
+ env(application: application, slice_name: slice_name, web: web),
26
+ )
27
+ end
28
+
29
+ private
30
+
31
+ def templates(web:, **)
32
+ super.then { |tpls|
33
+ if !web
34
+ tpls.reject { |tpl|
35
+ File.fnmatch?("*/web/**", tpl)
36
+ }
37
+ else
38
+ tpls
39
+ end
40
+ }
41
+ end
42
+
43
+ def env(application:, slice_name:, **others)
44
+ application_path = inflector.underscore(application.module.to_s)
45
+
46
+ {
47
+ application_path: application_path,
48
+ application_module: application.module.to_s,
49
+ slice_name: slice_name,
50
+ slice_path: "#{application_path}/#{slice_name}",
51
+ slice_module: inflector.camelize(slice_name),
52
+ }.merge(**others)
53
+ end
54
+
55
+ # TODO: use application's own inflector
56
+ def inflector
57
+ @inflector ||= Dry::Inflector.new
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,10 @@
1
+ require "<%= application_path %>/web/action"
2
+
3
+ module <%= application_module %>
4
+ module <%= slice_module %>
5
+ module Web
6
+ class Action < <%= application_module %>::Web::Action
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ # auto_register: false
3
+
4
+ require "slim"
5
+ require "dry/view"
6
+ require "<%= slice_path %>/slice"
7
+
8
+ module <%= application_module %>
9
+ module <%= slice_module %>
10
+ module Web
11
+ class View < Dry::View
12
+ config.paths = [Slice.root.join("web/templates")]
13
+ config.layout = "application"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "slice"
4
+
5
+ module <%= application_module %>
6
+ module <%= slice_module %>
7
+ Import = Slice.injector
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "snowpack/slice"
4
+
5
+ module <%= application_module %>
6
+ module <%= slice_module %>
7
+ class Slice < Snowpack::Slice
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "appsignal"
4
+
5
+ Appsignal::Transaction.class_eval do
6
+ def set_error_with_snowpack(*args)
7
+ restore!
8
+ set_error_without_snowpack(*args)
9
+ end
10
+
11
+ alias_method :set_error_without_snowpack, :set_error
12
+ alias_method :set_error, :set_error_with_snowpack
13
+ end