tina4ruby 3.10.42 → 3.10.44
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 +4 -4
- data/lib/tina4/ai.rb +492 -134
- data/lib/tina4/cli.rb +784 -74
- data/lib/tina4/database.rb +12 -5
- data/lib/tina4/dev_admin.rb +266 -66
- data/lib/tina4/events.rb +19 -0
- data/lib/tina4/field_types.rb +6 -1
- data/lib/tina4/frond.rb +112 -81
- data/lib/tina4/metrics.rb +43 -2
- data/lib/tina4/orm.rb +17 -7
- data/lib/tina4/public/js/tina4-dev-admin.min.js +167 -28
- data/lib/tina4/query_builder.rb +8 -2
- data/lib/tina4/rack_app.rb +17 -1
- data/lib/tina4/template.rb +57 -15
- data/lib/tina4/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ec47f9dbe61a4b79452909076bd16a76c6b8e01dd928ca117ed69318dec9a601
|
|
4
|
+
data.tar.gz: e9d20212ae627c9a905807453a7a01cfa4e9d8c39808b6e6e31d27748d139848
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5a69a10210660179142b9fe93cd2a81eff16a40744fc94805e4c4103c5402e9a73980d4d753f5b45580cd6f34775b125dc51d0419921f06f074294047b29e2a6
|
|
7
|
+
data.tar.gz: 99e9d9ce315dfe0962600d326ca2e79d55002186e4077038bdac47368184fc8bd2965b2927727b85168869e5b0ed20e9023b86e4e390ca536967dd1a32b5e4bd
|
data/lib/tina4/ai.rb
CHANGED
|
@@ -84,10 +84,9 @@ module Tina4
|
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
-
context = generate_context
|
|
88
|
-
|
|
89
87
|
indices.each do |idx|
|
|
90
88
|
tool = AI_TOOLS[idx]
|
|
89
|
+
context = generate_context(tool[:name])
|
|
91
90
|
files = install_for_tool(root_path, tool, context)
|
|
92
91
|
created.concat(files)
|
|
93
92
|
end
|
|
@@ -105,140 +104,29 @@ module Tina4
|
|
|
105
104
|
install_selected(root, "all")
|
|
106
105
|
end
|
|
107
106
|
|
|
108
|
-
# Generate
|
|
107
|
+
# Generate per-tool Tina4 Ruby context document.
|
|
109
108
|
#
|
|
109
|
+
# @param tool_name [String] AI tool name (default: "claude-code")
|
|
110
110
|
# @return [String]
|
|
111
|
-
def generate_context
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
## Project Structure
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
lib/tina4/ -- Core framework modules
|
|
134
|
-
src/routes/ -- Route handlers (auto-discovered, one per resource)
|
|
135
|
-
src/orm/ -- ORM models (one per file, filename = class name)
|
|
136
|
-
src/templates/ -- Twig/ERB templates (extends base template)
|
|
137
|
-
src/app/ -- Shared helpers and service classes
|
|
138
|
-
src/scss/ -- SCSS files (auto-compiled to public/css/)
|
|
139
|
-
src/public/ -- Static assets served at /
|
|
140
|
-
src/locales/ -- Translation JSON files
|
|
141
|
-
src/seeds/ -- Database seeder scripts
|
|
142
|
-
migrations/ -- SQL migration files (sequential numbered)
|
|
143
|
-
spec/ -- RSpec test files
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## Built-in Features (No External Gems Needed for Core)
|
|
147
|
-
|
|
148
|
-
| Feature | Module | Require |
|
|
149
|
-
|---------|--------|---------|
|
|
150
|
-
| Routing | Tina4::Router | `require "tina4/router"` |
|
|
151
|
-
| ORM | Tina4::ORM | `require "tina4/orm"` |
|
|
152
|
-
| Database | Tina4::Database | `require "tina4/database"` |
|
|
153
|
-
| Templates | Tina4::Template | `require "tina4/template"` |
|
|
154
|
-
| JWT Auth | Tina4::Auth | `require "tina4/auth"` |
|
|
155
|
-
| REST API Client | Tina4::API | `require "tina4/api"` |
|
|
156
|
-
| GraphQL | Tina4::GraphQL | `require "tina4/graphql"` |
|
|
157
|
-
| WebSocket | Tina4::WebSocket | `require "tina4/websocket"` |
|
|
158
|
-
| SOAP/WSDL | Tina4::WSDL | `require "tina4/wsdl"` |
|
|
159
|
-
| Email (SMTP+IMAP) | Tina4::Messenger | `require "tina4/messenger"` |
|
|
160
|
-
| Background Queue | Tina4::Queue | `require "tina4/queue"` |
|
|
161
|
-
| SCSS Compilation | Tina4::ScssCompiler | `require "tina4/scss_compiler"` |
|
|
162
|
-
| Migrations | Tina4::Migration | `require "tina4/migration"` |
|
|
163
|
-
| Seeder | Tina4::FakeData | `require "tina4/seeder"` |
|
|
164
|
-
| i18n | Tina4::Localization | `require "tina4/localization"` |
|
|
165
|
-
| Swagger/OpenAPI | Tina4::Swagger | `require "tina4/swagger"` |
|
|
166
|
-
| Sessions | Tina4::Session | `require "tina4/session"` |
|
|
167
|
-
| Middleware | Tina4::Middleware | `require "tina4/middleware"` |
|
|
168
|
-
| HTML Builder | Tina4::HtmlElement | `require "tina4/html_element"` |
|
|
169
|
-
| Form Tokens | Tina4::Template | `{{ form_token() }}` in Twig |
|
|
170
|
-
|
|
171
|
-
## Key Conventions
|
|
172
|
-
|
|
173
|
-
1. **Routes use block handlers** with `|request, response|` params
|
|
174
|
-
2. **GET routes are public**, POST/PUT/PATCH/DELETE require auth by default
|
|
175
|
-
3. **Use `auth: false`** to make write routes public, `secure_get` to protect GET routes
|
|
176
|
-
4. **Every template extends a base template** -- no standalone HTML pages
|
|
177
|
-
5. **No inline styles** -- use SCSS with CSS variables
|
|
178
|
-
6. **All schema changes via migrations** -- never create tables in route code
|
|
179
|
-
7. **Service pattern** -- complex logic goes in service classes, routes stay thin
|
|
180
|
-
8. **Use built-in features** -- never install gems for things Tina4 already provides
|
|
181
|
-
|
|
182
|
-
## AI Workflow -- Available Skills
|
|
183
|
-
|
|
184
|
-
When using an AI coding assistant with Tina4, these skills are available:
|
|
185
|
-
|
|
186
|
-
| Skill | Description |
|
|
187
|
-
|-------|-------------|
|
|
188
|
-
| `/tina4-route` | Create a new route with proper decorators and auth |
|
|
189
|
-
| `/tina4-orm` | Create an ORM model with migration |
|
|
190
|
-
| `/tina4-crud` | Generate complete CRUD (migration, ORM, routes, template, tests) |
|
|
191
|
-
| `/tina4-auth` | Set up JWT authentication with login/register |
|
|
192
|
-
| `/tina4-api` | Create an external API integration |
|
|
193
|
-
| `/tina4-queue` | Set up background job processing |
|
|
194
|
-
| `/tina4-template` | Create a server-rendered template page |
|
|
195
|
-
| `/tina4-graphql` | Set up a GraphQL endpoint |
|
|
196
|
-
| `/tina4-websocket` | Set up WebSocket communication |
|
|
197
|
-
| `/tina4-wsdl` | Create a SOAP/WSDL service |
|
|
198
|
-
| `/tina4-messenger` | Set up email send/receive |
|
|
199
|
-
| `/tina4-test` | Write tests for a feature |
|
|
200
|
-
| `/tina4-migration` | Create a database migration |
|
|
201
|
-
| `/tina4-seed` | Generate fake data for development |
|
|
202
|
-
| `/tina4-i18n` | Set up internationalization |
|
|
203
|
-
| `/tina4-scss` | Set up SCSS stylesheets |
|
|
204
|
-
| `/tina4-frontend` | Set up a frontend framework |
|
|
205
|
-
|
|
206
|
-
## Common Patterns
|
|
207
|
-
|
|
208
|
-
### Route
|
|
209
|
-
```ruby
|
|
210
|
-
Tina4.get "/api/widgets" do |request, response|
|
|
211
|
-
response.json({ widgets: Widget.all })
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
Tina4.post "/api/widgets", auth: false do |request, response|
|
|
215
|
-
widget = Widget.create(request.body)
|
|
216
|
-
response.json({ created: true }, 201)
|
|
217
|
-
end
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### ORM Model
|
|
221
|
-
```ruby
|
|
222
|
-
class Widget < Tina4::ORM
|
|
223
|
-
integer_field :id, primary_key: true, auto_increment: true
|
|
224
|
-
string_field :name
|
|
225
|
-
numeric_field :price
|
|
226
|
-
end
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### Template
|
|
230
|
-
```twig
|
|
231
|
-
{% extends "base.twig" %}
|
|
232
|
-
{% block content %}
|
|
233
|
-
<div class="container">
|
|
234
|
-
<h1>{{ title }}</h1>
|
|
235
|
-
{% for item in items %}
|
|
236
|
-
<p>{{ item.name }}</p>
|
|
237
|
-
{% endfor %}
|
|
238
|
-
</div>
|
|
239
|
-
{% endblock %}
|
|
240
|
-
```
|
|
241
|
-
CONTEXT
|
|
111
|
+
def generate_context(tool_name = "claude-code")
|
|
112
|
+
case tool_name
|
|
113
|
+
when "claude-code"
|
|
114
|
+
generate_claude_code_context
|
|
115
|
+
when "cursor"
|
|
116
|
+
generate_cursor_context
|
|
117
|
+
when "copilot"
|
|
118
|
+
generate_copilot_context
|
|
119
|
+
when "windsurf"
|
|
120
|
+
generate_windsurf_context
|
|
121
|
+
when "aider"
|
|
122
|
+
generate_aider_context
|
|
123
|
+
when "cline"
|
|
124
|
+
generate_cline_context
|
|
125
|
+
when "codex"
|
|
126
|
+
generate_codex_context
|
|
127
|
+
else
|
|
128
|
+
generate_claude_code_context
|
|
129
|
+
end
|
|
242
130
|
end
|
|
243
131
|
|
|
244
132
|
# Install context file for a single tool.
|
|
@@ -333,6 +221,476 @@ module Tina4
|
|
|
333
221
|
end
|
|
334
222
|
puts " \e[33m!\e[0m Python/pip not available -- skip tina4-ai"
|
|
335
223
|
end
|
|
224
|
+
|
|
225
|
+
private
|
|
226
|
+
|
|
227
|
+
# Read existing CLAUDE.md from the framework root.
|
|
228
|
+
#
|
|
229
|
+
# @return [String]
|
|
230
|
+
def generate_claude_code_context
|
|
231
|
+
framework_root = File.expand_path("../../..", __FILE__)
|
|
232
|
+
claude_md = File.join(framework_root, "CLAUDE.md")
|
|
233
|
+
if File.exist?(claude_md)
|
|
234
|
+
File.read(claude_md)
|
|
235
|
+
else
|
|
236
|
+
"# Tina4 Ruby #{Tina4::VERSION}\n\nSee https://tina4.com for documentation.\n"
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Cursor context (~45 lines).
|
|
241
|
+
#
|
|
242
|
+
# @return [String]
|
|
243
|
+
def generate_cursor_context
|
|
244
|
+
<<~CONTEXT
|
|
245
|
+
# Tina4 Ruby #{Tina4::VERSION} — Cursor Rules
|
|
246
|
+
|
|
247
|
+
You are working in a **Tina4 Ruby** project — a zero-dependency, batteries-included web framework.
|
|
248
|
+
Documentation: https://tina4.com
|
|
249
|
+
|
|
250
|
+
## Project Structure
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
src/routes/ — Route handlers (auto-discovered)
|
|
254
|
+
src/orm/ — ORM models
|
|
255
|
+
src/templates/ — Twig templates
|
|
256
|
+
src/app/ — Service classes
|
|
257
|
+
src/scss/ — SCSS (auto-compiled)
|
|
258
|
+
src/public/ — Static assets
|
|
259
|
+
src/seeds/ — Database seeders
|
|
260
|
+
migrations/ — SQL migration files
|
|
261
|
+
spec/ — RSpec tests
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Route Pattern
|
|
265
|
+
|
|
266
|
+
```ruby
|
|
267
|
+
Tina4.get "/api/users" do |request, response|
|
|
268
|
+
response.call({ users: [] }, Tina4::HTTP_OK)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
Tina4.post "/api/users" do |request, response|
|
|
272
|
+
response.call({ created: request.body["name"] }, 201)
|
|
273
|
+
end
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## ORM Pattern
|
|
277
|
+
|
|
278
|
+
```ruby
|
|
279
|
+
class User < Tina4::ORM
|
|
280
|
+
table_name "users"
|
|
281
|
+
integer_field :id, primary_key: true, auto_increment: true
|
|
282
|
+
string_field :name, required: true
|
|
283
|
+
string_field :email
|
|
284
|
+
end
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Conventions
|
|
288
|
+
|
|
289
|
+
1. Routes return `response.call(data, status)` — never `puts` or `render`
|
|
290
|
+
2. GET routes are public; POST/PUT/PATCH/DELETE require auth by default
|
|
291
|
+
3. Every template extends `base.twig`
|
|
292
|
+
4. All schema changes via migrations — never create tables in route code
|
|
293
|
+
5. Use built-in features — never install gems for things Tina4 already provides
|
|
294
|
+
6. Service pattern — complex logic in `src/app/`, routes stay thin
|
|
295
|
+
7. Use `snake_case` for methods and variables
|
|
296
|
+
|
|
297
|
+
## Built-in Features (No Gems Needed)
|
|
298
|
+
|
|
299
|
+
Router, ORM, Database (SQLite/PostgreSQL/MySQL/MSSQL/Firebird), Frond templates (Twig-compatible), JWT auth, Sessions (File/Redis/Valkey/MongoDB/DB), GraphQL + GraphiQL, WebSocket + Redis backplane, WSDL/SOAP, Queue (File/RabbitMQ/Kafka/MongoDB), HTTP client, Messenger (SMTP/IMAP), FakeData/Seeder, Migrations, SCSS compiler, Swagger/OpenAPI, i18n, Events, Container/DI, HtmlElement, Inline testing, Error overlay, Dev dashboard, Rate limiter, Response cache, Logging, MCP server
|
|
300
|
+
CONTEXT
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# GitHub Copilot context (~30 lines).
|
|
304
|
+
#
|
|
305
|
+
# @return [String]
|
|
306
|
+
def generate_copilot_context
|
|
307
|
+
<<~CONTEXT
|
|
308
|
+
# Tina4 Ruby #{Tina4::VERSION} — Copilot Instructions
|
|
309
|
+
|
|
310
|
+
This is a **Tina4 Ruby** project. Tina4 is a zero-dependency web framework. Docs: https://tina4.com
|
|
311
|
+
|
|
312
|
+
## Structure
|
|
313
|
+
|
|
314
|
+
Routes in `src/routes/`, ORM models in `src/orm/`, templates in `src/templates/`, services in `src/app/`, tests in `spec/`.
|
|
315
|
+
|
|
316
|
+
## Route Example
|
|
317
|
+
|
|
318
|
+
```ruby
|
|
319
|
+
Tina4.get "/api/users" do |request, response|
|
|
320
|
+
response.call({ users: [] }, Tina4::HTTP_OK)
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
Tina4.post "/api/users" do |request, response|
|
|
324
|
+
response.call({ created: request.body["name"] }, 201)
|
|
325
|
+
end
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## ORM Example
|
|
329
|
+
|
|
330
|
+
```ruby
|
|
331
|
+
class User < Tina4::ORM
|
|
332
|
+
table_name "users"
|
|
333
|
+
integer_field :id, primary_key: true, auto_increment: true
|
|
334
|
+
string_field :name, required: true
|
|
335
|
+
string_field :email
|
|
336
|
+
end
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Rules
|
|
340
|
+
|
|
341
|
+
- Always return `response.call(data, status)` from routes
|
|
342
|
+
- GET is public; POST/PUT/PATCH/DELETE require auth by default
|
|
343
|
+
- Templates extend `base.twig`; schema changes via migrations only
|
|
344
|
+
- Use `snake_case`; never install gems for built-in features
|
|
345
|
+
- Built-in: Router, ORM, Database, JWT auth, Sessions, GraphQL, WebSocket, Queue, Messenger, Migrations, SCSS, Swagger, i18n, Events, DI, Testing
|
|
346
|
+
CONTEXT
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
# Windsurf context (~60 lines).
|
|
350
|
+
#
|
|
351
|
+
# @return [String]
|
|
352
|
+
def generate_windsurf_context
|
|
353
|
+
<<~CONTEXT
|
|
354
|
+
# Tina4 Ruby #{Tina4::VERSION} — Windsurf Rules
|
|
355
|
+
|
|
356
|
+
You are working in a **Tina4 Ruby** project — a zero-dependency, batteries-included web framework.
|
|
357
|
+
Documentation: https://tina4.com
|
|
358
|
+
|
|
359
|
+
## Project Structure
|
|
360
|
+
|
|
361
|
+
```
|
|
362
|
+
src/routes/ — Route handlers (auto-discovered)
|
|
363
|
+
src/orm/ — ORM models
|
|
364
|
+
src/templates/ — Twig templates
|
|
365
|
+
src/app/ — Service classes
|
|
366
|
+
src/scss/ — SCSS (auto-compiled)
|
|
367
|
+
src/public/ — Static assets
|
|
368
|
+
src/seeds/ — Database seeders
|
|
369
|
+
migrations/ — SQL migration files
|
|
370
|
+
spec/ — RSpec tests
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## CLI Commands
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
tina4ruby init . # Scaffold project
|
|
377
|
+
tina4ruby serve # Start dev server on port 7147
|
|
378
|
+
tina4ruby migrate # Run database migrations
|
|
379
|
+
tina4ruby test # Run test suite
|
|
380
|
+
tina4ruby routes # List all registered routes
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Route Pattern
|
|
384
|
+
|
|
385
|
+
```ruby
|
|
386
|
+
Tina4.get "/api/users" do |request, response|
|
|
387
|
+
response.call({ users: [] }, Tina4::HTTP_OK)
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
Tina4.post "/api/users" do |request, response|
|
|
391
|
+
response.call({ created: request.body["name"] }, 201)
|
|
392
|
+
end
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## ORM Pattern
|
|
396
|
+
|
|
397
|
+
```ruby
|
|
398
|
+
class User < Tina4::ORM
|
|
399
|
+
table_name "users"
|
|
400
|
+
integer_field :id, primary_key: true, auto_increment: true
|
|
401
|
+
string_field :name, required: true
|
|
402
|
+
string_field :email
|
|
403
|
+
end
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
## Template Pattern
|
|
407
|
+
|
|
408
|
+
```twig
|
|
409
|
+
{% extends "base.twig" %}
|
|
410
|
+
{% block content %}
|
|
411
|
+
<div class="container">
|
|
412
|
+
<h1>{{ title }}</h1>
|
|
413
|
+
{% for item in items %}
|
|
414
|
+
<p>{{ item.name }}</p>
|
|
415
|
+
{% endfor %}
|
|
416
|
+
</div>
|
|
417
|
+
{% endblock %}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
## Conventions
|
|
421
|
+
|
|
422
|
+
1. Routes return `response.call(data, status)` — never `puts` or `render`
|
|
423
|
+
2. GET routes are public; POST/PUT/PATCH/DELETE require auth by default
|
|
424
|
+
3. Every template extends `base.twig`
|
|
425
|
+
4. All schema changes via migrations — never create tables in route code
|
|
426
|
+
5. Use built-in features — never install gems for things Tina4 already provides
|
|
427
|
+
6. Service pattern — complex logic in `src/app/`, routes stay thin
|
|
428
|
+
7. Use `snake_case` for methods and variables
|
|
429
|
+
|
|
430
|
+
## Built-in Features (No Gems Needed)
|
|
431
|
+
|
|
432
|
+
Router, ORM, Database (SQLite/PostgreSQL/MySQL/MSSQL/Firebird), Frond templates (Twig-compatible), JWT auth, Sessions (File/Redis/Valkey/MongoDB/DB), GraphQL + GraphiQL, WebSocket + Redis backplane, WSDL/SOAP, Queue (File/RabbitMQ/Kafka/MongoDB), HTTP client, Messenger (SMTP/IMAP), FakeData/Seeder, Migrations, SCSS compiler, Swagger/OpenAPI, i18n, Events, Container/DI, HtmlElement, Inline testing, Error overlay, Dev dashboard, Rate limiter, Response cache, Logging, MCP server
|
|
433
|
+
|
|
434
|
+
## Database Drivers
|
|
435
|
+
|
|
436
|
+
SQLite, PostgreSQL, MySQL, MSSQL, Firebird. Connection string format: `driver://host:port/database`.
|
|
437
|
+
|
|
438
|
+
## Auth
|
|
439
|
+
|
|
440
|
+
JWT auth built-in via `Tina4::Auth`. `secure_get` / `secure_post` for protected routes. Password hashing via `Tina4::Auth.hash_password` / `check_password`.
|
|
441
|
+
CONTEXT
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
# Aider context (~58 lines).
|
|
445
|
+
#
|
|
446
|
+
# @return [String]
|
|
447
|
+
def generate_aider_context
|
|
448
|
+
<<~CONTEXT
|
|
449
|
+
# Tina4 Ruby #{Tina4::VERSION} — Conventions
|
|
450
|
+
|
|
451
|
+
## Framework
|
|
452
|
+
|
|
453
|
+
Tina4 Ruby is a zero-dependency, batteries-included web framework. Docs: https://tina4.com
|
|
454
|
+
|
|
455
|
+
## Project Structure
|
|
456
|
+
|
|
457
|
+
```
|
|
458
|
+
src/routes/ — Route handlers (auto-discovered)
|
|
459
|
+
src/orm/ — ORM models
|
|
460
|
+
src/templates/ — Twig templates
|
|
461
|
+
src/app/ — Service classes
|
|
462
|
+
src/scss/ — SCSS (auto-compiled)
|
|
463
|
+
src/public/ — Static assets
|
|
464
|
+
src/seeds/ — Database seeders
|
|
465
|
+
migrations/ — SQL migration files
|
|
466
|
+
spec/ — RSpec tests
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## CLI
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
tina4ruby init . # Scaffold project
|
|
473
|
+
tina4ruby serve # Start dev server on port 7147
|
|
474
|
+
tina4ruby migrate # Run database migrations
|
|
475
|
+
tina4ruby test # Run test suite
|
|
476
|
+
tina4ruby routes # List all registered routes
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## Route Pattern
|
|
480
|
+
|
|
481
|
+
```ruby
|
|
482
|
+
Tina4.get "/api/users" do |request, response|
|
|
483
|
+
response.call({ users: [] }, Tina4::HTTP_OK)
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
Tina4.post "/api/users" do |request, response|
|
|
487
|
+
response.call({ created: request.body["name"] }, 201)
|
|
488
|
+
end
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
## ORM Pattern
|
|
492
|
+
|
|
493
|
+
```ruby
|
|
494
|
+
class User < Tina4::ORM
|
|
495
|
+
table_name "users"
|
|
496
|
+
integer_field :id, primary_key: true, auto_increment: true
|
|
497
|
+
string_field :name, required: true
|
|
498
|
+
string_field :email
|
|
499
|
+
end
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## Conventions
|
|
503
|
+
|
|
504
|
+
1. Routes return `response.call(data, status)` — never `puts` or `render`
|
|
505
|
+
2. GET routes are public; POST/PUT/PATCH/DELETE require auth by default
|
|
506
|
+
3. Every template extends `base.twig`
|
|
507
|
+
4. All schema changes via migrations — never create tables in route code
|
|
508
|
+
5. Use built-in features — never install gems for things Tina4 already provides
|
|
509
|
+
6. Service pattern — complex logic in `src/app/`, routes stay thin
|
|
510
|
+
7. Use `snake_case` for methods and variables
|
|
511
|
+
8. Wrap route logic in `begin/rescue`, log with `Tina4::Log.error()`
|
|
512
|
+
|
|
513
|
+
## Built-in Features
|
|
514
|
+
|
|
515
|
+
Router, ORM, Database (SQLite/PostgreSQL/MySQL/MSSQL/Firebird), Frond templates (Twig-compatible), JWT auth, Sessions (File/Redis/Valkey/MongoDB/DB), GraphQL + GraphiQL, WebSocket + Redis backplane, WSDL/SOAP, Queue (File/RabbitMQ/Kafka/MongoDB), HTTP client, Messenger (SMTP/IMAP), FakeData/Seeder, Migrations, SCSS compiler, Swagger/OpenAPI, i18n, Events, Container/DI, HtmlElement, Inline testing, Error overlay, Dev dashboard, Rate limiter, Response cache, Logging, MCP server
|
|
516
|
+
|
|
517
|
+
## Testing
|
|
518
|
+
|
|
519
|
+
Run: `bundle exec rspec` or `tina4ruby test`. Tests in `spec/`.
|
|
520
|
+
CONTEXT
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
# Cline context (~42 lines).
|
|
524
|
+
#
|
|
525
|
+
# @return [String]
|
|
526
|
+
def generate_cline_context
|
|
527
|
+
<<~CONTEXT
|
|
528
|
+
# Tina4 Ruby #{Tina4::VERSION} — Cline Rules
|
|
529
|
+
|
|
530
|
+
Tina4 Ruby is a zero-dependency web framework. Docs: https://tina4.com
|
|
531
|
+
|
|
532
|
+
## Structure
|
|
533
|
+
|
|
534
|
+
```
|
|
535
|
+
src/routes/ — Route handlers (auto-discovered)
|
|
536
|
+
src/orm/ — ORM models
|
|
537
|
+
src/templates/ — Twig templates
|
|
538
|
+
src/app/ — Service classes
|
|
539
|
+
src/scss/ — SCSS (auto-compiled)
|
|
540
|
+
src/public/ — Static assets
|
|
541
|
+
src/seeds/ — Database seeders
|
|
542
|
+
migrations/ — SQL migration files
|
|
543
|
+
spec/ — RSpec tests
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
## Route Pattern
|
|
547
|
+
|
|
548
|
+
```ruby
|
|
549
|
+
Tina4.get "/api/users" do |request, response|
|
|
550
|
+
response.call({ users: [] }, Tina4::HTTP_OK)
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
Tina4.post "/api/users" do |request, response|
|
|
554
|
+
response.call({ created: request.body["name"] }, 201)
|
|
555
|
+
end
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
## ORM Pattern
|
|
559
|
+
|
|
560
|
+
```ruby
|
|
561
|
+
class User < Tina4::ORM
|
|
562
|
+
table_name "users"
|
|
563
|
+
integer_field :id, primary_key: true, auto_increment: true
|
|
564
|
+
string_field :name, required: true
|
|
565
|
+
string_field :email
|
|
566
|
+
end
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
## Conventions
|
|
570
|
+
|
|
571
|
+
1. Routes return `response.call(data, status)` — never `puts` or `render`
|
|
572
|
+
2. GET routes are public; POST/PUT/PATCH/DELETE require auth by default
|
|
573
|
+
3. Every template extends `base.twig`
|
|
574
|
+
4. All schema changes via migrations — never create tables in route code
|
|
575
|
+
5. Use built-in features — never install gems for things Tina4 already provides
|
|
576
|
+
6. Service pattern — complex logic in `src/app/`, routes stay thin
|
|
577
|
+
7. Use `snake_case` for methods and variables
|
|
578
|
+
|
|
579
|
+
## Built-in Features
|
|
580
|
+
|
|
581
|
+
Router, ORM, Database (SQLite/PostgreSQL/MySQL/MSSQL/Firebird), Frond templates (Twig-compatible), JWT auth, Sessions, GraphQL, WebSocket, Queue, Messenger, Migrations, SCSS, Swagger, i18n, Events, Container/DI, Testing, Error overlay, Dev dashboard, Rate limiter, Response cache, Logging, MCP server
|
|
582
|
+
CONTEXT
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
# OpenAI Codex context (~70 lines).
|
|
586
|
+
#
|
|
587
|
+
# @return [String]
|
|
588
|
+
def generate_codex_context
|
|
589
|
+
<<~CONTEXT
|
|
590
|
+
# Tina4 Ruby #{Tina4::VERSION} — Codex Agent Instructions
|
|
591
|
+
|
|
592
|
+
You are working in a **Tina4 Ruby** project — a zero-dependency, batteries-included web framework.
|
|
593
|
+
Documentation: https://tina4.com
|
|
594
|
+
|
|
595
|
+
## Project Structure
|
|
596
|
+
|
|
597
|
+
```
|
|
598
|
+
src/routes/ — Route handlers (auto-discovered)
|
|
599
|
+
src/orm/ — ORM models
|
|
600
|
+
src/templates/ — Twig templates
|
|
601
|
+
src/app/ — Service classes
|
|
602
|
+
src/scss/ — SCSS (auto-compiled)
|
|
603
|
+
src/public/ — Static assets
|
|
604
|
+
src/seeds/ — Database seeders
|
|
605
|
+
migrations/ — SQL migration files
|
|
606
|
+
spec/ — RSpec tests
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
## CLI Commands
|
|
610
|
+
|
|
611
|
+
```bash
|
|
612
|
+
tina4ruby init . # Scaffold project
|
|
613
|
+
tina4ruby serve # Start dev server on port 7147
|
|
614
|
+
tina4ruby serve --dev # Dev mode with auto-reload
|
|
615
|
+
tina4ruby migrate # Run database migrations
|
|
616
|
+
tina4ruby test # Run test suite
|
|
617
|
+
tina4ruby routes # List all registered routes
|
|
618
|
+
tina4ruby seed # Run database seeders
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
## Route Pattern
|
|
622
|
+
|
|
623
|
+
```ruby
|
|
624
|
+
Tina4.get "/api/users" do |request, response|
|
|
625
|
+
response.call({ users: [] }, Tina4::HTTP_OK)
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
Tina4.post "/api/users" do |request, response|
|
|
629
|
+
response.call({ created: request.body["name"] }, 201)
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
# Protected GET route
|
|
633
|
+
Tina4.secure_get "/api/admin/users" do |request, response|
|
|
634
|
+
response.call({ users: User.all }, Tina4::HTTP_OK)
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
# Route with template rendering
|
|
638
|
+
Tina4::Router.get "/dashboard", template: "dashboard.twig" do |request, response|
|
|
639
|
+
response.call({ title: "Dashboard" }, Tina4::HTTP_OK)
|
|
640
|
+
end
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
## ORM Pattern
|
|
644
|
+
|
|
645
|
+
```ruby
|
|
646
|
+
class User < Tina4::ORM
|
|
647
|
+
table_name "users"
|
|
648
|
+
integer_field :id, primary_key: true, auto_increment: true
|
|
649
|
+
string_field :name, required: true
|
|
650
|
+
string_field :email
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
# Usage
|
|
654
|
+
user = User.create(name: "Alice", email: "alice@example.com")
|
|
655
|
+
users = User.where("name LIKE ?", ["%ali%"])
|
|
656
|
+
user = User.find(1)
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
## Template Pattern
|
|
660
|
+
|
|
661
|
+
```twig
|
|
662
|
+
{% extends "base.twig" %}
|
|
663
|
+
{% block content %}
|
|
664
|
+
<div class="container">
|
|
665
|
+
<h1>{{ title }}</h1>
|
|
666
|
+
{% for item in items %}
|
|
667
|
+
<p>{{ item.name }}</p>
|
|
668
|
+
{% endfor %}
|
|
669
|
+
</div>
|
|
670
|
+
{% endblock %}
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
## Conventions
|
|
674
|
+
|
|
675
|
+
1. Routes return `response.call(data, status)` — never `puts` or `render`
|
|
676
|
+
2. GET routes are public; POST/PUT/PATCH/DELETE require auth by default
|
|
677
|
+
3. Every template extends `base.twig`
|
|
678
|
+
4. All schema changes via migrations — never create tables in route code
|
|
679
|
+
5. Use built-in features — never install gems for things Tina4 already provides
|
|
680
|
+
6. Service pattern — complex logic in `src/app/`, routes stay thin
|
|
681
|
+
7. Use `snake_case` for methods and variables
|
|
682
|
+
8. Wrap route logic in `begin/rescue`, log with `Tina4::Log.error()`
|
|
683
|
+
9. Database drivers: SQLite, PostgreSQL, MySQL, MSSQL, Firebird
|
|
684
|
+
|
|
685
|
+
## Built-in Features (No Gems Needed)
|
|
686
|
+
|
|
687
|
+
Router, ORM, Database (SQLite/PostgreSQL/MySQL/MSSQL/Firebird), Frond templates (Twig-compatible), JWT auth, Sessions (File/Redis/Valkey/MongoDB/DB), GraphQL + GraphiQL, WebSocket + Redis backplane, WSDL/SOAP, Queue (File/RabbitMQ/Kafka/MongoDB), HTTP client, Messenger (SMTP/IMAP), FakeData/Seeder, Migrations, SCSS compiler, Swagger/OpenAPI, i18n, Events, Container/DI, HtmlElement, Inline testing, Error overlay, Dev dashboard, Rate limiter, Response cache, Logging, MCP server
|
|
688
|
+
|
|
689
|
+
## Testing
|
|
690
|
+
|
|
691
|
+
Run: `bundle exec rspec` or `tina4ruby test`. Tests live in `spec/`. Use `Tina4::Testing` for inline tests.
|
|
692
|
+
CONTEXT
|
|
693
|
+
end
|
|
336
694
|
end
|
|
337
695
|
end
|
|
338
696
|
end
|