kabk 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.

Potentially problematic release.


This version of kabk might be problematic. Click here for more details.

Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +27 -0
  3. data/Gemfile +6 -0
  4. data/Gemfile.lock +108 -0
  5. data/Kabk_logo.svg +33 -0
  6. data/LICENSE +21 -0
  7. data/README.md +101 -0
  8. data/doc/Kabk/Adapters/Base.html +854 -0
  9. data/doc/Kabk/Adapters/SequelAdapter.html +948 -0
  10. data/doc/Kabk/Adapters.html +120 -0
  11. data/doc/Kabk/ApiError.html +511 -0
  12. data/doc/Kabk/Auth/JwtStrategy.html +551 -0
  13. data/doc/Kabk/Auth.html +118 -0
  14. data/doc/Kabk/Concurrency.html +297 -0
  15. data/doc/Kabk/ConcurrencyConflictError.html +225 -0
  16. data/doc/Kabk/Error.html +140 -0
  17. data/doc/Kabk/ExportHandler.html +381 -0
  18. data/doc/Kabk/Field.html +2160 -0
  19. data/doc/Kabk/ForbiddenError.html +225 -0
  20. data/doc/Kabk/InvalidFieldError.html +136 -0
  21. data/doc/Kabk/InvalidOldPasswordError.html +225 -0
  22. data/doc/Kabk/NotFoundError.html +225 -0
  23. data/doc/Kabk/QueryBuilder.html +551 -0
  24. data/doc/Kabk/Registry.html +608 -0
  25. data/doc/Kabk/RelationHydrator.html +480 -0
  26. data/doc/Kabk/Resource.html +1986 -0
  27. data/doc/Kabk/ResourceBuilder.html +1002 -0
  28. data/doc/Kabk/RestEngine.html +879 -0
  29. data/doc/Kabk/SchemaRenderer.html +318 -0
  30. data/doc/Kabk/UnauthorizedError.html +225 -0
  31. data/doc/Kabk/UploadHandler.html +308 -0
  32. data/doc/Kabk/ValidationError.html +225 -0
  33. data/doc/Kabk/Validator.html +380 -0
  34. data/doc/Kabk.html +330 -0
  35. data/doc/_index.html +376 -0
  36. data/doc/class_list.html +54 -0
  37. data/doc/css/common.css +1 -0
  38. data/doc/css/full_list.css +206 -0
  39. data/doc/css/style.css +1089 -0
  40. data/doc/file.README.html +149 -0
  41. data/doc/file_list.html +59 -0
  42. data/doc/frames.html +22 -0
  43. data/doc/index.html +149 -0
  44. data/doc/js/app.js +801 -0
  45. data/doc/js/full_list.js +334 -0
  46. data/doc/js/jquery.js +4 -0
  47. data/doc/method_list.html +910 -0
  48. data/doc/top-level-namespace.html +112 -0
  49. data/docs/API_REFERENCE.md +241 -0
  50. data/lib/kabk/adapters/base.rb +45 -0
  51. data/lib/kabk/adapters/sequel_adapter.rb +125 -0
  52. data/lib/kabk/concurrency.rb +30 -0
  53. data/lib/kabk/errors.rb +62 -0
  54. data/lib/kabk/export_handler.rb +43 -0
  55. data/lib/kabk/field.rb +97 -0
  56. data/lib/kabk/query_builder.rb +72 -0
  57. data/lib/kabk/registry.rb +41 -0
  58. data/lib/kabk/relation_hydrator.rb +107 -0
  59. data/lib/kabk/resource.rb +88 -0
  60. data/lib/kabk/resource_builder.rb +93 -0
  61. data/lib/kabk/rest_engine.rb +84 -0
  62. data/lib/kabk/schema_renderer.rb +69 -0
  63. data/lib/kabk/upload_handler.rb +24 -0
  64. data/lib/kabk/validator.rb +64 -0
  65. data/lib/kabk/version.rb +6 -0
  66. data/lib/kabk.rb +51 -0
  67. metadata +193 -0
@@ -0,0 +1,149 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ File: README
8
+
9
+ &mdash; Documentation by YARD 0.9.45
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css">
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css">
16
+
17
+ <script type="text/javascript">
18
+ pathId = "README";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div id="main_progress" aria-hidden="true"></div>
31
+
32
+ <div class="nav_wrap">
33
+ <iframe id="nav" src="file_list.html?1"></iframe>
34
+ <div id="resizer"></div>
35
+ </div>
36
+
37
+ <div id="main" tabindex="-1">
38
+ <div id="header">
39
+ <div id="menu">
40
+
41
+ <a href="_index.html">Index</a> &raquo;
42
+ <span class="title">File: README</span>
43
+
44
+ </div>
45
+
46
+ <div id="search">
47
+
48
+ <a class="full_list_link" id="class_list_link"
49
+ href="class_list.html">
50
+
51
+ <svg width="24" height="24">
52
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
53
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
54
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
55
+ </svg>
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <div id="content"><div id='filecontents'><h1 align="center">
63
+ <img src="https://raw.githubusercontent.com/par-taheri/Kabk/main/Kabk_logo.svg" alt="Kabk Logo" width="200" />
64
+ </h1>
65
+ <p align="center">
66
+ <a href="https://rubygems.org/gems/kabk"><img src="https://img.shields.io/gem/v/kabk.svg?color=blue" alt="Gem Version"></a>
67
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
68
+ </p>
69
+ <blockquote>
70
+ <p><strong>Kabk carries the Ruby to Simorgh</strong></p>
71
+ </blockquote>
72
+ <p>The framework-agnostic Ruby backend engine designed exclusively to power the Simurgh Panel.</p>
73
+ <h2 id="Installation">Installation</h2>
74
+ <p>Add this line to your application's Gemfile:</p>
75
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_gem'>gem</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>kabk</span><span class='tstring_end'>&#39;</span></span>
76
+ </code></pre>
77
+ <h2 id="Usage">Usage</h2>
78
+ <p>This gem manages the metadata registry, schema manifest generation, server-side validation, pagination, and concurrency control. Kabk is ORM-agnostic and relies on the Adapter pattern to interface with your database (e.g., via Sequel). It operates entirely on plain Ruby hashes and assumes your host application (like Roda or Rails) handles authentication and authorization.</p>
79
+ <h3 id="Registering_a_Resource">Registering a Resource</h3>
80
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>kabk</span><span class='tstring_end'>&#39;</span></span>
81
+
82
+ <span class='comment'># Assuming you have a Sequel Model
83
+ </span><span class='kw'>class</span> <span class='const'>NewsItem</span> <span class='op'>&lt;</span> <span class='const'>Sequel</span><span class='op'>::</span><span class='const'>Model</span><span class='semicolon'>;</span> <span class='kw'>end</span>
84
+
85
+ <span class='comment'># Kabk automatically detects Sequel models and uses the Kabk::Adapters::SequelAdapter
86
+ </span>
87
+ <span class='const'><span class='object_link'><a href="Kabk.html" title="Kabk (module)">Kabk</a></span></span><span class='period'>.</span><span class='id identifier rubyid_register'><span class='object_link'><a href="Kabk.html#register-class_method" title="Kabk.register (method)">register</a></span></span><span class='lparen'>(</span><span class='label'>name:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>news_item</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='label'>table:</span> <span class='const'>NewsItem</span><span class='rparen'>)</span> <span class='kw'>do</span>
88
+ <span class='id identifier rubyid_title'>title</span> <span class='label'>fa:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>اخبار و اطلاعیه‌ها</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='label'>en:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>News &amp; Announcements</span><span class='tstring_end'>&#39;</span></span>
89
+ <span class='id identifier rubyid_icon'>icon</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Newspaper</span><span class='tstring_end'>&#39;</span></span>
90
+ <span class='id identifier rubyid_plural_name'>plural_name</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>news</span><span class='tstring_end'>&#39;</span></span>
91
+ <span class='id identifier rubyid_api_path'>api_path</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>/api/admin/news</span><span class='tstring_end'>&#39;</span></span>
92
+
93
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:id</span><span class='comma'>,</span> <span class='label'>type:</span> <span class='symbol'>:number</span><span class='comma'>,</span> <span class='label'>form_type:</span> <span class='symbol'>:number</span><span class='comma'>,</span> <span class='label'>primary_key:</span> <span class='kw'>true</span><span class='comma'>,</span> <span class='label'>hidden_in_form:</span> <span class='kw'>true</span>
94
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:title</span><span class='comma'>,</span> <span class='label'>type:</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>form_type:</span> <span class='symbol'>:text</span><span class='comma'>,</span> <span class='label'>required:</span> <span class='kw'>true</span><span class='comma'>,</span> <span class='label'>validation:</span> <span class='lbrace'>{</span> <span class='label'>min_length:</span> <span class='int'>5</span> <span class='rbrace'>}</span>
95
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:content</span><span class='comma'>,</span> <span class='label'>type:</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>form_type:</span> <span class='symbol'>:wysiwyg</span>
96
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:publish_date</span><span class='comma'>,</span> <span class='label'>type:</span> <span class='symbol'>:datetime</span><span class='comma'>,</span> <span class='label'>form_type:</span> <span class='symbol'>:datetime</span><span class='comma'>,</span> <span class='label'>calendar:</span> <span class='symbol'>:jalali</span>
97
+
98
+ <span class='comment'># Lifecycle Hooks
99
+ </span> <span class='id identifier rubyid_before_create'>before_create</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_params'>params</span><span class='comma'>,</span> <span class='id identifier rubyid_context'>context</span><span class='op'>|</span>
100
+ <span class='id identifier rubyid_params'>params</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>created_by</span><span class='tstring_end'>&quot;</span></span><span class='rbracket'>]</span> <span class='op'>=</span> <span class='id identifier rubyid_context'>context</span><span class='lbracket'>[</span><span class='symbol'>:current_user_id</span><span class='rbracket'>]</span>
101
+ <span class='kw'>end</span>
102
+
103
+ <span class='id identifier rubyid_after_create'>after_create</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_record'>record</span><span class='comma'>,</span> <span class='id identifier rubyid_context'>context</span><span class='op'>|</span>
104
+ <span class='comment'># trigger background job
105
+ </span> <span class='kw'>end</span>
106
+ <span class='kw'>end</span>
107
+ </code></pre>
108
+ <h3 id="Generic_REST_Engine">Generic REST Engine</h3>
109
+ <p>The <code>Kabk::RestEngine</code> class orchestrates validation and delegates CRUD operations to the configured ORM adapter. It returns standardized raw hashes that your HTTP layer can easily convert to JSON.</p>
110
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_engine'>engine</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="Kabk.html" title="Kabk (module)">Kabk</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Kabk/RestEngine.html" title="Kabk::RestEngine (class)">RestEngine</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'><span class='object_link'><a href="Kabk/RestEngine.html#initialize-instance_method" title="Kabk::RestEngine#initialize (method)">new</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>news_item</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
111
+
112
+ <span class='comment'># Pagination, Filtering, Sorting, and Hydration are automatic
113
+ </span><span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='id identifier rubyid_engine'>engine</span><span class='period'>.</span><span class='id identifier rubyid_list'>list</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>page</span><span class='tstring_end'>&quot;</span></span> <span class='op'>=&gt;</span> <span class='int'>1</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>per_page</span><span class='tstring_end'>&quot;</span></span> <span class='op'>=&gt;</span> <span class='int'>15</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>sort</span><span class='tstring_end'>&quot;</span></span> <span class='op'>=&gt;</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>-created_at</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
114
+ <span class='comment'># =&gt; { success: true, data: [...], meta: { ... } }
115
+ </span>
116
+ <span class='comment'># Validation and OCC automatically applied
117
+ </span><span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='id identifier rubyid_engine'>engine</span><span class='period'>.</span><span class='id identifier rubyid_update'>update</span><span class='lparen'>(</span><span class='int'>1</span><span class='comma'>,</span> <span class='lbrace'>{</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>title</span><span class='tstring_end'>&quot;</span></span> <span class='op'>=&gt;</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>New Title</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>updated_at</span><span class='tstring_end'>&quot;</span></span> <span class='op'>=&gt;</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>2026-03-15T11:00:00Z</span><span class='tstring_end'>&quot;</span></span> <span class='rbrace'>}</span><span class='rparen'>)</span>
118
+ </code></pre>
119
+ <h3 id="System_Configuration__Protocol_v1_6_0_">System Configuration (Protocol v1.6.0)</h3>
120
+ <p>Kabk generates a JSON schema manifest containing dynamic system configuration and UI settings. You can override these defaults by passing a custom hash to the <code>SchemaRenderer</code>. Ensure you inject your authentication endpoints here, as Kabk itself does not provide them.</p>
121
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_renderer'>renderer</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="Kabk.html" title="Kabk (module)">Kabk</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Kabk/SchemaRenderer.html" title="Kabk::SchemaRenderer (class)">SchemaRenderer</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'><span class='object_link'><a href="Kabk/SchemaRenderer.html#initialize-instance_method" title="Kabk::SchemaRenderer#initialize (method)">new</a></span></span><span class='lparen'>(</span>
122
+ <span class='label'>system_config:</span> <span class='lbrace'>{</span>
123
+ <span class='label'>title:</span> <span class='lbrace'>{</span> <span class='label'>fa:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>پنل مدیریت</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='label'>en:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>My Custom Admin</span><span class='tstring_end'>&quot;</span></span> <span class='rbrace'>}</span><span class='comma'>,</span>
124
+ <span class='label'>logo_url:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/custom-logo.png</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
125
+ <span class='label'>endpoints:</span> <span class='lbrace'>{</span>
126
+ <span class='label'>login:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/auth/admin_login</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
127
+ <span class='label'>me:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/auth/admin_me</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
128
+ <span class='label'>logout:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/auth/admin_logout</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
129
+ <span class='label'>refresh:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/auth/admin_refresh</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
130
+ <span class='label'>upload:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/api/files</span><span class='tstring_end'>&quot;</span></span>
131
+ <span class='rbrace'>}</span>
132
+ <span class='rbrace'>}</span>
133
+ <span class='rparen'>)</span>
134
+ <span class='id identifier rubyid_schema'>schema</span> <span class='op'>=</span> <span class='id identifier rubyid_renderer'>renderer</span><span class='period'>.</span><span class='id identifier rubyid_render'>render</span>
135
+ </code></pre>
136
+ <h2 id="Testing">Testing</h2>
137
+ <pre class="code bash"><code class="bash">bundle install
138
+ bundle exec rspec
139
+ </code></pre></div></div>
140
+
141
+ <div id="footer">
142
+ Generated on Tue Aug 11 21:17:05 2026 by
143
+ <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
144
+ 0.9.45 (ruby-4.0.6).
145
+ </div>
146
+
147
+ </div>
148
+ </body>
149
+ </html>
@@ -0,0 +1,59 @@
1
+ <!DOCTYPE html>
2
+ <html >
3
+ <head>
4
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
5
+ <meta charset="utf-8">
6
+
7
+ <link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen">
8
+
9
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen">
10
+
11
+
12
+
13
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
14
+
15
+ <script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
16
+
17
+
18
+ <title>File List</title>
19
+ <base id="base_target" target="_parent">
20
+ </head>
21
+ <body>
22
+ <div id="content">
23
+ <div class="fixed_header">
24
+ <h1 id="full_list_header">File List</h1>
25
+ <div id="full_list_nav">
26
+
27
+ <span><a target="_self" href="class_list.html">
28
+ Classes
29
+ </a></span>
30
+
31
+ <span><a target="_self" href="method_list.html">
32
+ Methods
33
+ </a></span>
34
+
35
+ <span><a target="_self" href="file_list.html">
36
+ Files
37
+ </a></span>
38
+
39
+ </div>
40
+
41
+ <div id="search">
42
+ <label for="search-class">Search:</label>
43
+ <input id="search-class" type="text">
44
+ </div>
45
+ </div>
46
+
47
+ <ul id="full_list" class="file">
48
+
49
+
50
+ <li id="object_README" class="odd">
51
+ <div class="item"><span class="object_link"><a href="index.html" title="README">README</a></span></div>
52
+ </li>
53
+
54
+
55
+
56
+ </ul>
57
+ </div>
58
+ </body>
59
+ </html>
data/doc/frames.html ADDED
@@ -0,0 +1,22 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Documentation by YARD 0.9.45</title>
6
+ </head>
7
+ <script type="text/javascript">
8
+ var mainUrl = 'index.html';
9
+ try {
10
+ var match = decodeURIComponent(window.location.hash).match(/^#!(.+)/);
11
+ var name = match ? match[1] : mainUrl;
12
+ var url = new URL(name, location.href);
13
+ window.top.location.replace(url.origin === location.origin ? name : mainUrl);
14
+ } catch (e) {
15
+ window.top.location.replace(mainUrl);
16
+ }
17
+ </script>
18
+ <noscript>
19
+ <h1>Oops!</h1>
20
+ <h2>YARD requires JavaScript!</h2>
21
+ </noscript>
22
+ </html>
data/doc/index.html ADDED
@@ -0,0 +1,149 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ File: README
8
+
9
+ &mdash; Documentation by YARD 0.9.45
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css">
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css">
16
+
17
+ <script type="text/javascript">
18
+ pathId = "README";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div id="main_progress" aria-hidden="true"></div>
31
+
32
+ <div class="nav_wrap">
33
+ <iframe id="nav" src="class_list.html?1"></iframe>
34
+ <div id="resizer"></div>
35
+ </div>
36
+
37
+ <div id="main" tabindex="-1">
38
+ <div id="header">
39
+ <div id="menu">
40
+
41
+ <a href="_index.html">Index</a> &raquo;
42
+ <span class="title">File: README</span>
43
+
44
+ </div>
45
+
46
+ <div id="search">
47
+
48
+ <a class="full_list_link" id="class_list_link"
49
+ href="class_list.html">
50
+
51
+ <svg width="24" height="24">
52
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
53
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
54
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
55
+ </svg>
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <div id="content"><div id='filecontents'><h1 align="center">
63
+ <img src="https://raw.githubusercontent.com/par-taheri/Kabk/main/Kabk_logo.svg" alt="Kabk Logo" width="200" />
64
+ </h1>
65
+ <p align="center">
66
+ <a href="https://rubygems.org/gems/kabk"><img src="https://img.shields.io/gem/v/kabk.svg?color=blue" alt="Gem Version"></a>
67
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
68
+ </p>
69
+ <blockquote>
70
+ <p><strong>Kabk carries the Ruby to Simorgh</strong></p>
71
+ </blockquote>
72
+ <p>The framework-agnostic Ruby backend engine designed exclusively to power the Simurgh Panel.</p>
73
+ <h2 id="Installation">Installation</h2>
74
+ <p>Add this line to your application's Gemfile:</p>
75
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_gem'>gem</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>kabk</span><span class='tstring_end'>&#39;</span></span>
76
+ </code></pre>
77
+ <h2 id="Usage">Usage</h2>
78
+ <p>This gem manages the metadata registry, schema manifest generation, server-side validation, pagination, and concurrency control. Kabk is ORM-agnostic and relies on the Adapter pattern to interface with your database (e.g., via Sequel). It operates entirely on plain Ruby hashes and assumes your host application (like Roda or Rails) handles authentication and authorization.</p>
79
+ <h3 id="Registering_a_Resource">Registering a Resource</h3>
80
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>kabk</span><span class='tstring_end'>&#39;</span></span>
81
+
82
+ <span class='comment'># Assuming you have a Sequel Model
83
+ </span><span class='kw'>class</span> <span class='const'>NewsItem</span> <span class='op'>&lt;</span> <span class='const'>Sequel</span><span class='op'>::</span><span class='const'>Model</span><span class='semicolon'>;</span> <span class='kw'>end</span>
84
+
85
+ <span class='comment'># Kabk automatically detects Sequel models and uses the Kabk::Adapters::SequelAdapter
86
+ </span>
87
+ <span class='const'><span class='object_link'><a href="Kabk.html" title="Kabk (module)">Kabk</a></span></span><span class='period'>.</span><span class='id identifier rubyid_register'><span class='object_link'><a href="Kabk.html#register-class_method" title="Kabk.register (method)">register</a></span></span><span class='lparen'>(</span><span class='label'>name:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>news_item</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='label'>table:</span> <span class='const'>NewsItem</span><span class='rparen'>)</span> <span class='kw'>do</span>
88
+ <span class='id identifier rubyid_title'>title</span> <span class='label'>fa:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>اخبار و اطلاعیه‌ها</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='label'>en:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>News &amp; Announcements</span><span class='tstring_end'>&#39;</span></span>
89
+ <span class='id identifier rubyid_icon'>icon</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Newspaper</span><span class='tstring_end'>&#39;</span></span>
90
+ <span class='id identifier rubyid_plural_name'>plural_name</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>news</span><span class='tstring_end'>&#39;</span></span>
91
+ <span class='id identifier rubyid_api_path'>api_path</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>/api/admin/news</span><span class='tstring_end'>&#39;</span></span>
92
+
93
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:id</span><span class='comma'>,</span> <span class='label'>type:</span> <span class='symbol'>:number</span><span class='comma'>,</span> <span class='label'>form_type:</span> <span class='symbol'>:number</span><span class='comma'>,</span> <span class='label'>primary_key:</span> <span class='kw'>true</span><span class='comma'>,</span> <span class='label'>hidden_in_form:</span> <span class='kw'>true</span>
94
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:title</span><span class='comma'>,</span> <span class='label'>type:</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>form_type:</span> <span class='symbol'>:text</span><span class='comma'>,</span> <span class='label'>required:</span> <span class='kw'>true</span><span class='comma'>,</span> <span class='label'>validation:</span> <span class='lbrace'>{</span> <span class='label'>min_length:</span> <span class='int'>5</span> <span class='rbrace'>}</span>
95
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:content</span><span class='comma'>,</span> <span class='label'>type:</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>form_type:</span> <span class='symbol'>:wysiwyg</span>
96
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:publish_date</span><span class='comma'>,</span> <span class='label'>type:</span> <span class='symbol'>:datetime</span><span class='comma'>,</span> <span class='label'>form_type:</span> <span class='symbol'>:datetime</span><span class='comma'>,</span> <span class='label'>calendar:</span> <span class='symbol'>:jalali</span>
97
+
98
+ <span class='comment'># Lifecycle Hooks
99
+ </span> <span class='id identifier rubyid_before_create'>before_create</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_params'>params</span><span class='comma'>,</span> <span class='id identifier rubyid_context'>context</span><span class='op'>|</span>
100
+ <span class='id identifier rubyid_params'>params</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>created_by</span><span class='tstring_end'>&quot;</span></span><span class='rbracket'>]</span> <span class='op'>=</span> <span class='id identifier rubyid_context'>context</span><span class='lbracket'>[</span><span class='symbol'>:current_user_id</span><span class='rbracket'>]</span>
101
+ <span class='kw'>end</span>
102
+
103
+ <span class='id identifier rubyid_after_create'>after_create</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_record'>record</span><span class='comma'>,</span> <span class='id identifier rubyid_context'>context</span><span class='op'>|</span>
104
+ <span class='comment'># trigger background job
105
+ </span> <span class='kw'>end</span>
106
+ <span class='kw'>end</span>
107
+ </code></pre>
108
+ <h3 id="Generic_REST_Engine">Generic REST Engine</h3>
109
+ <p>The <code>Kabk::RestEngine</code> class orchestrates validation and delegates CRUD operations to the configured ORM adapter. It returns standardized raw hashes that your HTTP layer can easily convert to JSON.</p>
110
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_engine'>engine</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="Kabk.html" title="Kabk (module)">Kabk</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Kabk/RestEngine.html" title="Kabk::RestEngine (class)">RestEngine</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'><span class='object_link'><a href="Kabk/RestEngine.html#initialize-instance_method" title="Kabk::RestEngine#initialize (method)">new</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>news_item</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
111
+
112
+ <span class='comment'># Pagination, Filtering, Sorting, and Hydration are automatic
113
+ </span><span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='id identifier rubyid_engine'>engine</span><span class='period'>.</span><span class='id identifier rubyid_list'>list</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>page</span><span class='tstring_end'>&quot;</span></span> <span class='op'>=&gt;</span> <span class='int'>1</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>per_page</span><span class='tstring_end'>&quot;</span></span> <span class='op'>=&gt;</span> <span class='int'>15</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>sort</span><span class='tstring_end'>&quot;</span></span> <span class='op'>=&gt;</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>-created_at</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
114
+ <span class='comment'># =&gt; { success: true, data: [...], meta: { ... } }
115
+ </span>
116
+ <span class='comment'># Validation and OCC automatically applied
117
+ </span><span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='id identifier rubyid_engine'>engine</span><span class='period'>.</span><span class='id identifier rubyid_update'>update</span><span class='lparen'>(</span><span class='int'>1</span><span class='comma'>,</span> <span class='lbrace'>{</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>title</span><span class='tstring_end'>&quot;</span></span> <span class='op'>=&gt;</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>New Title</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>updated_at</span><span class='tstring_end'>&quot;</span></span> <span class='op'>=&gt;</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>2026-03-15T11:00:00Z</span><span class='tstring_end'>&quot;</span></span> <span class='rbrace'>}</span><span class='rparen'>)</span>
118
+ </code></pre>
119
+ <h3 id="System_Configuration__Protocol_v1_6_0_">System Configuration (Protocol v1.6.0)</h3>
120
+ <p>Kabk generates a JSON schema manifest containing dynamic system configuration and UI settings. You can override these defaults by passing a custom hash to the <code>SchemaRenderer</code>. Ensure you inject your authentication endpoints here, as Kabk itself does not provide them.</p>
121
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_renderer'>renderer</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="Kabk.html" title="Kabk (module)">Kabk</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Kabk/SchemaRenderer.html" title="Kabk::SchemaRenderer (class)">SchemaRenderer</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'><span class='object_link'><a href="Kabk/SchemaRenderer.html#initialize-instance_method" title="Kabk::SchemaRenderer#initialize (method)">new</a></span></span><span class='lparen'>(</span>
122
+ <span class='label'>system_config:</span> <span class='lbrace'>{</span>
123
+ <span class='label'>title:</span> <span class='lbrace'>{</span> <span class='label'>fa:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>پنل مدیریت</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='label'>en:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>My Custom Admin</span><span class='tstring_end'>&quot;</span></span> <span class='rbrace'>}</span><span class='comma'>,</span>
124
+ <span class='label'>logo_url:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/custom-logo.png</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
125
+ <span class='label'>endpoints:</span> <span class='lbrace'>{</span>
126
+ <span class='label'>login:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/auth/admin_login</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
127
+ <span class='label'>me:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/auth/admin_me</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
128
+ <span class='label'>logout:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/auth/admin_logout</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
129
+ <span class='label'>refresh:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/auth/admin_refresh</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
130
+ <span class='label'>upload:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>/api/files</span><span class='tstring_end'>&quot;</span></span>
131
+ <span class='rbrace'>}</span>
132
+ <span class='rbrace'>}</span>
133
+ <span class='rparen'>)</span>
134
+ <span class='id identifier rubyid_schema'>schema</span> <span class='op'>=</span> <span class='id identifier rubyid_renderer'>renderer</span><span class='period'>.</span><span class='id identifier rubyid_render'>render</span>
135
+ </code></pre>
136
+ <h2 id="Testing">Testing</h2>
137
+ <pre class="code bash"><code class="bash">bundle install
138
+ bundle exec rspec
139
+ </code></pre></div></div>
140
+
141
+ <div id="footer">
142
+ Generated on Tue Aug 11 21:17:05 2026 by
143
+ <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
144
+ 0.9.45 (ruby-4.0.6).
145
+ </div>
146
+
147
+ </div>
148
+ </body>
149
+ </html>