odac 0.9.0 → 1.0.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 (208) hide show
  1. package/.github/workflows/auto-pr-description.yml +0 -2
  2. package/.github/workflows/codeql.yml +46 -0
  3. package/.github/workflows/release.yml +13 -6
  4. package/.github/workflows/test-coverage.yml +10 -9
  5. package/.releaserc.js +9 -6
  6. package/CHANGELOG.md +62 -150
  7. package/CODE_OF_CONDUCT.md +1 -1
  8. package/CONTRIBUTING.md +8 -8
  9. package/LICENSE +21 -661
  10. package/README.md +12 -12
  11. package/SECURITY.md +4 -4
  12. package/bin/odac.js +101 -0
  13. package/{framework/web/candy.js → client/odac.js} +310 -44
  14. package/docs/backend/01-overview/{01-whats-in-the-candy-box.md → 01-whats-in-the-odac-box.md} +4 -2
  15. package/docs/backend/01-overview/02-super-handy-helper-functions.md +29 -1
  16. package/docs/backend/01-overview/03-development-server.md +11 -11
  17. package/docs/backend/02-structure/01-typical-project-layout.md +4 -4
  18. package/docs/backend/03-config/00-configuration-overview.md +6 -6
  19. package/docs/backend/03-config/01-database-connection.md +1 -1
  20. package/docs/backend/03-config/02-static-route-mapping-optional.md +4 -4
  21. package/docs/backend/03-config/04-environment-variables.md +20 -20
  22. package/docs/backend/03-config/05-early-hints.md +4 -4
  23. package/docs/backend/04-routing/01-basic-page-routes.md +4 -4
  24. package/docs/backend/04-routing/02-controller-less-view-routes.md +5 -5
  25. package/docs/backend/04-routing/03-api-and-data-routes.md +3 -3
  26. package/docs/backend/04-routing/04-authentication-aware-routes.md +5 -5
  27. package/docs/backend/04-routing/05-advanced-routing.md +3 -3
  28. package/docs/backend/04-routing/06-error-pages.md +17 -17
  29. package/docs/backend/04-routing/07-cron-jobs.md +13 -13
  30. package/docs/backend/04-routing/08-middleware.md +214 -0
  31. package/docs/backend/04-routing/09-websocket-auth-middleware.md +292 -0
  32. package/docs/backend/04-routing/09-websocket-examples.md +381 -0
  33. package/docs/backend/04-routing/09-websocket-quick-reference.md +211 -0
  34. package/docs/backend/04-routing/09-websocket.md +298 -0
  35. package/docs/backend/05-controllers/01-how-to-build-a-controller.md +3 -3
  36. package/docs/backend/05-controllers/02-your-trusty-odac-assistant.md +41 -0
  37. package/docs/backend/05-controllers/03-controller-classes.md +19 -19
  38. package/docs/backend/05-forms/01-custom-forms.md +114 -114
  39. package/docs/backend/05-forms/02-automatic-database-insert.md +82 -82
  40. package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +26 -26
  41. package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +10 -10
  42. package/docs/backend/07-views/01-the-view-directory.md +1 -1
  43. package/docs/backend/07-views/02-rendering-a-view.md +22 -22
  44. package/docs/backend/07-views/03-template-syntax.md +52 -52
  45. package/docs/backend/07-views/03-variables.md +84 -84
  46. package/docs/backend/07-views/04-request-data.md +57 -57
  47. package/docs/backend/07-views/05-conditionals.md +78 -78
  48. package/docs/backend/07-views/06-loops.md +114 -114
  49. package/docs/backend/07-views/07-translations.md +66 -66
  50. package/docs/backend/07-views/08-backend-javascript.md +103 -103
  51. package/docs/backend/07-views/09-comments.md +71 -71
  52. package/docs/backend/08-database/01-database-connection.md +8 -8
  53. package/docs/backend/08-database/02-using-mysql.md +49 -49
  54. package/docs/backend/09-validation/01-the-validator-service.md +38 -38
  55. package/docs/backend/10-authentication/01-user-logins-with-authjs.md +15 -15
  56. package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +10 -10
  57. package/docs/backend/10-authentication/03-register.md +12 -12
  58. package/docs/backend/10-authentication/{04-candy-register-forms.md → 04-odac-register-forms.md} +141 -141
  59. package/docs/backend/10-authentication/05-session-management.md +10 -10
  60. package/docs/backend/10-authentication/{06-candy-login-forms.md → 06-odac-login-forms.md} +125 -125
  61. package/docs/backend/11-mail/01-the-mail-service.md +5 -5
  62. package/docs/backend/12-streaming/01-streaming-overview.md +96 -54
  63. package/docs/backend/13-utilities/{01-candy-var.md → 01-odac-var.md} +109 -109
  64. package/docs/frontend/01-overview/01-introduction.md +30 -30
  65. package/docs/frontend/02-ajax-navigation/01-quick-start.md +45 -45
  66. package/docs/frontend/02-ajax-navigation/02-configuration.md +14 -14
  67. package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +36 -36
  68. package/docs/frontend/03-forms/01-form-handling.md +32 -32
  69. package/docs/frontend/04-api-requests/01-get-post.md +33 -33
  70. package/docs/frontend/05-streaming/01-client-streaming.md +15 -15
  71. package/docs/frontend/06-websocket/00-overview.md +76 -0
  72. package/docs/frontend/06-websocket/01-websocket-client.md +139 -0
  73. package/docs/frontend/06-websocket/02-shared-websocket.md +149 -0
  74. package/docs/index.json +49 -11
  75. package/eslint.config.mjs +6 -6
  76. package/{framework/index.js → index.js} +1 -1
  77. package/package.json +14 -39
  78. package/{framework/src → src}/Auth.js +59 -59
  79. package/{framework/src → src}/Config.js +3 -3
  80. package/{framework/src → src}/Lang.js +7 -7
  81. package/{framework/src → src}/Mail.js +5 -5
  82. package/{framework/src → src}/Mysql.js +42 -42
  83. package/src/Odac.js +112 -0
  84. package/{framework/src → src}/Request.js +38 -36
  85. package/{framework/src → src}/Route/Internal.js +116 -116
  86. package/src/Route/Middleware.js +75 -0
  87. package/src/Route.js +621 -0
  88. package/src/Server.js +22 -0
  89. package/{framework/src → src}/Stream.js +11 -3
  90. package/{framework/src → src}/Validator.js +21 -21
  91. package/{framework/src → src}/Var.js +5 -5
  92. package/{framework/src → src}/View/EarlyHints.js +1 -1
  93. package/{framework/src → src}/View/Form.js +69 -69
  94. package/{framework/src → src}/View.js +78 -81
  95. package/src/WebSocket.js +403 -0
  96. package/template/config.json +5 -0
  97. package/{web → template}/controller/page/about.js +6 -6
  98. package/{web → template}/controller/page/index.js +9 -9
  99. package/{web → template}/package.json +4 -5
  100. package/{web → template}/public/assets/css/style.css +4 -4
  101. package/{web → template}/public/assets/js/app.js +6 -6
  102. package/{web → template}/route/www.js +6 -6
  103. package/{web → template}/skeleton/main.html +1 -1
  104. package/{web → template}/view/content/about.html +5 -5
  105. package/{web → template}/view/content/home.html +12 -12
  106. package/template/view/footer/main.html +11 -0
  107. package/{web → template}/view/head/main.html +1 -1
  108. package/{web → template}/view/header/main.html +2 -2
  109. package/test/core/Candy.test.js +58 -58
  110. package/test/core/Commands.test.js +7 -7
  111. package/test/core/Config.test.js +82 -85
  112. package/test/core/Lang.test.js +2 -2
  113. package/test/core/Process.test.js +6 -6
  114. package/test/framework/Route.test.js +56 -37
  115. package/test/framework/View/EarlyHints.test.js +2 -2
  116. package/test/framework/WebSocket.test.js +100 -0
  117. package/test/framework/middleware.test.js +85 -0
  118. package/test/server/Api.test.js +31 -31
  119. package/test/server/DNS.test.js +11 -11
  120. package/test/server/Hub.test.js +497 -0
  121. package/test/server/Mail.account.test_.js +3 -3
  122. package/test/server/Mail.init.test_.js +10 -10
  123. package/test/server/Mail.test_.js +20 -20
  124. package/test/server/SSL.test_.js +54 -54
  125. package/test/server/Server.test.js +39 -39
  126. package/test/server/Service.test_.js +7 -7
  127. package/test/server/Subdomain.test.js +7 -7
  128. package/test/server/Web/Firewall.test.js +87 -87
  129. package/test/server/Web/Proxy.test.js +397 -0
  130. package/test/server/{Web.test_.js → Web.test.js} +137 -205
  131. package/test/server/__mocks__/fs.js +2 -2
  132. package/test/server/__mocks__/{globalCandy.js → globalOdac.js} +5 -5
  133. package/test/server/__mocks__/index.js +6 -6
  134. package/test/server/__mocks__/testFactories.js +1 -1
  135. package/test/server/__mocks__/testHelpers.js +7 -7
  136. package/.husky/pre-commit +0 -2
  137. package/.kiro/steering/code-style.md +0 -56
  138. package/.kiro/steering/product.md +0 -20
  139. package/.kiro/steering/structure.md +0 -77
  140. package/.kiro/steering/tech.md +0 -87
  141. package/AGENTS.md +0 -84
  142. package/bin/candy +0 -10
  143. package/bin/candypack +0 -10
  144. package/cli/index.js +0 -3
  145. package/cli/src/Cli.js +0 -348
  146. package/cli/src/Connector.js +0 -93
  147. package/cli/src/Monitor.js +0 -416
  148. package/core/Candy.js +0 -87
  149. package/core/Commands.js +0 -239
  150. package/core/Config.js +0 -1094
  151. package/core/Lang.js +0 -52
  152. package/core/Log.js +0 -43
  153. package/core/Process.js +0 -26
  154. package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +0 -20
  155. package/docs/server/01-installation/01-quick-install.md +0 -19
  156. package/docs/server/01-installation/02-manual-installation-via-npm.md +0 -9
  157. package/docs/server/02-get-started/01-core-concepts.md +0 -7
  158. package/docs/server/02-get-started/02-basic-commands.md +0 -57
  159. package/docs/server/02-get-started/03-cli-reference.md +0 -276
  160. package/docs/server/02-get-started/04-cli-quick-reference.md +0 -102
  161. package/docs/server/03-service/01-start-a-new-service.md +0 -57
  162. package/docs/server/03-service/02-delete-a-service.md +0 -48
  163. package/docs/server/04-web/01-create-a-website.md +0 -36
  164. package/docs/server/04-web/02-list-websites.md +0 -9
  165. package/docs/server/04-web/03-delete-a-website.md +0 -29
  166. package/docs/server/05-subdomain/01-create-a-subdomain.md +0 -32
  167. package/docs/server/05-subdomain/02-list-subdomains.md +0 -33
  168. package/docs/server/05-subdomain/03-delete-a-subdomain.md +0 -41
  169. package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +0 -34
  170. package/docs/server/07-mail/01-create-a-mail-account.md +0 -23
  171. package/docs/server/07-mail/02-delete-a-mail-account.md +0 -20
  172. package/docs/server/07-mail/03-list-mail-accounts.md +0 -20
  173. package/docs/server/07-mail/04-change-account-password.md +0 -23
  174. package/framework/src/Candy.js +0 -81
  175. package/framework/src/Route.js +0 -455
  176. package/framework/src/Server.js +0 -15
  177. package/locale/de-DE.json +0 -80
  178. package/locale/en-US.json +0 -79
  179. package/locale/es-ES.json +0 -80
  180. package/locale/fr-FR.json +0 -80
  181. package/locale/pt-BR.json +0 -80
  182. package/locale/ru-RU.json +0 -80
  183. package/locale/tr-TR.json +0 -85
  184. package/locale/zh-CN.json +0 -80
  185. package/server/index.js +0 -5
  186. package/server/src/Api.js +0 -88
  187. package/server/src/DNS.js +0 -940
  188. package/server/src/Hub.js +0 -535
  189. package/server/src/Mail.js +0 -571
  190. package/server/src/SSL.js +0 -180
  191. package/server/src/Server.js +0 -27
  192. package/server/src/Service.js +0 -248
  193. package/server/src/Subdomain.js +0 -64
  194. package/server/src/Web/Firewall.js +0 -170
  195. package/server/src/Web/Proxy.js +0 -134
  196. package/server/src/Web.js +0 -451
  197. package/server/src/mail/imap.js +0 -1091
  198. package/server/src/mail/server.js +0 -32
  199. package/server/src/mail/smtp.js +0 -786
  200. package/test/server/Client.test.js +0 -338
  201. package/test/server/__mocks__/http-proxy.js +0 -105
  202. package/watchdog/index.js +0 -3
  203. package/watchdog/src/Watchdog.js +0 -156
  204. package/web/config.json +0 -5
  205. package/web/view/footer/main.html +0 -11
  206. /package/{framework/src → src}/Env.js +0 -0
  207. /package/{framework/src → src}/Route/Cron.js +0 -0
  208. /package/{framework/src → src}/Token.js +0 -0
@@ -1,6 +1,6 @@
1
1
  ## 💬 Comments in Views
2
2
 
3
- CandyPack supports two types of comments in view files: backend comments (not rendered) and regular HTML comments (rendered).
3
+ Odac supports two types of comments in view files: backend comments (not rendered) and regular HTML comments (rendered).
4
4
 
5
5
  ### Backend Comments (Not Rendered)
6
6
 
@@ -9,18 +9,18 @@ Backend comments are removed during template rendering and never appear in the H
9
9
  #### Single-Line Backend Comments
10
10
 
11
11
  ```html
12
- <!--candy This is a backend comment -->
12
+ <!--odac This is a backend comment -->
13
13
  <p>This will be rendered</p>
14
14
  ```
15
15
 
16
16
  #### Multi-Line Backend Comments
17
17
 
18
18
  ```html
19
- <!--candy
19
+ <!--odac
20
20
  This is a multi-line backend comment
21
21
  It can span multiple lines
22
22
  None of this will appear in the output
23
- candy-->
23
+ odac-->
24
24
 
25
25
  <div class="content">
26
26
  <p>This will be rendered</p>
@@ -43,50 +43,50 @@ Standard HTML comments are preserved and sent to the browser:
43
43
 
44
44
  **Development Notes:**
45
45
  ```html
46
- <!--candy TODO: Add pagination here -->
47
- <!--candy FIXME: This needs optimization -->
48
- <!--candy NOTE: This section is for admin users only -->
46
+ <!--odac TODO: Add pagination here -->
47
+ <!--odac FIXME: This needs optimization -->
48
+ <!--odac NOTE: This section is for admin users only -->
49
49
  ```
50
50
 
51
51
  **Sensitive Information:**
52
52
  ```html
53
- <!--candy
53
+ <!--odac
54
54
  Database query returns: id, name, email, password_hash
55
55
  We only display: name, email
56
- candy-->
56
+ odac-->
57
57
 
58
- <candy:for in="users" value="user">
59
- <p><candy var="user.name" /> - <candy var="user.email" /></p>
60
- </candy:for>
58
+ <odac:for in="users" value="user">
59
+ <p><odac var="user.name" /> - <odac var="user.email" /></p>
60
+ </odac:for>
61
61
  ```
62
62
 
63
63
  **Debugging Information:**
64
64
  ```html
65
- <!--candy Debug: user object structure -->
66
- <!--candy { id: 1, name: "John", role: "admin" } -->
65
+ <!--odac Debug: user object structure -->
66
+ <!--odac { id: 1, name: "John", role: "admin" } -->
67
67
 
68
- <candy:if condition="user.role === 'admin'">
68
+ <odac:if condition="user.role === 'admin'">
69
69
  <div class="admin-panel">Admin content</div>
70
- </candy:if>
70
+ </odac:if>
71
71
  ```
72
72
 
73
73
  **Temporary Code:**
74
74
  ```html
75
- <!--candy
75
+ <!--odac
76
76
  Old implementation - keeping for reference
77
77
  <div class="old-layout">
78
- <candy:for in="items" value="item">
79
- <p><candy var="item.name" /></p>
80
- </candy:for>
78
+ <odac:for in="items" value="item">
79
+ <p><odac var="item.name" /></p>
80
+ </odac:for>
81
81
  </div>
82
- candy-->
82
+ odac-->
83
83
 
84
84
  <div class="new-layout">
85
- <candy:for in="items" value="item">
85
+ <odac:for in="items" value="item">
86
86
  <div class="item-card">
87
- <h3><candy var="item.name" /></h3>
87
+ <h3><odac var="item.name" /></h3>
88
88
  </div>
89
- </candy:for>
89
+ </odac:for>
90
90
  </div>
91
91
  ```
92
92
 
@@ -135,18 +135,18 @@ candy-->
135
135
  #### Documenting Complex Logic
136
136
 
137
137
  ```html
138
- <!--candy
138
+ <!--odac
139
139
  This section displays products based on user role:
140
140
  - Admin: sees all products including inactive
141
141
  - Regular user: sees only active products
142
142
  - Guest: sees only featured products
143
- candy-->
143
+ odac-->
144
144
 
145
- <script:candy>
145
+ <script:odac>
146
146
  let visibleProducts;
147
147
 
148
- if (Candy.Auth.check()) {
149
- const user = Candy.Auth.user();
148
+ if (Odac.Auth.check()) {
149
+ const user = Odac.Auth.user();
150
150
  if (user.role === 'admin') {
151
151
  visibleProducts = products;
152
152
  } else {
@@ -155,52 +155,52 @@ candy-->
155
155
  } else {
156
156
  visibleProducts = products.filter(p => p.featured);
157
157
  }
158
- </script:candy>
158
+ </script:odac>
159
159
 
160
- <candy:for in="visibleProducts" value="product">
160
+ <odac:for in="visibleProducts" value="product">
161
161
  <div class="product">
162
- <h3><candy var="product.name" /></h3>
162
+ <h3><odac var="product.name" /></h3>
163
163
  </div>
164
- </candy:for>
164
+ </odac:for>
165
165
  ```
166
166
 
167
167
  #### Marking Sections for Developers
168
168
 
169
169
  ```html
170
170
  <div class="dashboard">
171
- <!--candy START: User Statistics Section -->
171
+ <!--odac START: User Statistics Section -->
172
172
  <div class="stats">
173
173
  <h2>Statistics</h2>
174
- <p>Total Users: <candy var="stats.totalUsers" /></p>
175
- <p>Active Users: <candy var="stats.activeUsers" /></p>
174
+ <p>Total Users: <odac var="stats.totalUsers" /></p>
175
+ <p>Active Users: <odac var="stats.activeUsers" /></p>
176
176
  </div>
177
- <!--candy END: User Statistics Section -->
177
+ <!--odac END: User Statistics Section -->
178
178
 
179
- <!--candy START: Recent Activity Section -->
179
+ <!--odac START: Recent Activity Section -->
180
180
  <div class="activity">
181
181
  <h2>Recent Activity</h2>
182
- <candy:for in="activities" value="activity">
183
- <p><candy var="activity.description" /></p>
184
- </candy:for>
182
+ <odac:for in="activities" value="activity">
183
+ <p><odac var="activity.description" /></p>
184
+ </odac:for>
185
185
  </div>
186
- <!--candy END: Recent Activity Section -->
186
+ <!--odac END: Recent Activity Section -->
187
187
  </div>
188
188
  ```
189
189
 
190
190
  #### Explaining Template Variables
191
191
 
192
192
  ```html
193
- <!--candy
193
+ <!--odac
194
194
  Available variables from controller:
195
195
  - user: Current user object { id, name, email, role }
196
196
  - posts: Array of post objects
197
197
  - categories: Array of category objects
198
198
  - settings: Site settings object
199
- candy-->
199
+ odac-->
200
200
 
201
201
  <div class="profile">
202
- <h1><candy var="user.name" /></h1>
203
- <p><candy var="user.email" /></p>
202
+ <h1><odac var="user.name" /></h1>
203
+ <p><odac var="user.email" /></p>
204
204
  </div>
205
205
  ```
206
206
 
@@ -208,31 +208,31 @@ candy-->
208
208
 
209
209
  ```html
210
210
  <div class="products">
211
- <candy:for in="products" value="product">
211
+ <odac:for in="products" value="product">
212
212
  <div class="product-card">
213
- <h3><candy var="product.name" /></h3>
214
- <p>$<candy var="product.price" /></p>
213
+ <h3><odac var="product.name" /></h3>
214
+ <p>$<odac var="product.price" /></p>
215
215
 
216
- <!--candy Temporarily disabled - waiting for API
216
+ <!--odac Temporarily disabled - waiting for API
217
217
  <div class="reviews">
218
- <candy var="product.averageRating" /> stars
218
+ <odac var="product.averageRating" /> stars
219
219
  </div>
220
- candy-->
220
+ odac-->
221
221
  </div>
222
- </candy:for>
222
+ </odac:for>
223
223
  </div>
224
224
  ```
225
225
 
226
226
  #### Version History
227
227
 
228
228
  ```html
229
- <!--candy
229
+ <!--odac
230
230
  Version History:
231
231
  v1.0 - Initial implementation
232
232
  v1.1 - Added sorting functionality
233
233
  v1.2 - Added filtering by category
234
234
  v2.0 - Complete redesign with new layout
235
- candy-->
235
+ odac-->
236
236
 
237
237
  <div class="product-list">
238
238
  <!-- Product list implementation -->
@@ -249,19 +249,19 @@ candy-->
249
249
 
250
250
  **Good:**
251
251
  ```html
252
- <!--candy This query is cached for 5 minutes -->
253
- <candy:for in="products" value="product">
254
- <div><candy var="product.name" /></div>
255
- </candy:for>
252
+ <!--odac This query is cached for 5 minutes -->
253
+ <odac:for in="products" value="product">
254
+ <div><odac var="product.name" /></div>
255
+ </odac:for>
256
256
  ```
257
257
 
258
258
  **Avoid:**
259
259
  ```html
260
- <!--candy Loop through products -->
261
- <candy:for in="products" value="product">
262
- <!--candy Display product name -->
263
- <div><candy var="product.name" /></div>
264
- </candy:for>
260
+ <!--odac Loop through products -->
261
+ <odac:for in="products" value="product">
262
+ <!--odac Display product name -->
263
+ <div><odac var="product.name" /></div>
264
+ </odac:for>
265
265
  ```
266
266
 
267
267
  ### Security Considerations
@@ -273,9 +273,9 @@ candy-->
273
273
  <!-- Database password: secret123 -->
274
274
  <!-- API key: abc123xyz -->
275
275
 
276
- <!--candy GOOD: Not visible in output -->
277
- <!--candy Database password: secret123 -->
278
- <!--candy API key: abc123xyz -->
276
+ <!--odac GOOD: Not visible in output -->
277
+ <!--odac Database password: secret123 -->
278
+ <!--odac API key: abc123xyz -->
279
279
  ```
280
280
 
281
281
  **Be careful with user data:**
@@ -284,14 +284,14 @@ candy-->
284
284
  <!-- BAD: Exposes user data -->
285
285
  <!-- User ID: 12345, Email: user@example.com -->
286
286
 
287
- <!--candy GOOD: Hidden from output -->
288
- <!--candy User ID: 12345, Email: user@example.com -->
287
+ <!--odac GOOD: Hidden from output -->
288
+ <!--odac User ID: 12345, Email: user@example.com -->
289
289
  ```
290
290
 
291
291
  ### Comment Syntax Summary
292
292
 
293
293
  | Type | Syntax | Rendered | Use Case |
294
294
  |------|--------|----------|----------|
295
- | Backend Single-Line | `<!--candy comment -->` | No | Development notes, TODOs |
296
- | Backend Multi-Line | `<!--candy ... candy-->` | No | Detailed explanations, disabled code |
295
+ | Backend Single-Line | `<!--odac comment -->` | No | Development notes, TODOs |
296
+ | Backend Multi-Line | `<!--odac ... odac-->` | No | Detailed explanations, disabled code |
297
297
  | HTML Comment | `<!-- comment -->` | Yes | Section markers, browser hacks |
@@ -1,6 +1,6 @@
1
1
  ## 🔌 Database Connection
2
2
 
3
- CandyPack automatically connects to your MySQL database when you provide the configuration.
3
+ Odac automatically connects to your MySQL database when you provide the configuration.
4
4
 
5
5
  ### Configuration
6
6
 
@@ -44,10 +44,10 @@ Access different databases:
44
44
 
45
45
  ```javascript
46
46
  // Default database
47
- const users = await Candy.Mysql.table('users').get()
47
+ const users = await Odac.Mysql.table('users').get()
48
48
 
49
49
  // Specific database
50
- const stats = await Candy.Mysql.database('analytics').table('stats').get()
50
+ const stats = await Odac.Mysql.database('analytics').table('stats').get()
51
51
  ```
52
52
 
53
53
  ### Environment Variables
@@ -86,14 +86,14 @@ Available configuration options:
86
86
 
87
87
  ### Automatic Connection
88
88
 
89
- The connection is established automatically when your application starts. You don't need to write any connection code - just use `Candy.Mysql` in your controllers.
89
+ The connection is established automatically when your application starts. You don't need to write any connection code - just use `Odac.Mysql` in your controllers.
90
90
 
91
91
  ```javascript
92
- module.exports = async function (Candy) {
92
+ module.exports = async function (Odac) {
93
93
  // Connection is already established
94
- const users = await Candy.Mysql.table('users').get()
94
+ const users = await Odac.Mysql.table('users').get()
95
95
 
96
- Candy.set('users', users)
97
- Candy.View.set({ skeleton: 'main', content: 'users' })
96
+ Odac.set('users', users)
97
+ Odac.View.set({ skeleton: 'main', content: 'users' })
98
98
  }
99
99
  ```
@@ -1,25 +1,25 @@
1
1
  ## 🗄️ Using MySQL
2
2
 
3
- CandyPack provides a powerful query builder for safe and easy database operations.
3
+ Odac provides a powerful query builder for safe and easy database operations.
4
4
 
5
5
  ### Selecting Data
6
6
 
7
7
  #### Get All Records
8
8
 
9
9
  ```javascript
10
- const users = await Candy.Mysql.table('users').get()
10
+ const users = await Odac.Mysql.table('users').get()
11
11
  ```
12
12
 
13
13
  #### Get First Record
14
14
 
15
15
  ```javascript
16
- const user = await Candy.Mysql.table('users').where('id', 1).first()
16
+ const user = await Odac.Mysql.table('users').where('id', 1).first()
17
17
  ```
18
18
 
19
19
  #### Select Specific Columns
20
20
 
21
21
  ```javascript
22
- const users = await Candy.Mysql.table('users')
22
+ const users = await Odac.Mysql.table('users')
23
23
  .select('id', 'name', 'email')
24
24
  .get()
25
25
  ```
@@ -28,35 +28,35 @@ const users = await Candy.Mysql.table('users')
28
28
 
29
29
  ```javascript
30
30
  // Single condition
31
- const users = await Candy.Mysql.table('users')
31
+ const users = await Odac.Mysql.table('users')
32
32
  .where('status', 'active')
33
33
  .get()
34
34
 
35
35
  // Multiple conditions (AND)
36
- const users = await Candy.Mysql.table('users')
36
+ const users = await Odac.Mysql.table('users')
37
37
  .where('status', 'active')
38
38
  .where('verified', 1)
39
39
  .get()
40
40
 
41
41
  // OR condition
42
- const users = await Candy.Mysql.table('users')
42
+ const users = await Odac.Mysql.table('users')
43
43
  .where('role', 'admin')
44
44
  .orWhere('role', 'moderator')
45
45
  .get()
46
46
 
47
47
  // Comparison operators
48
- const products = await Candy.Mysql.table('products')
48
+ const products = await Odac.Mysql.table('products')
49
49
  .where('price', '>', 100)
50
50
  .where('stock', '<=', 10)
51
51
  .get()
52
52
 
53
53
  // LIKE
54
- const users = await Candy.Mysql.table('users')
54
+ const users = await Odac.Mysql.table('users')
55
55
  .where('name', 'LIKE', '%John%')
56
56
  .get()
57
57
 
58
58
  // IN
59
- const users = await Candy.Mysql.table('users')
59
+ const users = await Odac.Mysql.table('users')
60
60
  .where('role', 'IN', ['admin', 'moderator'])
61
61
  .get()
62
62
  ```
@@ -67,7 +67,7 @@ For complex queries with nested AND/OR conditions, use arrays:
67
67
 
68
68
  ```javascript
69
69
  // SQL: WHERE (status = 'active' AND verified = 1) OR (role = 'admin')
70
- const users = await Candy.Mysql.table('users')
70
+ const users = await Odac.Mysql.table('users')
71
71
  .where([
72
72
  ['status', 'active'],
73
73
  ['verified', 1]
@@ -76,7 +76,7 @@ const users = await Candy.Mysql.table('users')
76
76
  .get()
77
77
 
78
78
  // SQL: WHERE status = 'active' AND (role = 'admin' OR role = 'moderator')
79
- const users = await Candy.Mysql.table('users')
79
+ const users = await Odac.Mysql.table('users')
80
80
  .where('status', 'active')
81
81
  .where([
82
82
  ['role', 'admin'],
@@ -88,7 +88,7 @@ const users = await Candy.Mysql.table('users')
88
88
  // Complex nested conditions
89
89
  // SQL: WHERE (status = 'active' AND (role = 'admin' OR role = 'moderator'))
90
90
  // AND (verified = 1 OR email_verified = 1)
91
- const users = await Candy.Mysql.table('users')
91
+ const users = await Odac.Mysql.table('users')
92
92
  .where([
93
93
  ['status', 'active'],
94
94
  [
@@ -109,19 +109,19 @@ const users = await Candy.Mysql.table('users')
109
109
 
110
110
  ```javascript
111
111
  // Order by
112
- const users = await Candy.Mysql.table('users')
112
+ const users = await Odac.Mysql.table('users')
113
113
  .order('created_at', 'desc')
114
114
  .get()
115
115
 
116
116
  // Limit
117
- const users = await Candy.Mysql.table('users')
117
+ const users = await Odac.Mysql.table('users')
118
118
  .limit(10)
119
119
  .get()
120
120
 
121
121
  // Pagination
122
122
  const page = 2
123
123
  const perPage = 20
124
- const users = await Candy.Mysql.table('users')
124
+ const users = await Odac.Mysql.table('users')
125
125
  .limit((page - 1) * perPage, perPage)
126
126
  .get()
127
127
  ```
@@ -129,7 +129,7 @@ const users = await Candy.Mysql.table('users')
129
129
  ### Counting Records
130
130
 
131
131
  ```javascript
132
- const userCount = await Candy.Mysql.table('users')
132
+ const userCount = await Odac.Mysql.table('users')
133
133
  .where('status', 'active')
134
134
  .rows()
135
135
  ```
@@ -137,7 +137,7 @@ const userCount = await Candy.Mysql.table('users')
137
137
  ### Joins
138
138
 
139
139
  ```javascript
140
- const orders = await Candy.Mysql.table('orders')
140
+ const orders = await Odac.Mysql.table('orders')
141
141
  .leftJoin('users', 'orders.user_id', 'users.id')
142
142
  .select('orders.*', 'users.name', 'users.email')
143
143
  .get()
@@ -147,7 +147,7 @@ const orders = await Candy.Mysql.table('orders')
147
147
 
148
148
  ```javascript
149
149
  // Insert single record
150
- const result = await Candy.Mysql.table('users').insert({
150
+ const result = await Odac.Mysql.table('users').insert({
151
151
  name: 'John Doe',
152
152
  email: 'john@example.com',
153
153
  status: 'active'
@@ -160,7 +160,7 @@ console.log(result.affected) // Affected rows
160
160
  ### Updating Data
161
161
 
162
162
  ```javascript
163
- const result = await Candy.Mysql.table('users')
163
+ const result = await Odac.Mysql.table('users')
164
164
  .where('id', 1)
165
165
  .set({
166
166
  name: 'Jane Doe',
@@ -173,7 +173,7 @@ console.log(result.affected) // Number of updated rows
173
173
  ### Deleting Data
174
174
 
175
175
  ```javascript
176
- const result = await Candy.Mysql.table('users')
176
+ const result = await Odac.Mysql.table('users')
177
177
  .where('id', 1)
178
178
  .delete()
179
179
 
@@ -186,12 +186,12 @@ For complex queries, use raw SQL:
186
186
 
187
187
  ```javascript
188
188
  // Raw value in select
189
- const users = await Candy.Mysql.table('users')
190
- .select('id', 'name', Candy.Mysql.raw('COUNT(*) as total'))
189
+ const users = await Odac.Mysql.table('users')
190
+ .select('id', 'name', Odac.Mysql.raw('COUNT(*) as total'))
191
191
  .get()
192
192
 
193
193
  // Raw query with parameters (SAFE - recommended)
194
- const result = await Candy.Mysql.run('SELECT * FROM users WHERE status = ?', ['active'])
194
+ const result = await Odac.Mysql.run('SELECT * FROM users WHERE status = ?', ['active'])
195
195
  ```
196
196
 
197
197
  #### ⚠️ Security Warning: Mysql.raw()
@@ -200,25 +200,25 @@ const result = await Candy.Mysql.run('SELECT * FROM users WHERE status = ?', ['a
200
200
 
201
201
  ```javascript
202
202
  // ❌ DANGEROUS - Never do this!
203
- const userInput = await Candy.request('search')
204
- const users = await Candy.Mysql.table('users')
205
- .where('name', Candy.Mysql.raw(userInput)) // SQL INJECTION RISK!
203
+ const userInput = await Odac.request('search')
204
+ const users = await Odac.Mysql.table('users')
205
+ .where('name', Odac.Mysql.raw(userInput)) // SQL INJECTION RISK!
206
206
  .get()
207
207
 
208
208
  // ✅ SAFE - Use query builder instead
209
- const userInput = await Candy.request('search')
210
- const users = await Candy.Mysql.table('users')
209
+ const userInput = await Odac.request('search')
210
+ const users = await Odac.Mysql.table('users')
211
211
  .where('name', 'LIKE', `%${userInput}%`) // Automatically escaped
212
212
  .get()
213
213
 
214
214
  // ✅ SAFE - Use with hardcoded values only
215
- const users = await Candy.Mysql.table('users')
216
- .select('id', 'name', Candy.Mysql.raw('COUNT(*) as total')) // OK - hardcoded
215
+ const users = await Odac.Mysql.table('users')
216
+ .select('id', 'name', Odac.Mysql.raw('COUNT(*) as total')) // OK - hardcoded
217
217
  .get()
218
218
 
219
219
  // ✅ SAFE - Use parameterized queries for dynamic values
220
- const status = await Candy.request('status')
221
- const result = await Candy.Mysql.run(
220
+ const status = await Odac.request('status')
221
+ const result = await Odac.Mysql.run(
222
222
  'SELECT * FROM users WHERE status = ?',
223
223
  [status] // Automatically escaped
224
224
  )
@@ -237,8 +237,8 @@ const result = await Candy.Mysql.run(
237
237
  ### Group By
238
238
 
239
239
  ```javascript
240
- const stats = await Candy.Mysql.table('orders')
241
- .select('user_id', Candy.Mysql.raw('COUNT(*) as order_count'))
240
+ const stats = await Odac.Mysql.table('orders')
241
+ .select('user_id', Odac.Mysql.raw('COUNT(*) as order_count'))
242
242
  .groupBy('user_id')
243
243
  .get()
244
244
  ```
@@ -246,13 +246,13 @@ const stats = await Candy.Mysql.table('orders')
246
246
  ### Complete Example
247
247
 
248
248
  ```javascript
249
- module.exports = async function (Candy) {
250
- const page = await Candy.request('page') || 1
249
+ module.exports = async function (Odac) {
250
+ const page = await Odac.request('page') || 1
251
251
  const perPage = 20
252
- const search = await Candy.request('search')
252
+ const search = await Odac.request('search')
253
253
 
254
254
  // Build query
255
- let query = Candy.Mysql.table('products')
255
+ let query = Odac.Mysql.table('products')
256
256
  .select('id', 'name', 'price', 'stock')
257
257
  .where('status', 'active')
258
258
 
@@ -268,17 +268,17 @@ module.exports = async function (Candy) {
268
268
  .get()
269
269
 
270
270
  // Get total count
271
- const totalCount = await Candy.Mysql.table('products')
271
+ const totalCount = await Odac.Mysql.table('products')
272
272
  .where('status', 'active')
273
273
  .rows()
274
274
 
275
- Candy.set({
275
+ Odac.set({
276
276
  products: products,
277
277
  currentPage: page,
278
278
  totalPages: Math.ceil(totalCount / perPage)
279
279
  })
280
280
 
281
- Candy.View.set({
281
+ Odac.View.set({
282
282
  skeleton: 'main',
283
283
  content: 'products.list'
284
284
  })
@@ -298,23 +298,23 @@ module.exports = async function (Candy) {
298
298
  ### Error Handling
299
299
 
300
300
  ```javascript
301
- module.exports = async function (Candy) {
301
+ module.exports = async function (Odac) {
302
302
  try {
303
- const user = await Candy.Mysql.table('users')
304
- .where('id', await Candy.request('id'))
303
+ const user = await Odac.Mysql.table('users')
304
+ .where('id', await Odac.request('id'))
305
305
  .first()
306
306
 
307
307
  if (!user) {
308
- Candy.set('error', 'User not found')
308
+ Odac.set('error', 'User not found')
309
309
  } else {
310
- Candy.set('user', user)
310
+ Odac.set('user', user)
311
311
  }
312
312
  } catch (error) {
313
313
  console.error('Database error:', error)
314
- Candy.set('error', 'An error occurred')
314
+ Odac.set('error', 'An error occurred')
315
315
  }
316
316
 
317
- Candy.View.set({
317
+ Odac.View.set({
318
318
  skeleton: 'main',
319
319
  content: 'user.profile'
320
320
  })