stipa 0.1.7 → 0.2.0

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: abdc053626744d0381f7335db140ba8db53b10417709d497a42576bba6b7b9cd
4
+ data.tar.gz: 7baaa2ff8bf626791f07c21984a554cfe313a25755ef4ee4ef8c18f48bef27ec
5
5
  SHA512:
6
- metadata.gz: 2c434487c1186267976b98d73e3dfa9723babd352f46eacadaf0623045668e99e02972c12799c5123f11e35cc8855253ade8de05d6e913e958fde156138b67c2
7
- data.tar.gz: feca4e22d0712c1fd927a828c49bed7e6696575fdb34cef8c2a73e013e50a2c7523c44a2a35c1a9ba12d416a1fe4cd4cf35b395b8d8ff5f77e1002ddb5c07359
6
+ metadata.gz: 8b149710bae024245ef518ce3e9c199ef3eccb3271423e6eee17b03b3e655ae017208bc5db412e31a460c08a1072ec8aac4c46cae3381952abf7929e120d9fb4
7
+ data.tar.gz: 2ec4167d53cd1ad5d099c1d4e458c439ade9c69bab612604e2002931eef7c7010872b6f37bc0e544f46247e76476f65b6c0f9cabea5beba856a6dcd36934aa87
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,131 @@
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
+ @connection
42
+ rescue KeyError => e
43
+ raise "Missing database configuration: #{e.message}"
44
+ rescue ArgumentError => e
45
+ raise "Invalid database configuration: #{e.message}"
46
+ end
47
+
48
+ def connection
49
+ @connection || raise('Database.connect! must be called first')
50
+ end
51
+
52
+ def connected?
53
+ !@connection.nil?
54
+ end
55
+
56
+ def healthy?
57
+ connection.get(Sequel.lit('SELECT 1')) == 1
58
+ rescue Sequel::Error
59
+ false
60
+ end
61
+
62
+ def disconnect!
63
+ @connection&.disconnect
64
+ @connection = nil
65
+ end
66
+
67
+ def transaction(&block)
68
+ connection.transaction(&block)
69
+ end
70
+
71
+ # -------------------------------------------------------------------
72
+ # Database-specific extensions
73
+ # -------------------------------------------------------------------
74
+ #
75
+ # The defaults below are tuned for PostgreSQL. If you're using a
76
+ # different adapter, comment out or remove the lines that don't apply.
77
+ #
78
+ # ── PostgreSQL ──────────────────────────────────────────────────────
79
+ # No changes needed — the lines below work out of the box.
80
+ #
81
+ # ── MySQL / MariaDB ─────────────────────────────────────────────────
82
+ # Replace the body of this method with:
83
+ #
84
+ # def configure_connection!
85
+ # return unless @connection.adapter_scheme == :mysql
86
+ #
87
+ # @connection.extension :pg_json # not available — remove
88
+ # @connection.extension :pg_array # not available — remove
89
+ #
90
+ # Sequel.extension :pg_json_ops # not available — remove
91
+ # Sequel.extension :pg_array_ops # not available — remove
92
+ # end
93
+ #
94
+ # ── SQLite ──────────────────────────────────────────────────────────
95
+ # Replace the body of this method with:
96
+ #
97
+ # def configure_connection!
98
+ # return unless @connection.adapter_scheme == :sqlite
99
+ #
100
+ # @connection.extension :pagination # optional: simple pagination
101
+ # end
102
+ #
103
+ # ── Generic / adapter-agnostic ──────────────────────────────────────
104
+ # If you want a safe default that works with any adapter:
105
+ #
106
+ # def configure_connection!
107
+ # # No adapter-specific extensions.
108
+ # # Add extensions conditionally based on adapter_scheme:
109
+ # #
110
+ # # case @connection.adapter_scheme
111
+ # # when :postgres
112
+ # # @connection.extension :pg_json
113
+ # # @connection.extension :pg_array
114
+ # # when :sqlite
115
+ # # @connection.extension :pagination
116
+ # # end
117
+ # end
118
+ #
119
+ def configure_connection!
120
+ return unless @connection.adapter_scheme == :postgres
121
+
122
+ @connection.extension :pg_json
123
+ @connection.extension :pg_array
124
+
125
+ Sequel.extension :pg_json_ops
126
+ Sequel.extension :pg_array_ops
127
+ end
128
+
129
+ private_class_method :configure_connection!
130
+ end
131
+ 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,13 @@ module Stipa
87
87
  source 'https://rubygems.org'
88
88
 
89
89
  gem 'stipa'
90
+ gem 'sequel'
91
+ gem 'dotenv'
92
+
93
+ # Database adapter — uncomment the one you need:
94
+ # gem 'pg' # PostgreSQL
95
+ # gem 'mysql2' # MySQL / MariaDB
96
+ # gem 'sqlite3' # SQLite
90
97
  RUBY
91
98
  end
92
99
 
@@ -148,6 +155,116 @@ module Stipa
148
155
  end
149
156
  RUBY
150
157
  end
158
+
159
+ def t_database_config
160
+ <<~RUBY
161
+ # frozen_string_literal: true
162
+
163
+ environment = ENV.fetch('APP_ENV', 'development')
164
+
165
+ case environment
166
+ when 'development', 'test'
167
+ require 'dotenv/load'
168
+ end
169
+
170
+ # Set DATABASE_URL in your .env file (development/test) or environment (production).
171
+ #
172
+ # PostgreSQL:
173
+ # DATABASE_URL=postgres://user:password@localhost:5432/myapp
174
+ #
175
+ # MySQL:
176
+ # DATABASE_URL=mysql2://user:password@localhost:3306/myapp
177
+ #
178
+ # SQLite:
179
+ # DATABASE_URL=sqlite://db/development.db
180
+
181
+ Sequel.database_timezone = :utc
182
+ Sequel.application_timezone = :local
183
+ RUBY
184
+ end
185
+
186
+ def t_application_model
187
+ <<~RUBY
188
+ # frozen_string_literal: true
189
+
190
+ require 'stipa/model'
191
+
192
+ class ApplicationModel < Sequel::Model
193
+ include Stipa::Model
194
+
195
+ def self.dataset
196
+ super
197
+ rescue Sequel::Error => e
198
+ raise "Database not ready: \#{e.message}"
199
+ end
200
+ end
201
+ RUBY
202
+ end
203
+
204
+ def t_migration_create_posts
205
+ <<~RUBY
206
+ # frozen_string_literal: true
207
+
208
+ Sequel.migration do
209
+ change do
210
+ create_table :posts do
211
+ primary_key :id
212
+ String :title, null: false
213
+ String :body, text: true
214
+ String :slug, null: false
215
+ DateTime :created_at, null: false
216
+ DateTime :updated_at, null: false
217
+
218
+ index :slug, unique: true
219
+ end
220
+ end
221
+ end
222
+ RUBY
223
+ end
224
+
225
+ def t_rakefile
226
+ <<~RUBY
227
+ # frozen_string_literal: true
228
+
229
+ require 'rake'
230
+ require 'stipa/database'
231
+
232
+ namespace :db do
233
+ desc 'Run pending migrations'
234
+ task :migrate do
235
+ load_config
236
+ Sequel::Migrator.run(Stipa::Database.connection, 'db/migrate')
237
+ puts "Migrated to \#{Stipa::Database.connection[:schema_info].first[:version]}"
238
+ end
239
+
240
+ desc 'Rollback the last migration'
241
+ task :rollback do
242
+ load_config
243
+ Sequel::Migrator.run(Stipa::Database.connection, 'db/migrate', target: current_version - 1)
244
+ puts "Rolled back to \#{current_version}"
245
+ end
246
+
247
+ desc 'Show current migration version'
248
+ task :version do
249
+ load_config
250
+ puts "Current version: \#{current_version}"
251
+ end
252
+ end
253
+
254
+ task default: 'db:migrate'
255
+
256
+ def load_config
257
+ require_relative 'config/database'
258
+ Stipa::Database.connect!
259
+ end
260
+
261
+ def current_version
262
+ Stipa::Database.connection[:schema_info].first[:version]
263
+ rescue
264
+ 0
265
+ end
266
+ RUBY
267
+ end
151
268
  end
152
269
  end
153
270
  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.0'
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.0
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