rivulet-rb 0.1.7 → 0.2.1

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.
@@ -6,6 +6,7 @@ module Rivulet
6
6
  class New < Dry::CLI::Command
7
7
  desc "Create a new Rivulet application"
8
8
  argument :name, required: true, desc: "Application name"
9
+ option :with_db, values: %w[postgres sqlite mysql], desc: "Database adapter (omit for no database)"
9
10
 
10
11
  DIRS = %w[
11
12
  app/handlers
@@ -21,14 +22,16 @@ module Rivulet
21
22
  db/migrations
22
23
  ].freeze
23
24
 
24
- def call(name:, **)
25
+ def call(name:, with_db: nil, **)
25
26
  DIRS.each { |d| create_dir "#{name}/#{d}" }
26
27
 
27
- write name, 'Gemfile', gemfile
28
+ write name, 'Gemfile', gemfile(with_db)
28
29
  write name, 'config.ru', config_ru
29
- write name, 'config/application.rb', application_config(name)
30
+ write name, 'config/application.rb', application_config(name, with_db)
30
31
  write name, 'config/routes.rb', routes_config
31
32
  write name, 'falcon.rb', falcon_config
33
+ write name, 'Dockerfile', dockerfile(with_db)
34
+ write name, 'docker-compose.yml', docker_compose(name, with_db)
32
35
  write name, 'app/handlers.rb', handlers_container
33
36
  write name, 'app/handlers/shared/container.rb', handlers_shared_container
34
37
  write name, 'app/handlers/shared/namespace.rb', handlers_shared_namespace
@@ -36,8 +39,9 @@ module Rivulet
36
39
  write name, 'app/services/shared/container.rb', services_shared_container
37
40
  write name, 'app/services/shared/namespace.rb', services_shared_namespace
38
41
  write name, 'app/application_contract.rb', application_contract_template
42
+ copy name, 'AGENTS.md', File.expand_path('../../../docs/AGENTS.md', __dir__)
39
43
 
40
- puts "\nDone! Next steps:\n cd #{name}\n bundle install\n bundle exec falcon host falcon.rb"
44
+ puts "\nDone! Next steps:\n cd #{name}\n docker compose up"
41
45
  end
42
46
 
43
47
  private
@@ -52,12 +56,24 @@ module Rivulet
52
56
  puts " create #{relative_path}"
53
57
  end
54
58
 
55
- def gemfile
59
+ def copy(root, relative_path, source_path)
60
+ FileUtils.copy_file(source_path, File.join(root, relative_path))
61
+ puts " create #{relative_path}"
62
+ end
63
+
64
+ def gemfile(db)
65
+ adapter = case db
66
+ when 'postgres' then "gem 'pg'"
67
+ when 'sqlite' then "gem 'sqlite3'"
68
+ when 'mysql' then "gem 'mysql2'"
69
+ end
70
+
56
71
  <<~RUBY
57
72
  source 'https://rubygems.org'
58
73
 
59
74
  gem 'rivulet-rb'
60
75
  gem 'falcon'
76
+ #{adapter}
61
77
  RUBY
62
78
  end
63
79
 
@@ -69,10 +85,22 @@ module Rivulet
69
85
  RUBY
70
86
  end
71
87
 
72
- def application_config(name)
88
+ def application_config(name, db)
89
+ dsn_default = case db
90
+ when 'postgres' then "postgres://rivulet:rivulet@db:5432/#{name}_development"
91
+ when 'sqlite' then "sqlite://db/#{name}.sqlite3"
92
+ when 'mysql' then "mysql2://rivulet:rivulet@db:3306/#{name}_development"
93
+ end
94
+
95
+ dsn_line = if dsn_default
96
+ "config.database.dsn = ENV.fetch('DATABASE_URL', '#{dsn_default}')"
97
+ else
98
+ "# config.database.dsn = ENV.fetch('DATABASE_URL', 'postgres://rivulet:rivulet@db:5432/#{name}_development')"
99
+ end
100
+
73
101
  <<~RUBY
74
102
  Rivulet.configure do |config|
75
- # config.database.dsn = ENV.fetch('DATABASE_URL', 'sqlite://db/#{name}.sqlite3')
103
+ #{dsn_line}
76
104
 
77
105
  # config.sendfile.enabled = true
78
106
  # config.sendfile.variation = 'x-accel-redirect'
@@ -96,6 +124,119 @@ module Rivulet
96
124
  RUBY
97
125
  end
98
126
 
127
+ def dockerfile(db)
128
+ apk = case db
129
+ when 'postgres' then "RUN apk add --no-cache postgresql-dev libpq\n\n"
130
+ when 'sqlite' then "RUN apk add --no-cache sqlite-dev\n\n"
131
+ when 'mysql' then "RUN apk add --no-cache mariadb-dev\n\n"
132
+ end
133
+
134
+ <<~DOCKERFILE
135
+ FROM mrvold/rivulet:latest
136
+ #{apk}WORKDIR /app
137
+ COPY Gemfile ./
138
+ RUN bundle install
139
+
140
+ EXPOSE 9292
141
+
142
+ ENTRYPOINT []
143
+ CMD ["bundle", "exec", "falcon", "serve", "-n", "1", "-b", "http://0.0.0.0:9292"]
144
+ DOCKERFILE
145
+ end
146
+
147
+ def docker_compose(name, db)
148
+ case db
149
+ when 'postgres' then docker_compose_postgres(name)
150
+ when 'mysql' then docker_compose_mysql(name)
151
+ else docker_compose_simple
152
+ end
153
+ end
154
+
155
+ def docker_compose_simple
156
+ <<~YAML
157
+ services:
158
+ app:
159
+ build: .
160
+ ports:
161
+ - "9292:9292"
162
+ volumes:
163
+ - ./:/app
164
+ YAML
165
+ end
166
+
167
+ def docker_compose_postgres(name)
168
+ <<~YAML
169
+ services:
170
+ app:
171
+ build: .
172
+ ports:
173
+ - "9292:9292"
174
+ environment:
175
+ DATABASE_URL: postgres://rivulet:rivulet@db:5432/#{name}_development
176
+ volumes:
177
+ - ./:/app
178
+ depends_on:
179
+ db:
180
+ condition: service_healthy
181
+
182
+ db:
183
+ image: postgres:17-alpine
184
+ environment:
185
+ POSTGRES_USER: rivulet
186
+ POSTGRES_PASSWORD: rivulet
187
+ POSTGRES_DB: #{name}_development
188
+ ports:
189
+ - "5432:5432"
190
+ volumes:
191
+ - db:/var/lib/postgresql/data
192
+ healthcheck:
193
+ test: ["CMD-SHELL", "pg_isready -U rivulet"]
194
+ interval: 5s
195
+ timeout: 3s
196
+ retries: 5
197
+
198
+ volumes:
199
+ db:
200
+ YAML
201
+ end
202
+
203
+ def docker_compose_mysql(name)
204
+ <<~YAML
205
+ services:
206
+ app:
207
+ build: .
208
+ ports:
209
+ - "9292:9292"
210
+ environment:
211
+ DATABASE_URL: mysql2://rivulet:rivulet@db:3306/#{name}_development
212
+ volumes:
213
+ - ./:/app
214
+ depends_on:
215
+ db:
216
+ condition: service_healthy
217
+
218
+ db:
219
+ image: mysql:8
220
+ environment:
221
+ MYSQL_ROOT_PASSWORD: root
222
+ MYSQL_USER: rivulet
223
+ MYSQL_PASSWORD: rivulet
224
+ MYSQL_DATABASE: #{name}_development
225
+ ports:
226
+ - "3306:3306"
227
+ volumes:
228
+ - db:/var/lib/mysql
229
+ healthcheck:
230
+ test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u rivulet -privulet"]
231
+ interval: 5s
232
+ timeout: 3s
233
+ retries: 5
234
+
235
+ volumes:
236
+ db:
237
+ YAML
238
+ end
239
+
99
240
  def routes_config
100
241
  <<~RUBY
101
242
  # get :posts, to: 'posts#index'
@@ -1,3 +1,3 @@
1
1
  module Rivulet
2
- VERSION = '0.1.7'
2
+ VERSION = '0.2.1'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rivulet-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dombrovskiy <vold@fastmail.com>
@@ -267,6 +267,8 @@ extensions: []
267
267
  extra_rdoc_files: []
268
268
  files:
269
269
  - bin/rivulet
270
+ - docs/AGENTS.md
271
+ - docs/architecture.md
270
272
  - lib/rivulet.rb
271
273
  - lib/rivulet/application.rb
272
274
  - lib/rivulet/cli.rb