syntropy 0.30.0 → 0.32.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.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +30 -0
  4. data/TODO.md +46 -1
  5. data/bin/syntropy +8 -86
  6. data/cmd/_banner.rb +16 -0
  7. data/cmd/console.rb +77 -0
  8. data/cmd/help.rb +12 -0
  9. data/cmd/serve.rb +95 -0
  10. data/cmd/test.rb +40 -0
  11. data/examples/{counter.rb → basic/counter.rb} +1 -1
  12. data/examples/{templates.rb → basic/templates.rb} +1 -1
  13. data/examples/blog/app/_layout/default.rb +11 -0
  14. data/examples/blog/app/_lib/post_store.rb +47 -0
  15. data/examples/blog/app/_schema/2026-01-01-initial.rb +9 -0
  16. data/examples/blog/app/_setup.rb +4 -0
  17. data/examples/blog/app/index.rb +7 -0
  18. data/examples/blog/app/posts/[id]/edit.rb +33 -0
  19. data/examples/blog/app/posts/[id]/index.rb +58 -0
  20. data/examples/blog/app/posts/index.rb +38 -0
  21. data/examples/blog/app/posts/new.rb +29 -0
  22. data/examples/mcp-oauth/.ruby-version +1 -0
  23. data/examples/mcp-oauth/Gemfile +8 -0
  24. data/examples/mcp-oauth/README.md +128 -0
  25. data/examples/mcp-oauth/app/.well-known/oauth-authorization-server.rb +18 -0
  26. data/examples/mcp-oauth/app/.well-known/oauth-protected-resource.rb +10 -0
  27. data/examples/mcp-oauth/app/_lib/auth_store.rb +23 -0
  28. data/examples/mcp-oauth/app/index.md +1 -0
  29. data/examples/mcp-oauth/app/mcp.rb +85 -0
  30. data/examples/mcp-oauth/app/oauth/authorize.rb +18 -0
  31. data/examples/mcp-oauth/app/oauth/consent.rb +86 -0
  32. data/examples/mcp-oauth/app/oauth/register.rb +14 -0
  33. data/examples/mcp-oauth/app/oauth/token.rb +79 -0
  34. data/examples/mcp-oauth/app/signin.rb +85 -0
  35. data/examples/mcp-oauth/test/helper.rb +9 -0
  36. data/examples/mcp-oauth/test/test_app.rb +27 -0
  37. data/examples/mcp-oauth/test/test_oauth.rb +628 -0
  38. data/lib/syntropy/app.rb +34 -9
  39. data/lib/syntropy/applets/builtin/default_error_handler.rb +3 -3
  40. data/lib/syntropy/applets/builtin/req.rb +1 -1
  41. data/lib/syntropy/db/connection_pool.rb +71 -0
  42. data/lib/syntropy/db/schema.rb +92 -0
  43. data/lib/syntropy/db/store.rb +31 -0
  44. data/lib/syntropy/dev_mode.rb +1 -1
  45. data/lib/syntropy/errors.rb +6 -0
  46. data/lib/syntropy/http/client.rb +43 -0
  47. data/lib/syntropy/http/client_connection.rb +36 -0
  48. data/lib/syntropy/http/io_extensions.rb +176 -0
  49. data/lib/syntropy/http/server.rb +5 -5
  50. data/lib/syntropy/http/{connection.rb → server_connection.rb} +15 -91
  51. data/lib/syntropy/http.rb +3 -1
  52. data/lib/syntropy/logger.rb +5 -1
  53. data/lib/syntropy/{module.rb → module_loader.rb} +47 -8
  54. data/lib/syntropy/papercraft_extensions.rb +1 -1
  55. data/lib/syntropy/request/mock_adapter.rb +2 -0
  56. data/lib/syntropy/request/request_info.rb +22 -4
  57. data/lib/syntropy/request/response.rb +2 -2
  58. data/lib/syntropy/request/validation.rb +11 -5
  59. data/lib/syntropy/routing_tree.rb +2 -1
  60. data/lib/syntropy/test.rb +77 -0
  61. data/lib/syntropy/version.rb +1 -1
  62. data/lib/syntropy.rb +5 -23
  63. data/syntropy.gemspec +3 -3
  64. data/test/app/.well-known/foo.rb +3 -0
  65. data/test/app/_hook.rb +1 -1
  66. data/test/app/by_method.rb +9 -0
  67. data/test/app_setup/_setup.rb +7 -0
  68. data/test/app_setup/index.rb +1 -0
  69. data/test/app_with_schema/_schema/2026-01-02-foo.rb +12 -0
  70. data/test/app_with_schema/_schema/2026-05-30-bar.rb +7 -0
  71. data/test/helper.rb +1 -25
  72. data/test/schema/2026-01-02-foo.rb +12 -0
  73. data/test/schema/2026-05-30-bar.rb +7 -0
  74. data/test/test_app.rb +110 -70
  75. data/test/test_caching.rb +1 -1
  76. data/test/{test_connection_pool.rb → test_db_connection_pool.rb} +7 -2
  77. data/test/test_db_schema.rb +96 -0
  78. data/test/test_db_store.rb +24 -0
  79. data/test/test_http_client.rb +52 -0
  80. data/test/test_http_client_connection.rb +43 -0
  81. data/test/test_http_protocol.rb +250 -0
  82. data/test/{test_connection.rb → test_http_server_connection.rb} +39 -48
  83. data/test/test_json_api.rb +5 -5
  84. data/test/{test_module.rb → test_module_loader.rb} +31 -0
  85. data/test/{test_request_extensions.rb → test_request.rb} +153 -18
  86. data/test/test_routing_tree.rb +15 -3
  87. data/test/test_server.rb +9 -13
  88. metadata +84 -36
  89. data/lib/syntropy/connection_pool.rb +0 -61
  90. data/test/test_request_info.rb +0 -90
  91. /data/examples/{bad.rb → basic/bad.rb} +0 -0
  92. /data/examples/{card.rb → basic/card.rb} +0 -0
  93. /data/examples/{counter.js → basic/counter.js} +0 -0
  94. /data/examples/{counter_api.rb → basic/counter_api.rb} +0 -0
  95. /data/examples/{favicon.ico → basic/favicon.ico} +0 -0
  96. /data/examples/{index.md → basic/index.md} +0 -0
@@ -1,90 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'helper'
4
-
5
- class RequestInfoTest < Minitest::Test
6
- def test_uri
7
- r = Syntropy::MockAdapter.mock(':path' => '/test/path')
8
- assert_equal '/test/path', r.path
9
- assert_equal({}, r.query)
10
-
11
- r = Syntropy::MockAdapter.mock(':path' => '/test/path?a=1&b=2&c=3%2f4')
12
- assert_equal '/test/path', r.path
13
- assert_equal({ a: '1', b: '2', c: '3/4' }, r.query)
14
- end
15
-
16
- def test_query
17
- r = Syntropy::MockAdapter.mock(':path' => '/GponForm/diag_Form?images/')
18
- assert_equal '/GponForm/diag_Form', r.path
19
- assert_equal({:'images/' => true}, r.query)
20
-
21
- r = Syntropy::MockAdapter.mock(':path' => '/?a=1&b=2')
22
- assert_equal '/', r.path
23
- assert_equal({a: '1', b: '2'}, r.query)
24
-
25
- r = Syntropy::MockAdapter.mock(':path' => '/?l=a&t=&x=42')
26
- assert_equal({l: 'a', t: '', x: '42'}, r.query)
27
- end
28
-
29
- def test_host
30
- r = Syntropy::MockAdapter.mock(':path' => '/')
31
- assert_nil r.host
32
- assert_nil r.authority
33
-
34
- r = Syntropy::MockAdapter.mock('host' => 'my.example.com')
35
- assert_equal 'my.example.com', r.host
36
- assert_equal 'my.example.com', r.authority
37
-
38
- r = Syntropy::MockAdapter.mock(':authority' => 'my.foo.com')
39
- assert_equal 'my.foo.com', r.host
40
- assert_equal 'my.foo.com', r.authority
41
- end
42
-
43
- def test_full_uri
44
- r = Syntropy::MockAdapter.mock(
45
- ':scheme' => 'https',
46
- 'host' => 'foo.bar',
47
- ':path' => '/hey?a=b&c=d'
48
- )
49
-
50
- assert_equal 'https://foo.bar/hey?a=b&c=d', r.full_uri
51
- end
52
-
53
- def test_cookies
54
- r = Syntropy::MockAdapter.mock
55
-
56
- assert_equal({}, r.cookies)
57
-
58
- r = Syntropy::MockAdapter.mock(
59
- 'cookie' => 'uaid=a%2Fb; lastLocus=settings; signin_ref=/'
60
- )
61
-
62
- assert_equal({
63
- 'uaid' => 'a/b',
64
- 'lastLocus' => 'settings',
65
- 'signin_ref' => '/'
66
- }, r.cookies)
67
- end
68
-
69
- def test_rewrite!
70
- r = Syntropy::MockAdapter.mock(
71
- ':scheme' => 'https',
72
- 'host' => 'foo.bar',
73
- ':path' => '/hey/ho?a=b&c=d'
74
- )
75
-
76
- assert_equal '/hey/ho', r.path
77
- assert_equal URI.parse('/hey/ho?a=b&c=d'), r.uri
78
- assert_equal 'https://foo.bar/hey/ho?a=b&c=d', r.full_uri
79
-
80
- r.rewrite!('/hhh', '/')
81
- assert_equal '/hey/ho', r.path
82
- assert_equal URI.parse('/hey/ho?a=b&c=d'), r.uri
83
- assert_equal 'https://foo.bar/hey/ho?a=b&c=d', r.full_uri
84
-
85
- r.rewrite!('/hey', '/')
86
- assert_equal '/ho', r.path
87
- assert_equal URI.parse('/ho?a=b&c=d'), r.uri
88
- assert_equal 'https://foo.bar/ho?a=b&c=d', r.full_uri
89
- end
90
- end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes