stipa 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 80e062eee66bb5fb015d00f45bb604c85ad905fbf35bbb32652ac48dbbc2b888
4
- data.tar.gz: c2883dd7c9e9bf9025330d43ee0053bfb602841c47c12683df67497fe41a59f7
3
+ metadata.gz: f091e5c4ee4aa36a0ebeb498b1ad781be0bb0d0f3423c5c1b242ff1dc11754f0
4
+ data.tar.gz: 2b97f2bc8eaa3a8cfe1ccacab9a030209b88ba44dbd76f84cbc99ba56530ca52
5
5
  SHA512:
6
- metadata.gz: 2c434487c1186267976b98d73e3dfa9723babd352f46eacadaf0623045668e99e02972c12799c5123f11e35cc8855253ade8de05d6e913e958fde156138b67c2
7
- data.tar.gz: feca4e22d0712c1fd927a828c49bed7e6696575fdb34cef8c2a73e013e50a2c7523c44a2a35c1a9ba12d416a1fe4cd4cf35b395b8d8ff5f77e1002ddb5c07359
6
+ metadata.gz: cac5a86b535550c92811bbff7db3715109e736e32d1eab7e809b2da14d448e768c4a9ee2a5e1b9a15f9ad07dc4949dd369314dc644ddb071aebc4e84bd7926fc
7
+ data.tar.gz: 83dc705b0d41a4616609bb2a8469511a8cb6ef46e12c8acc4372eb6875bf031fc49a9b62707ca6ce698dfc8b7f7660e37970df631df93b2131dba4ed3cace838
data/README.md CHANGED
@@ -15,6 +15,7 @@
15
15
  - **Middleware stack** compiled once at startup — zero per-request overhead
16
16
  - **ERB template engine** with layouts, partials, and Vue 3 island helpers
17
17
  - **CLI generator** — `stipa new myapp` scaffolds a full MVC app with Vue + TypeScript
18
+ - **Database layer** — optional Sequel integration with migrations, models, and connection management
18
19
 
19
20
  ---
20
21
 
@@ -73,15 +74,21 @@ Generated structure (`--vue`):
73
74
  myapp/
74
75
  ├── server.rb # entry point
75
76
  ├── Gemfile
77
+ ├── Rakefile # db:migrate, db:rollback, db:version
76
78
  ├── package.json # rollup + vue + typescript
77
79
  ├── rollup.config.js
78
80
  ├── tsconfig.json
79
- ├── src/
80
- │ ├── config/routes.rb
81
+ ├── app/
82
+ │ ├── config/
83
+ │ │ ├── database.rb # DATABASE_URL, Sequel settings
84
+ │ │ └── routes.rb
81
85
  │ ├── controllers/
82
86
  │ ├── models/
87
+ │ │ └── application_model.rb # base model with Stipa::Model
83
88
  │ ├── views/
84
89
  │ └── components/ # Vue SFC source (.vue, .ts)
90
+ ├── db/
91
+ │ └── migrate/ # Sequel migrations
85
92
  └── public/
86
93
  ├── stipa-vue.js
87
94
  ├── app.css
@@ -324,6 +331,116 @@ Handles `SIGTERM` / `SIGINT` with graceful drain.
324
331
 
325
332
  ---
326
333
 
334
+ ## Database
335
+
336
+ Optional Sequel integration. Add to your Gemfile:
337
+
338
+ ```ruby
339
+ gem 'sequel'
340
+ gem 'pg' # or mysql2, sqlite3
341
+ ```
342
+
343
+ Configure via `DATABASE_URL`:
344
+
345
+ ```bash
346
+ # .env (development / test)
347
+ DATABASE_URL=postgres://user:password@localhost:5432/myapp
348
+ ```
349
+
350
+ ```ruby
351
+ require 'stipa/database'
352
+
353
+ Stipa::Database.connect!
354
+ DB = Stipa::Database.connection
355
+
356
+ # health check
357
+ Stipa::Database.healthy? # => true
358
+
359
+ # transactions
360
+ Stipa::Database.transaction { DB[:posts].insert(title: 'Hello') }
361
+
362
+ # shutdown
363
+ Stipa::Database.disconnect!
364
+ ```
365
+
366
+ ### Migrations
367
+
368
+ ```bash
369
+ rake db:migrate # run pending migrations
370
+ rake db:rollback # rollback last migration
371
+ rake db:version # show current version
372
+ ```
373
+
374
+ Create a migration:
375
+
376
+ ```ruby
377
+ # db/migrate/002_create_comments.rb
378
+ Sequel.migration do
379
+ change do
380
+ create_table :comments do
381
+ primary_key :id
382
+ foreign_key :post_id, null: false
383
+ String :body, text: true
384
+ DateTime :created_at, null: false
385
+ DateTime :updated_at, null: false
386
+ end
387
+ end
388
+ end
389
+ ```
390
+
391
+ ---
392
+
393
+ ## Models
394
+
395
+ Models use `Stipa::Model` — a set of Sequel plugins for common patterns:
396
+
397
+ ```ruby
398
+ require 'stipa/model'
399
+
400
+ class Post < ApplicationModel
401
+ # Included by default:
402
+ # - Timestamps (created_at / updated_at)
403
+ # - UUID (auto-generate UUID primary key)
404
+ # - SoftDelete (deleted_at scoping)
405
+ # - Serialization (to_hash, to_json, from_json)
406
+
407
+ plugin :validation_helpers
408
+
409
+ def validate
410
+ super
411
+ validates_presence [:title]
412
+ validates_unique [:slug]
413
+ end
414
+ end
415
+ ```
416
+
417
+ ### Standalone modules
418
+
419
+ Use individual modules without the full `Stipa::Model` bundle:
420
+
421
+ ```ruby
422
+ class User < Sequel::Model
423
+ include Stipa::Model::UUID
424
+ include Stipa::Model::Pagination
425
+ end
426
+
427
+ # Pagination
428
+ result = User.paginate(page: 2, per_page: 10)
429
+ result[:records] # => [#<User>, ...]
430
+ result[:total] # => 150
431
+ result[:total_pages] # => 15
432
+
433
+ # Soft delete
434
+ user.soft_delete
435
+ user.deleted? # => true
436
+ User.all # => excludes soft-deleted
437
+ User.with_deleted # => includes all
438
+ User.only_deleted # => soft-deleted only
439
+ user.restore
440
+ ```
441
+
442
+ ---
443
+
327
444
  ## License
328
445
 
329
446
  MIT
data/lib/stipa/app.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  require_relative 'version'
2
2
  require_relative 'logger'
3
- require_relative 'server'
4
- require_relative 'middleware'
5
- require_relative 'request'
6
- require_relative 'response'
3
+ require_relative 'server/server'
4
+ require_relative 'middleware/stack'
5
+ require_relative 'http/request'
6
+ require_relative 'http/response'
7
7
 
8
8
  module Stipa
9
9
  # User-facing DSL for defining routes and middleware.
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel'
4
+
5
+ module Stipa
6
+ # Database connection manager.
7
+ #
8
+ # Usage:
9
+ # require 'stipa/database'
10
+ #
11
+ # Stipa::Database.connect! # reads DATABASE_URL from environment
12
+ # DB = Stipa::Database.connection
13
+ #
14
+ # Environment variables:
15
+ # DATABASE_URL — connection string (required)
16
+ # DATABASE_POOL — max connections (default: 5)
17
+ #
18
+ # Connection string examples:
19
+ # postgres://user:pass@localhost:5432/myapp
20
+ # mysql2://user:pass@localhost:3306/myapp
21
+ # sqlite://db/development.db
22
+ #
23
+ module Database
24
+ module_function
25
+
26
+ def connect!
27
+ return @connection if @connection
28
+
29
+ @connection = Sequel.connect(
30
+ ENV.fetch('DATABASE_URL'),
31
+ max_connections: Integer(ENV.fetch('DATABASE_POOL', '5')),
32
+ connect_timeout: 5,
33
+ test: true,
34
+ keep_reference: false,
35
+ after_connect: lambda do |connection|
36
+ connection.exec("SET TIME ZONE 'UTC'") if connection.respond_to?(:exec)
37
+ end
38
+ )
39
+
40
+ configure_connection!
41
+ Sequel::Model.db = @connection
42
+ @connection
43
+ rescue KeyError => e
44
+ raise "Missing database configuration: #{e.message}"
45
+ rescue ArgumentError => e
46
+ raise "Invalid database configuration: #{e.message}"
47
+ end
48
+
49
+ def connection
50
+ @connection || raise('Database.connect! must be called first')
51
+ end
52
+
53
+ def connected?
54
+ !@connection.nil?
55
+ end
56
+
57
+ def healthy?
58
+ connection.get(Sequel.lit('SELECT 1')) == 1
59
+ rescue Sequel::Error
60
+ false
61
+ end
62
+
63
+ def disconnect!
64
+ @connection&.disconnect
65
+ @connection = nil
66
+ end
67
+
68
+ def transaction(&block)
69
+ connection.transaction(&block)
70
+ end
71
+
72
+ # -------------------------------------------------------------------
73
+ # Database-specific extensions
74
+ # -------------------------------------------------------------------
75
+ #
76
+ # The defaults below are tuned for PostgreSQL. If you're using a
77
+ # different adapter, comment out or remove the lines that don't apply.
78
+ #
79
+ # ── PostgreSQL ──────────────────────────────────────────────────────
80
+ # No changes needed — the lines below work out of the box.
81
+ #
82
+ # ── MySQL / MariaDB ─────────────────────────────────────────────────
83
+ # Replace the body of this method with:
84
+ #
85
+ # def configure_connection!
86
+ # return unless @connection.adapter_scheme == :mysql
87
+ #
88
+ # @connection.extension :pg_json # not available — remove
89
+ # @connection.extension :pg_array # not available — remove
90
+ #
91
+ # Sequel.extension :pg_json_ops # not available — remove
92
+ # Sequel.extension :pg_array_ops # not available — remove
93
+ # end
94
+ #
95
+ # ── SQLite ──────────────────────────────────────────────────────────
96
+ # Replace the body of this method with:
97
+ #
98
+ # def configure_connection!
99
+ # return unless @connection.adapter_scheme == :sqlite
100
+ #
101
+ # @connection.extension :pagination # optional: simple pagination
102
+ # end
103
+ #
104
+ # ── Generic / adapter-agnostic ──────────────────────────────────────
105
+ # If you want a safe default that works with any adapter:
106
+ #
107
+ # def configure_connection!
108
+ # # No adapter-specific extensions.
109
+ # # Add extensions conditionally based on adapter_scheme:
110
+ # #
111
+ # # case @connection.adapter_scheme
112
+ # # when :postgres
113
+ # # @connection.extension :pg_json
114
+ # # @connection.extension :pg_array
115
+ # # when :sqlite
116
+ # # @connection.extension :pagination
117
+ # # end
118
+ # end
119
+ #
120
+ def configure_connection!
121
+ return unless @connection.adapter_scheme == :postgres
122
+
123
+ @connection.extension :pg_json
124
+ @connection.extension :pg_array
125
+
126
+ Sequel.extension :pg_json_ops
127
+ Sequel.extension :pg_array_ops
128
+ end
129
+
130
+ private_class_method :configure_connection!
131
+ end
132
+ end
@@ -8,7 +8,7 @@ module Stipa
8
8
  def template_name = 'api'
9
9
 
10
10
  def dirs
11
- %w[config controllers]
11
+ %w[config controllers models db/migrate]
12
12
  end
13
13
 
14
14
  def done_message
@@ -25,13 +25,17 @@ module Stipa
25
25
  {
26
26
  '.gitignore' => t_gitignore,
27
27
  'Gemfile' => t_gemfile,
28
+ 'Rakefile' => t_rakefile,
28
29
  'server.rb' => t_server,
30
+ 'config/database.rb' => t_database_config,
29
31
  'config/routes.rb' => t_routes(
30
32
  extra_requires: ['../controllers/health_controller'],
31
33
  extra_routes: ["get '/health', to: 'health#show'"],
32
34
  ),
33
35
  'controllers/application_controller.rb' => t_application_controller,
34
36
  'controllers/health_controller.rb' => t_health_controller,
37
+ 'models/application_model.rb' => t_application_model,
38
+ 'db/migrate/001_create_posts.rb' => t_migration_create_posts,
35
39
  }
36
40
  end
37
41
 
@@ -42,8 +46,16 @@ module Stipa
42
46
  def t_server
43
47
  <<~RUBY
44
48
  require 'stipa'
49
+ require 'stipa/database'
50
+
51
+ require_relative 'config/database'
45
52
  require_relative 'config/routes'
46
53
 
54
+ Stipa::Database.connect!
55
+
56
+ # Models must be loaded after the database connection is established.
57
+ require_relative 'models/application_model'
58
+
47
59
  app = Stipa::App.new
48
60
 
49
61
  app.use Stipa::Middleware::RequestId
@@ -52,6 +64,14 @@ module Stipa
52
64
 
53
65
  Routes.draw(app)
54
66
 
67
+ app.get '/api/health' do |_req, res|
68
+ res.json({ status: 'ok', framework: 'Stipa', version: Stipa::VERSION, ts: Time.now.utc.iso8601 })
69
+ end
70
+
71
+ at_exit do
72
+ Stipa::Database.disconnect!
73
+ end
74
+
55
75
  app.start(host: '127.0.0.1', port: 3710)
56
76
  RUBY
57
77
  end
@@ -87,6 +87,14 @@ module Stipa
87
87
  source 'https://rubygems.org'
88
88
 
89
89
  gem 'stipa'
90
+ gem 'rake'
91
+ gem 'sequel'
92
+ gem 'dotenv'
93
+
94
+ # Database adapter — uncomment the one you need:
95
+ # gem 'pg' # PostgreSQL
96
+ # gem 'mysql2' # MySQL / MariaDB
97
+ # gem 'sqlite3' # SQLite
90
98
  RUBY
91
99
  end
92
100
 
@@ -148,6 +156,118 @@ module Stipa
148
156
  end
149
157
  RUBY
150
158
  end
159
+
160
+ def t_database_config
161
+ <<~RUBY
162
+ # frozen_string_literal: true
163
+
164
+ environment = ENV.fetch('APP_ENV', 'development')
165
+
166
+ case environment
167
+ when 'development', 'test'
168
+ require 'dotenv/load'
169
+ end
170
+
171
+ # Set DATABASE_URL in your .env file (development/test) or environment (production).
172
+ #
173
+ # PostgreSQL:
174
+ # DATABASE_URL=postgres://user:password@localhost:5432/myapp
175
+ #
176
+ # MySQL:
177
+ # DATABASE_URL=mysql2://user:password@localhost:3306/myapp
178
+ #
179
+ # SQLite:
180
+ # DATABASE_URL=sqlite://db/development.db
181
+
182
+ Sequel.database_timezone = :utc
183
+ Sequel.application_timezone = :local
184
+ RUBY
185
+ end
186
+
187
+ def t_application_model
188
+ <<~RUBY
189
+ # frozen_string_literal: true
190
+
191
+ require 'stipa/model'
192
+
193
+ class ApplicationModel < Sequel::Model
194
+ include Stipa::Model
195
+
196
+ def self.dataset
197
+ super
198
+ rescue Sequel::Error => e
199
+ raise "Database not ready: \#{e.message}"
200
+ end
201
+ end
202
+ RUBY
203
+ end
204
+
205
+ def t_migration_create_posts
206
+ <<~RUBY
207
+ # frozen_string_literal: true
208
+
209
+ Sequel.migration do
210
+ change do
211
+ create_table :posts do
212
+ primary_key :id
213
+ String :title, null: false
214
+ String :body, text: true
215
+ String :slug, null: false
216
+ DateTime :created_at, null: false
217
+ DateTime :updated_at, null: false
218
+
219
+ index :slug, unique: true
220
+ end
221
+ end
222
+ end
223
+ RUBY
224
+ end
225
+
226
+ def t_rakefile
227
+ <<~RUBY
228
+ # frozen_string_literal: true
229
+
230
+ require 'rake'
231
+ require 'sequel'
232
+ require 'sequel/extensions/migration'
233
+ require 'stipa/database'
234
+
235
+ namespace :db do
236
+ desc 'Run pending migrations'
237
+ task :migrate do
238
+ load_config
239
+ Sequel::Migrator.run(Stipa::Database.connection, 'db/migrate')
240
+ puts "Migrated to \#{Stipa::Database.connection[:schema_info].first[:version]}"
241
+ end
242
+
243
+ desc 'Rollback the last migration'
244
+ task :rollback do
245
+ load_config
246
+ Sequel::Migrator.run(Stipa::Database.connection, 'db/migrate', target: current_version - 1)
247
+ puts "Rolled back to \#{current_version}"
248
+ end
249
+
250
+ desc 'Show current migration version'
251
+ task :version do
252
+ load_config
253
+ puts "Current version: \#{current_version}"
254
+ end
255
+ end
256
+
257
+ task default: 'db:migrate'
258
+
259
+ def load_config
260
+ require_relative 'config/database'
261
+ Stipa::Database.connect!
262
+ end
263
+
264
+ def current_version
265
+ Stipa::Database.connection[:schema_info].first[:version]
266
+ rescue
267
+ 0
268
+ end
269
+ RUBY
270
+ end
151
271
  end
152
272
  end
153
273
  end
@@ -15,6 +15,7 @@ module Stipa
15
15
  app/views/layouts
16
16
  app/views/home
17
17
  app/components
18
+ db/migrate
18
19
  public/vendor
19
20
  ]
20
21
  end
@@ -55,10 +56,12 @@ module Stipa
55
56
  {
56
57
  '.gitignore' => t_gitignore,
57
58
  'Gemfile' => t_gemfile,
59
+ 'Rakefile' => t_rakefile,
58
60
  'package.json' => t_package_json,
59
61
  'rollup.config.js' => t_rollup_config,
60
62
  'tsconfig.json' => t_tsconfig,
61
63
  'server.rb' => t_server,
64
+ 'app/config/database.rb' => t_database_config,
62
65
  'app/config/routes.rb' => t_routes(
63
66
  extra_requires: ['../controllers/home_controller', '../controllers/health_controller'],
64
67
  extra_routes: ["get '/', to: 'home#index'", "get '/api/health', to: 'health#show'"],
@@ -67,6 +70,8 @@ module Stipa
67
70
  'app/controllers/application_controller.rb' => t_application_controller,
68
71
  'app/controllers/home_controller.rb' => t_home_controller,
69
72
  'app/controllers/health_controller.rb' => t_health_controller,
73
+ 'app/models/application_model.rb' => t_application_model,
74
+ 'db/migrate/001_create_posts.rb' => t_migration_create_posts,
70
75
  'app/views/layouts/application.html.erb' => t_layout,
71
76
  'app/views/home/index.html.erb' => t_home_index,
72
77
  'public/app.css' => t_app_css,
@@ -151,8 +156,16 @@ module Stipa
151
156
  def t_server
152
157
  <<~RUBY
153
158
  require 'stipa'
159
+ require 'stipa/database'
160
+
161
+ require_relative 'app/config/database'
154
162
  require_relative 'app/config/routes'
155
163
 
164
+ Stipa::Database.connect!
165
+
166
+ # Models must be loaded after the database connection is established.
167
+ require_relative 'app/models/application_model'
168
+
156
169
  APP_DIR = __dir__
157
170
 
158
171
  app = Stipa::App.new(
@@ -169,6 +182,10 @@ module Stipa
169
182
  res.json({ status: 'ok', framework: 'Stipa', version: Stipa::VERSION, ts: Time.now.utc.iso8601 })
170
183
  end
171
184
 
185
+ at_exit do
186
+ Stipa::Database.disconnect!
187
+ end
188
+
172
189
  app.start(host: '127.0.0.1', port: 3710)
173
190
  RUBY
174
191
  end
@@ -1,4 +1,6 @@
1
1
  require 'socket'
2
+ require_relative 'request'
3
+ require_relative 'response'
2
4
 
3
5
  module Stipa
4
6
  # Manages the HTTP/1.1 keep-alive request/response loop for a single socket.
@@ -0,0 +1,28 @@
1
+ module Stipa
2
+ module Model
3
+ module Pagination
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def paginate(page: 1, per_page: 20)
10
+ page = [page.to_i, 1].max
11
+ per_page = [per_page.to_i, 1].max
12
+
13
+ total = count
14
+ records = limit(per_page).offset((page - 1) * per_page).all
15
+ total_pages = (total.to_f / per_page).ceil
16
+
17
+ {
18
+ records: records,
19
+ page: page,
20
+ per_page: per_page,
21
+ total: total,
22
+ total_pages: total_pages,
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ require 'json'
2
+
3
+ module Stipa
4
+ module Model
5
+ module Serialization
6
+ def to_hash
7
+ columns.each_with_object({}) do |col, h|
8
+ h[col] = send(col)
9
+ end
10
+ end
11
+
12
+ def to_json(*args)
13
+ to_hash.to_json(*args)
14
+ end
15
+
16
+ def self.included(base)
17
+ base.instance_eval do
18
+ def from_json(json)
19
+ new(JSON.parse(json))
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ module Stipa
2
+ module Model
3
+ module SoftDelete
4
+ def self.included(base)
5
+ base.instance_eval do
6
+ dataset_module do
7
+ def deleted
8
+ where(deleted_at: !nil)
9
+ end
10
+
11
+ def not_deleted
12
+ where(deleted_at: nil)
13
+ end
14
+ end
15
+
16
+ def self.dataset
17
+ super.not_deleted
18
+ end
19
+ end
20
+ end
21
+
22
+ def soft_delete
23
+ update(deleted_at: Time.now.utc)
24
+ end
25
+
26
+ def restore
27
+ update(deleted_at: nil)
28
+ end
29
+
30
+ def deleted?
31
+ !deleted_at.nil?
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ module Stipa
2
+ module Model
3
+ module Timestamps
4
+ def self.included(base)
5
+ base.instance_eval do
6
+ plugin :timestamps,
7
+ create: :created_at,
8
+ update: :updated_at,
9
+ update_on_create: true
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ require 'securerandom'
2
+
3
+ module Stipa
4
+ module Model
5
+ module UUID
6
+ def self.included(base)
7
+ base.instance_eval do
8
+ before_create { self.id ||= SecureRandom.uuid }
9
+ end
10
+ end
11
+
12
+ def to_param
13
+ id
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'model/uuid'
2
+ require_relative 'model/soft_delete'
3
+ require_relative 'model/serialization'
4
+ require_relative 'model/timestamps'
5
+ require_relative 'model/pagination'
6
+
7
+ module Stipa
8
+ module Model
9
+ def self.included(base)
10
+ base.plugin :validation_helpers
11
+ base.plugin :dirty
12
+
13
+ base.include Timestamps
14
+ base.include UUID
15
+ base.include SoftDelete
16
+ base.include Serialization
17
+ end
18
+ end
19
+ end
@@ -1,9 +1,9 @@
1
1
  require 'socket'
2
2
  require_relative 'thread_pool'
3
- require_relative 'connection'
4
- require_relative 'request'
5
- require_relative 'response'
6
- require_relative 'logger'
3
+ require_relative '../http/connection'
4
+ require_relative '../http/request'
5
+ require_relative '../http/response'
6
+ require_relative '../logger'
7
7
 
8
8
  module Stipa
9
9
  # TCP accept loop and connection lifecycle manager.
data/lib/stipa/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Stipa
2
- VERSION = '0.1.7'
2
+ VERSION = '0.2.1'
3
3
  end
data/lib/stipa.rb CHANGED
@@ -5,27 +5,28 @@
5
5
  # loads the entire framework.
6
6
  #
7
7
  # Dependency order:
8
- # version — no deps
9
- # logger — no deps
10
- # thread_pool — no deps
11
- # middleware — no deps
12
- # static depends on middleware
13
- # template no deps (stdlib only: erb, json)
14
- # request — no deps
15
- # response depends on template (via render helper)
16
- # connection — depends on request, response
17
- # server — depends on thread_pool, connection
18
- # app — depends on server, middleware, template, request, response
8
+ # version — no deps
9
+ # logger — no deps
10
+ # server/thread_pool — no deps
11
+ # server/reloader — no deps
12
+ # middleware/stack no deps
13
+ # middleware/static depends on middleware/stack
14
+ # template/template — no deps (stdlib only: erb, json)
15
+ # http/request no deps
16
+ # http/response — depends on template (via render helper)
17
+ # http/connection — depends on http/request, http/response
18
+ # server/server — depends on server/thread_pool, http/connection
19
+ # app — depends on server/server, middleware, template, http/request, http/response
19
20
 
20
21
  require_relative 'stipa/version'
21
22
  require_relative 'stipa/logger'
22
- require_relative 'stipa/thread_pool'
23
- require_relative 'stipa/reloader'
24
- require_relative 'stipa/middleware'
25
- require_relative 'stipa/static'
26
- require_relative 'stipa/template'
27
- require_relative 'stipa/request'
28
- require_relative 'stipa/response'
29
- require_relative 'stipa/connection'
30
- require_relative 'stipa/server'
23
+ require_relative 'stipa/server/thread_pool'
24
+ require_relative 'stipa/server/reloader'
25
+ require_relative 'stipa/middleware/stack'
26
+ require_relative 'stipa/middleware/static'
27
+ require_relative 'stipa/template/template'
28
+ require_relative 'stipa/http/request'
29
+ require_relative 'stipa/http/response'
30
+ require_relative 'stipa/http/connection'
31
+ require_relative 'stipa/server/server'
31
32
  require_relative 'stipa/app'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stipa
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
  - Jānis Harbs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-02 00:00:00.000000000 Z
11
+ date: 2026-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -93,20 +93,27 @@ files:
93
93
  - lib/stipa.rb
94
94
  - lib/stipa/app.rb
95
95
  - lib/stipa/cli.rb
96
- - lib/stipa/connection.rb
96
+ - lib/stipa/database.rb
97
97
  - lib/stipa/generator.rb
98
98
  - lib/stipa/generators/api.rb
99
99
  - lib/stipa/generators/base.rb
100
100
  - lib/stipa/generators/vue.rb
101
+ - lib/stipa/http/connection.rb
102
+ - lib/stipa/http/request.rb
103
+ - lib/stipa/http/response.rb
101
104
  - lib/stipa/logger.rb
102
- - lib/stipa/middleware.rb
103
- - lib/stipa/reloader.rb
104
- - lib/stipa/request.rb
105
- - lib/stipa/response.rb
106
- - lib/stipa/server.rb
107
- - lib/stipa/static.rb
108
- - lib/stipa/template.rb
109
- - lib/stipa/thread_pool.rb
105
+ - lib/stipa/middleware/stack.rb
106
+ - lib/stipa/middleware/static.rb
107
+ - lib/stipa/model.rb
108
+ - lib/stipa/model/pagination.rb
109
+ - lib/stipa/model/serialization.rb
110
+ - lib/stipa/model/soft_delete.rb
111
+ - lib/stipa/model/timestamps.rb
112
+ - lib/stipa/model/uuid.rb
113
+ - lib/stipa/server/reloader.rb
114
+ - lib/stipa/server/server.rb
115
+ - lib/stipa/server/thread_pool.rb
116
+ - lib/stipa/template/template.rb
110
117
  - lib/stipa/version.rb
111
118
  - media/favicon.ico
112
119
  - media/logo.png
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes