tina4 0.3.0 → 0.4.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: 72ab361453b9a6f60b1d62f9450dbab31a94d4ef69af9fb51c3e3047035d8ce9
4
- data.tar.gz: 7c8d983c70fb05f14a4da70d9b743c61b652efd825b5152c9d85a4ea859e2826
3
+ metadata.gz: 5418ddd6412424d2a754ec45b7a435d1d189dcbfdfc0ddfcff54b02f5993d5ca
4
+ data.tar.gz: 8729da6284e85d545426c96b8b8e5a33b22b040270cd6e0fd754bb9f75e71198
5
5
  SHA512:
6
- metadata.gz: dbe3231942c281359623df045a34ca3e0687e9383c2bc678914f30dd5075190b7b7e1531752531b04b72878e625665add006e55e0beb5a2c4d153582a8f4f2d7
7
- data.tar.gz: 91e996e88bdbda88b4d6b7791f4fdea9af0e633f941b4f231474df1400d5882c10c3039fa9b62d18d31654d7b1ee4fae9f1fea14bc12433fb31c37854abd26a3
6
+ metadata.gz: e63ae672c5752d40cb22785438897ae0b6cbdea0e52402cf749dec6eba22786b4da72873ab87f2de3df8df73ed0a2abd15e925dcf8aeffaddb660900834f5b5d
7
+ data.tar.gz: 1fdfcf15878f12d1cc4451dd0a9cdb73e659455d8e1c54ccbeba41d4acd1396d08c5c7022f75037fb4590c7d36c99e67968fdc7c3ae1d6461f5a50208a731263
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.0] - 2026-03-18
4
+
5
+ ### Added
6
+ - Multi-stage Dockerfile (ruby:3.3-alpine, build + runtime stages, optimized layer caching)
7
+ - .dockerignore for clean Docker builds
8
+ - `tina4 init` now generates Dockerfile and .dockerignore alongside project scaffolding
9
+
3
10
  ## [0.3.0] - 2026-03-14
4
11
 
5
12
  ### Added
data/README.md CHANGED
@@ -517,6 +517,102 @@ end
517
517
 
518
518
  Visit `http://localhost:7145/swagger` for the interactive Swagger UI.
519
519
 
520
+ ## GraphQL
521
+
522
+ Zero-dependency GraphQL support with a custom parser, executor, and ORM auto-schema generation.
523
+
524
+ ### Manual Schema
525
+
526
+ ```ruby
527
+ schema = Tina4::GraphQLSchema.new
528
+
529
+ # Add queries
530
+ schema.add_query("hello", type: "String") { |_root, _args, _ctx| "Hello World!" }
531
+
532
+ schema.add_query("user", type: "User", args: { "id" => { type: "ID!" } }) do |_root, args, _ctx|
533
+ User.find(args["id"])&.to_hash
534
+ end
535
+
536
+ # Add mutations
537
+ schema.add_mutation("createUser", type: "User",
538
+ args: { "name" => { type: "String!" }, "email" => { type: "String!" } }
539
+ ) do |_root, args, _ctx|
540
+ User.create(name: args["name"], email: args["email"]).to_hash
541
+ end
542
+
543
+ # Register the /graphql endpoint
544
+ gql = Tina4::GraphQL.new(schema)
545
+ gql.register_route # POST /graphql + GET /graphql (GraphiQL UI)
546
+ ```
547
+
548
+ ### ORM Auto-Schema
549
+
550
+ Generate full CRUD queries and mutations from your ORM models with one line:
551
+
552
+ ```ruby
553
+ schema = Tina4::GraphQLSchema.new
554
+ schema.from_orm(User) # Creates: user, users, createUser, updateUser, deleteUser
555
+ schema.from_orm(Product) # Creates: product, products, createProduct, updateProduct, deleteProduct
556
+
557
+ gql = Tina4::GraphQL.new(schema)
558
+ gql.register_route("/graphql")
559
+ ```
560
+
561
+ This auto-generates:
562
+ - **Queries:** `user(id)` (single), `users(limit, offset)` (list with pagination)
563
+ - **Mutations:** `createUser(input)`, `updateUser(id, input)`, `deleteUser(id)`
564
+
565
+ ### Query Examples
566
+
567
+ ```graphql
568
+ # Simple query
569
+ { hello }
570
+
571
+ # Nested fields with arguments
572
+ { user(id: 42) { id name email } }
573
+
574
+ # List with pagination
575
+ { users(limit: 10, offset: 0) { id name } }
576
+
577
+ # Aliases
578
+ { admin: user(id: 1) { name } guest: user(id: 2) { name } }
579
+
580
+ # Variables
581
+ query GetUser($userId: ID!) {
582
+ user(id: $userId) { id name email }
583
+ }
584
+
585
+ # Fragments
586
+ fragment UserFields on User { id name email }
587
+ { user(id: 1) { ...UserFields } }
588
+
589
+ # Mutations
590
+ mutation {
591
+ createUser(name: "Alice", email: "alice@example.com") { id name }
592
+ }
593
+ ```
594
+
595
+ ### Programmatic Execution
596
+
597
+ ```ruby
598
+ gql = Tina4::GraphQL.new(schema)
599
+
600
+ # Execute a query directly
601
+ result = gql.execute('{ hello }')
602
+ puts result["data"]["hello"] # "Hello World!"
603
+
604
+ # With variables
605
+ result = gql.execute(
606
+ 'query($id: ID!) { user(id: $id) { name } }',
607
+ variables: { "id" => 42 }
608
+ )
609
+
610
+ # Handle an HTTP request body (JSON string)
611
+ result = gql.handle_request('{"query": "{ hello }"}')
612
+ ```
613
+
614
+ Visit `http://localhost:7145/graphql` for the interactive GraphiQL UI.
615
+
520
616
  ## REST API Client
521
617
 
522
618
  ```ruby
data/lib/tina4/cli.rb CHANGED
@@ -217,6 +217,75 @@ module Tina4
217
217
  TEXT
218
218
  end
219
219
 
220
+ # Dockerfile
221
+ unless File.exist?(File.join(dir, "Dockerfile"))
222
+ File.write(File.join(dir, "Dockerfile"), <<~DOCKERFILE)
223
+ # === Build Stage ===
224
+ FROM ruby:3.3-alpine AS builder
225
+
226
+ # Install build dependencies
227
+ RUN apk add --no-cache \\
228
+ build-base \\
229
+ libffi-dev \\
230
+ gcompat
231
+
232
+ WORKDIR /app
233
+
234
+ # Copy dependency definition first (layer caching)
235
+ COPY Gemfile Gemfile.lock* ./
236
+
237
+ # Install gems
238
+ RUN bundle config set --local without 'development test' && \\
239
+ bundle install --jobs 4 --retry 3
240
+
241
+ # Copy application code
242
+ COPY . .
243
+
244
+ # === Runtime Stage ===
245
+ FROM ruby:3.3-alpine
246
+
247
+ # Runtime packages only
248
+ RUN apk add --no-cache libffi gcompat
249
+
250
+ WORKDIR /app
251
+
252
+ # Copy installed gems
253
+ COPY --from=builder /usr/local/bundle /usr/local/bundle
254
+
255
+ # Copy application code
256
+ COPY --from=builder /app /app
257
+
258
+ EXPOSE 7145
259
+
260
+ # Swagger defaults (override with env vars in docker-compose/k8s if needed)
261
+ ENV SWAGGER_TITLE="Tina4 API"
262
+ ENV SWAGGER_VERSION="0.1.0"
263
+ ENV SWAGGER_DESCRIPTION="Auto-generated API documentation"
264
+
265
+ # Start the server on all interfaces
266
+ CMD ["bundle", "exec", "tina4", "start", "-p", "7145", "-h", "0.0.0.0"]
267
+ DOCKERFILE
268
+ puts " Created Dockerfile"
269
+ end
270
+
271
+ # .dockerignore
272
+ unless File.exist?(File.join(dir, ".dockerignore"))
273
+ File.write(File.join(dir, ".dockerignore"), <<~TEXT)
274
+ .git
275
+ .env
276
+ .keys/
277
+ logs/
278
+ sessions/
279
+ .queue/
280
+ *.db
281
+ *.gem
282
+ tmp/
283
+ spec/
284
+ vendor/bundle
285
+ TEXT
286
+ puts " Created .dockerignore"
287
+ end
288
+
220
289
  # Base template
221
290
  templates_dir = File.join(dir, "templates")
222
291
  unless File.exist?(File.join(templates_dir, "base.twig"))
data/lib/tina4/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tina4
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tina4
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tina4 Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-03-14 00:00:00.000000000 Z
11
+ date: 2026-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack