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,8 +1,8 @@
1
1
  ## 🔧 Template Syntax Overview
2
2
 
3
- CandyPack uses a powerful template engine to create dynamic content in view files. The engine provides a clean, HTML-like syntax for displaying variables, conditionals, loops, translations, and more.
3
+ Odac uses a powerful template engine to create dynamic content in view files. The engine provides a clean, HTML-like syntax for displaying variables, conditionals, loops, translations, and more.
4
4
 
5
- > **Note:** CandyPack also supports legacy syntax (`{{ }}`, `{!! !!}`, `{{-- --}}`) for backward compatibility, but the new `<candy>` tag syntax is recommended for all new projects.
5
+ > **Note:** Odac also supports legacy syntax (`{{ }}`, `{!! !!}`, `{{-- --}}`) for backward compatibility, but the new `<odac>` tag syntax is recommended for all new projects.
6
6
 
7
7
  ### Quick Reference
8
8
 
@@ -10,17 +10,17 @@ This page provides a quick overview of all available template features. For deta
10
10
 
11
11
  ### Variables (Controller Data)
12
12
 
13
- Display data passed from controllers using `Candy.set()`:
13
+ Display data passed from controllers using `Odac.set()`:
14
14
 
15
15
  ```html
16
16
  <!-- HTML-safe output -->
17
- <candy var="username" />
17
+ <odac var="username" />
18
18
 
19
19
  <!-- Raw HTML output -->
20
- <candy var="htmlContent" raw />
20
+ <odac var="htmlContent" raw />
21
21
 
22
22
  <!-- String literals -->
23
- <candy>Hello World</candy>
23
+ <odac>Hello World</odac>
24
24
  ```
25
25
 
26
26
  **[→ Learn more about Variables](./03-variables.md)**
@@ -32,11 +32,11 @@ Access URL query parameters directly:
32
32
  ```html
33
33
  <!-- Get query parameter from URL -->
34
34
  <!-- URL: /search?q=laptop -->
35
- <candy get="q" />
35
+ <odac get="q" />
36
36
  <!-- Output: laptop -->
37
37
  ```
38
38
 
39
- **Note:** `<candy get>` is for URL parameters. For controller data, use `<candy var>`.
39
+ **Note:** `<odac get>` is for URL parameters. For controller data, use `<odac var>`.
40
40
 
41
41
  **[→ Learn more about Request Data](./04-request-data.md)**
42
42
 
@@ -46,13 +46,13 @@ Create multi-language applications:
46
46
 
47
47
  ```html
48
48
  <!-- Basic translation -->
49
- <candy translate>Welcome</candy>
49
+ <odac translate>Welcome</odac>
50
50
 
51
51
  <!-- With placeholders -->
52
- <candy translate>Hello <candy var="user.name" /></candy>
52
+ <odac translate>Hello <odac var="user.name" /></odac>
53
53
 
54
54
  <!-- With HTML preserved -->
55
- <candy translate raw>Click <a href="/help">here</a></candy>
55
+ <odac translate raw>Click <a href="/help">here</a></odac>
56
56
  ```
57
57
 
58
58
  **[→ Learn more about Translations](./07-translations.md)**
@@ -62,12 +62,12 @@ Create multi-language applications:
62
62
  Two types of comments for different purposes:
63
63
 
64
64
  ```html
65
- <!--candy Backend comment (not rendered) -->
65
+ <!--odac Backend comment (not rendered) -->
66
66
 
67
- <!--candy
67
+ <!--odac
68
68
  Multi-line backend comment
69
69
  Won't appear in output
70
- candy-->
70
+ odac-->
71
71
 
72
72
  <!-- Regular HTML comment (rendered) -->
73
73
  ```
@@ -79,13 +79,13 @@ candy-->
79
79
  Show or hide content based on conditions:
80
80
 
81
81
  ```html
82
- <candy:if condition="user.isAdmin">
82
+ <odac:if condition="user.isAdmin">
83
83
  <p>Admin panel</p>
84
- <candy:elseif condition="user.isModerator">
84
+ <odac:elseif condition="user.isModerator">
85
85
  <p>Moderator panel</p>
86
- <candy:else>
86
+ <odac:else>
87
87
  <p>User panel</p>
88
- </candy:if>
88
+ </odac:if>
89
89
  ```
90
90
 
91
91
  **[→ Learn more about Conditionals](./05-conditionals.md)**
@@ -96,18 +96,18 @@ Iterate over arrays and objects:
96
96
 
97
97
  ```html
98
98
  <!-- For loop -->
99
- <candy:for in="users" key="index" value="user">
100
- <div><candy var="user.name" /></div>
101
- </candy:for>
99
+ <odac:for in="users" key="index" value="user">
100
+ <div><odac var="user.name" /></div>
101
+ </odac:for>
102
102
 
103
103
  <!-- While loop -->
104
- <candy:while condition="counter < 10">
105
- <p><candy var="counter" /></p>
106
- </candy:while>
104
+ <odac:while condition="counter < 10">
105
+ <p><odac var="counter" /></p>
106
+ </odac:while>
107
107
 
108
108
  <!-- Loop control -->
109
- <candy:break />
110
- <candy:continue />
109
+ <odac:break />
110
+ <odac:continue />
111
111
  ```
112
112
 
113
113
  **[→ Learn more about Loops](./06-loops.md)**
@@ -117,54 +117,54 @@ Iterate over arrays and objects:
117
117
  Execute JavaScript on the server during template rendering:
118
118
 
119
119
  ```html
120
- <script:candy>
120
+ <script:odac>
121
121
  // Runs on SERVER before HTML is sent
122
122
  let total = 0;
123
123
  for (let item of cart) {
124
124
  total += item.price * item.quantity;
125
125
  }
126
- </script:candy>
126
+ </script:odac>
127
127
 
128
- <p>Total: $<candy var="total" /></p>
128
+ <p>Total: $<odac var="total" /></p>
129
129
  ```
130
130
 
131
131
  **[→ Learn more about Backend JavaScript](./08-backend-javascript.md)**
132
132
 
133
- ### Accessing the Candy Object
133
+ ### Accessing the Odac Object
134
134
 
135
- Full access to the Candy object in templates:
135
+ Full access to the Odac object in templates:
136
136
 
137
137
  ```html
138
- <candy:if condition="Candy.Auth.check()">
139
- <p>User: <candy var="Candy.Auth.user().name" /></p>
140
- </candy:if>
138
+ <odac:if condition="Odac.Auth.check()">
139
+ <p>User: <odac var="Odac.Auth.user().name" /></p>
140
+ </odac:if>
141
141
 
142
- <p>URL: <candy var="Candy.Request.url" /></p>
142
+ <p>URL: <odac var="Odac.Request.url" /></p>
143
143
  ```
144
144
 
145
145
  ### Complete Syntax Reference
146
146
 
147
147
  | Feature | Syntax | Documentation |
148
148
  |---------|--------|---------------|
149
- | Variable (Controller) | `<candy var="x" />` | [Variables](./03-variables.md) |
150
- | Raw HTML | `<candy var="x" raw />` | [Variables](./03-variables.md) |
151
- | String | `<candy>text</candy>` | [Variables](./03-variables.md) |
152
- | Query Parameter | `<candy get="key" />` | [Request Data](./04-request-data.md) |
153
- | Translation | `<candy translate>key</candy>` | [Translations](./07-translations.md) |
154
- | Translation Raw | `<candy translate raw>key</candy>` | [Translations](./07-translations.md) |
155
- | If | `<candy:if condition="x">` | [Conditionals](./05-conditionals.md) |
156
- | Elseif | `<candy:elseif condition="x">` | [Conditionals](./05-conditionals.md) |
157
- | Else | `<candy:else>` | [Conditionals](./05-conditionals.md) |
158
- | For | `<candy:for in="x" value="item">` | [Loops](./06-loops.md) |
159
- | While | `<candy:while condition="x">` | [Loops](./06-loops.md) |
160
- | Break | `<candy:break />` | [Loops](./06-loops.md) |
161
- | Continue | `<candy:continue />` | [Loops](./06-loops.md) |
162
- | JavaScript | `<script:candy>...</script:candy>` | [Backend JavaScript](./08-backend-javascript.md) |
163
- | Comment | `<!--candy ... candy-->` | [Comments](./09-comments.md) |
149
+ | Variable (Controller) | `<odac var="x" />` | [Variables](./03-variables.md) |
150
+ | Raw HTML | `<odac var="x" raw />` | [Variables](./03-variables.md) |
151
+ | String | `<odac>text</odac>` | [Variables](./03-variables.md) |
152
+ | Query Parameter | `<odac get="key" />` | [Request Data](./04-request-data.md) |
153
+ | Translation | `<odac translate>key</odac>` | [Translations](./07-translations.md) |
154
+ | Translation Raw | `<odac translate raw>key</odac>` | [Translations](./07-translations.md) |
155
+ | If | `<odac:if condition="x">` | [Conditionals](./05-conditionals.md) |
156
+ | Elseif | `<odac:elseif condition="x">` | [Conditionals](./05-conditionals.md) |
157
+ | Else | `<odac:else>` | [Conditionals](./05-conditionals.md) |
158
+ | For | `<odac:for in="x" value="item">` | [Loops](./06-loops.md) |
159
+ | While | `<odac:while condition="x">` | [Loops](./06-loops.md) |
160
+ | Break | `<odac:break />` | [Loops](./06-loops.md) |
161
+ | Continue | `<odac:continue />` | [Loops](./06-loops.md) |
162
+ | JavaScript | `<script:odac>...</script:odac>` | [Backend JavaScript](./08-backend-javascript.md) |
163
+ | Comment | `<!--odac ... odac-->` | [Comments](./09-comments.md) |
164
164
 
165
165
  ### Legacy Syntax
166
166
 
167
- CandyPack also supports legacy syntax for backward compatibility:
167
+ Odac also supports legacy syntax for backward compatibility:
168
168
 
169
169
  ```html
170
170
  <!-- Variable output -->
@@ -177,5 +177,5 @@ CandyPack also supports legacy syntax for backward compatibility:
177
177
  {{-- This is a comment --}}
178
178
  ```
179
179
 
180
- **Note:** The new `<candy>` tag syntax is recommended for all new projects.
180
+ **Note:** The new `<odac>` tag syntax is recommended for all new projects.
181
181
 
@@ -1,19 +1,19 @@
1
1
  ## 📦 Variables in Views
2
2
 
3
- Variables allow you to display dynamic data in your templates. Data is passed from controllers to views using `Candy.set()` and displayed using the `<candy var>` tag.
3
+ Variables allow you to display dynamic data in your templates. Data is passed from controllers to views using `Odac.set()` and displayed using the `<odac var>` tag.
4
4
 
5
5
  ### Passing Data from Controller
6
6
 
7
- Use `Candy.set()` in your controller to pass data to views:
7
+ Use `Odac.set()` in your controller to pass data to views:
8
8
 
9
9
  ```javascript
10
10
  // Controller: controller/profile.js
11
- module.exports = async function(Candy) {
11
+ module.exports = async function(Odac) {
12
12
  // Set single variable
13
- Candy.set('username', 'John Doe')
13
+ Odac.set('username', 'John Doe')
14
14
 
15
15
  // Set multiple variables at once
16
- Candy.set({
16
+ Odac.set({
17
17
  user: {
18
18
  name: 'John Doe',
19
19
  email: 'john@example.com',
@@ -22,7 +22,7 @@ module.exports = async function(Candy) {
22
22
  pageTitle: 'User Profile'
23
23
  })
24
24
 
25
- Candy.View.skeleton('main').set('content', 'profile')
25
+ Odac.View.skeleton('main').set('content', 'profile')
26
26
  }
27
27
  ```
28
28
 
@@ -31,9 +31,9 @@ module.exports = async function(Candy) {
31
31
  #### HTML-Safe Output (Recommended)
32
32
 
33
33
  ```html
34
- <candy var="username" />
35
- <candy var="user.email" />
36
- <candy var="product.price" />
34
+ <odac var="username" />
35
+ <odac var="user.email" />
36
+ <odac var="product.price" />
37
37
  ```
38
38
 
39
39
  This automatically:
@@ -43,12 +43,12 @@ This automatically:
43
43
  **Example:**
44
44
  ```javascript
45
45
  // Controller
46
- Candy.set('message', 'Hello\nWorld')
46
+ Odac.set('message', 'Hello\nWorld')
47
47
  ```
48
48
 
49
49
  ```html
50
50
  <!-- View -->
51
- <candy var="message" />
51
+ <odac var="message" />
52
52
  <!-- Output: Hello<br>World -->
53
53
  ```
54
54
 
@@ -57,8 +57,8 @@ Candy.set('message', 'Hello\nWorld')
57
57
  When you need to display HTML content without escaping:
58
58
 
59
59
  ```html
60
- <candy var="htmlContent" raw />
61
- <candy var="user.bio" raw />
60
+ <odac var="htmlContent" raw />
61
+ <odac var="user.bio" raw />
62
62
  ```
63
63
 
64
64
  **Security Warning:** Only use `raw` with trusted content. Never use it with user-generated content to prevent XSS attacks.
@@ -66,12 +66,12 @@ When you need to display HTML content without escaping:
66
66
  **Example:**
67
67
  ```javascript
68
68
  // Controller
69
- Candy.set('content', '<strong>Bold text</strong>')
69
+ Odac.set('content', '<strong>Bold text</strong>')
70
70
  ```
71
71
 
72
72
  ```html
73
73
  <!-- View -->
74
- <candy var="content" raw />
74
+ <odac var="content" raw />
75
75
  <!-- Output: <strong>Bold text</strong> -->
76
76
  ```
77
77
 
@@ -81,7 +81,7 @@ You can access nested object properties using dot notation:
81
81
 
82
82
  ```javascript
83
83
  // Controller
84
- Candy.set('user', {
84
+ Odac.set('user', {
85
85
  name: 'John',
86
86
  profile: {
87
87
  email: 'john@example.com',
@@ -94,9 +94,9 @@ Candy.set('user', {
94
94
 
95
95
  ```html
96
96
  <!-- View -->
97
- <p>Name: <candy var="user.name" /></p>
98
- <p>Email: <candy var="user.profile.email" /></p>
99
- <p>City: <candy var="user.profile.address.city" /></p>
97
+ <p>Name: <odac var="user.name" /></p>
98
+ <p>Email: <odac var="user.profile.email" /></p>
99
+ <p>City: <odac var="user.profile.address.city" /></p>
100
100
  ```
101
101
 
102
102
  ### String Literals
@@ -104,32 +104,32 @@ Candy.set('user', {
104
104
  Display static text directly:
105
105
 
106
106
  ```html
107
- <candy>Hello World</candy>
108
- <candy>Welcome to our site</candy>
107
+ <odac>Hello World</odac>
108
+ <odac>Welcome to our site</odac>
109
109
  ```
110
110
 
111
111
  This is useful when you want consistent syntax throughout your templates.
112
112
 
113
- ### Accessing the Candy Object
113
+ ### Accessing the Odac Object
114
114
 
115
- You have full access to the `Candy` object within templates:
115
+ You have full access to the `Odac` object within templates:
116
116
 
117
117
  ```html
118
118
  <!-- Authentication -->
119
- <candy:if condition="Candy.Auth.check()">
120
- <p>User ID: <candy var="Candy.Auth.user().id" /></p>
121
- <p>Email: <candy var="Candy.Auth.user().email" /></p>
122
- </candy:if>
119
+ <odac:if condition="Odac.Auth.check()">
120
+ <p>User ID: <odac var="Odac.Auth.user().id" /></p>
121
+ <p>Email: <odac var="Odac.Auth.user().email" /></p>
122
+ </odac:if>
123
123
 
124
124
  <!-- Request Information -->
125
- <p>Method: <candy var="Candy.Request.method" /></p>
126
- <p>URL: <candy var="Candy.Request.url" /></p>
127
- <p>IP: <candy var="Candy.Request.ip" /></p>
125
+ <p>Method: <odac var="Odac.Request.method" /></p>
126
+ <p>URL: <odac var="Odac.Request.url" /></p>
127
+ <p>IP: <odac var="Odac.Request.ip" /></p>
128
128
 
129
129
  <!-- Configuration -->
130
- <candy:if condition="Candy.Config.debug">
130
+ <odac:if condition="Odac.Config.debug">
131
131
  <div class="debug-info">Debug mode enabled</div>
132
- </candy:if>
132
+ </odac:if>
133
133
  ```
134
134
 
135
135
  ### Practical Examples
@@ -138,37 +138,37 @@ You have full access to the `Candy` object within templates:
138
138
 
139
139
  ```javascript
140
140
  // Controller: controller/profile.js
141
- module.exports = async function(Candy) {
141
+ module.exports = async function(Odac) {
142
142
  // Fetch user from database
143
- const userId = Candy.Request.get('id')
144
- const user = await Candy.Mysql.table('users')
143
+ const userId = Odac.Request.get('id')
144
+ const user = await Odac.Mysql.table('users')
145
145
  .where('id', userId)
146
146
  .first()
147
147
 
148
148
  // Pass to view
149
- Candy.set('user', {
149
+ Odac.set('user', {
150
150
  name: user.name,
151
151
  email: user.email,
152
152
  bio: user.bio,
153
153
  isVerified: user.verified
154
154
  })
155
155
 
156
- Candy.View.skeleton('main').set('content', 'profile')
156
+ Odac.View.skeleton('main').set('content', 'profile')
157
157
  }
158
158
  ```
159
159
 
160
160
  ```html
161
161
  <!-- View: view/content/profile.html -->
162
162
  <div class="profile-card">
163
- <h2><candy var="user.name" /></h2>
164
- <p><candy var="user.email" /></p>
163
+ <h2><odac var="user.name" /></h2>
164
+ <p><odac var="user.email" /></p>
165
165
 
166
- <candy:if condition="user.isVerified">
166
+ <odac:if condition="user.isVerified">
167
167
  <span class="badge">✓ Verified</span>
168
- </candy:if>
168
+ </odac:if>
169
169
 
170
170
  <div class="bio">
171
- <candy var="user.bio" raw />
171
+ <odac var="user.bio" raw />
172
172
  </div>
173
173
  </div>
174
174
  ```
@@ -177,9 +177,9 @@ module.exports = async function(Candy) {
177
177
 
178
178
  ```javascript
179
179
  // Controller: controller/product.js
180
- module.exports = async function(Candy) {
181
- const productId = Candy.Request.get('id')
182
- const product = await Candy.Mysql.table('products')
180
+ module.exports = async function(Odac) {
181
+ const productId = Odac.Request.get('id')
182
+ const product = await Odac.Mysql.table('products')
183
183
  .where('id', productId)
184
184
  .first()
185
185
 
@@ -187,31 +187,31 @@ module.exports = async function(Candy) {
187
187
  const hasDiscount = product.discount > 0
188
188
  const finalPrice = product.price * (1 - product.discount / 100)
189
189
 
190
- Candy.set({
190
+ Odac.set({
191
191
  product: product,
192
192
  hasDiscount: hasDiscount,
193
193
  finalPrice: finalPrice
194
194
  })
195
195
 
196
- Candy.View.skeleton('main').set('content', 'product')
196
+ Odac.View.skeleton('main').set('content', 'product')
197
197
  }
198
198
  ```
199
199
 
200
200
  ```html
201
201
  <!-- View: view/content/product.html -->
202
202
  <div class="product">
203
- <h1><candy var="product.name" /></h1>
203
+ <h1><odac var="product.name" /></h1>
204
204
 
205
- <candy:if condition="hasDiscount">
206
- <p class="original-price">$<candy var="product.price" /></p>
207
- <p class="final-price">$<candy var="finalPrice" /></p>
208
- <span class="discount">-<candy var="product.discount" />%</span>
209
- <candy:else>
210
- <p class="price">$<candy var="product.price" /></p>
211
- </candy:if>
205
+ <odac:if condition="hasDiscount">
206
+ <p class="original-price">$<odac var="product.price" /></p>
207
+ <p class="final-price">$<odac var="finalPrice" /></p>
208
+ <span class="discount">-<odac var="product.discount" />%</span>
209
+ <odac:else>
210
+ <p class="price">$<odac var="product.price" /></p>
211
+ </odac:if>
212
212
 
213
213
  <div class="description">
214
- <candy var="product.description" />
214
+ <odac var="product.description" />
215
215
  </div>
216
216
  </div>
217
217
  ```
@@ -220,38 +220,38 @@ module.exports = async function(Candy) {
220
220
 
221
221
  ```javascript
222
222
  // Controller: controller/products.js
223
- module.exports = async function(Candy) {
224
- const products = await Candy.Mysql.table('products')
223
+ module.exports = async function(Odac) {
224
+ const products = await Odac.Mysql.table('products')
225
225
  .where('active', true)
226
226
  .get()
227
227
 
228
- Candy.set({
228
+ Odac.set({
229
229
  products: products,
230
230
  totalProducts: products.length
231
231
  })
232
232
 
233
- Candy.View.skeleton('main').set('content', 'products')
233
+ Odac.View.skeleton('main').set('content', 'products')
234
234
  }
235
235
  ```
236
236
 
237
237
  ```html
238
238
  <!-- View: view/content/products.html -->
239
- <h1>Products (<candy var="totalProducts" />)</h1>
239
+ <h1>Products (<odac var="totalProducts" />)</h1>
240
240
 
241
241
  <div class="products-grid">
242
- <candy:for in="products" value="product">
242
+ <odac:for in="products" value="product">
243
243
  <div class="product-card">
244
- <h3><candy var="product.name" /></h3>
245
- <p>$<candy var="product.price" /></p>
244
+ <h3><odac var="product.name" /></h3>
245
+ <p>$<odac var="product.price" /></p>
246
246
  </div>
247
- </candy:for>
247
+ </odac:for>
248
248
  </div>
249
249
  ```
250
250
 
251
251
  ### Best Practices
252
252
 
253
- 1. **Always use Candy.set()**: Pass all data through `Candy.set()` for consistency
254
- 2. **Set data before rendering**: All `Candy.set()` calls should come before `Candy.View.set()`
253
+ 1. **Always use Odac.set()**: Pass all data through `Odac.set()` for consistency
254
+ 2. **Set data before rendering**: All `Odac.set()` calls should come before `Odac.View.set()`
255
255
  3. **Compute in controller**: Do calculations in the controller, not in views
256
256
  4. **Use descriptive names**: `pageTitle`, `userProfile` instead of `title`, `data`
257
257
  5. **Group related data**: Use objects to organize related data
@@ -259,10 +259,10 @@ module.exports = async function(Candy) {
259
259
  **Good:**
260
260
  ```javascript
261
261
  // Controller
262
- const user = await Candy.Mysql.table('users').first()
262
+ const user = await Odac.Mysql.table('users').first()
263
263
  const isAdmin = user.role === 'admin'
264
264
 
265
- Candy.set({
265
+ Odac.set({
266
266
  user: user,
267
267
  isAdmin: isAdmin
268
268
  })
@@ -271,9 +271,9 @@ Candy.set({
271
271
  **Avoid:**
272
272
  ```html
273
273
  <!-- Don't do complex logic in views -->
274
- <candy:if condition="user.role === 'admin' && user.verified && !user.banned">
274
+ <odac:if condition="user.role === 'admin' && user.verified && !user.banned">
275
275
  ...
276
- </candy:if>
276
+ </odac:if>
277
277
  ```
278
278
 
279
279
  ### Error Handling
@@ -282,38 +282,38 @@ Always handle cases where data might not exist:
282
282
 
283
283
  ```javascript
284
284
  // Controller
285
- module.exports = async function(Candy) {
286
- const productId = Candy.Request.get('id')
287
- const product = await Candy.Mysql.table('products')
285
+ module.exports = async function(Odac) {
286
+ const productId = Odac.Request.get('id')
287
+ const product = await Odac.Mysql.table('products')
288
288
  .where('id', productId)
289
289
  .first()
290
290
 
291
291
  if (!product) {
292
- Candy.set('error', 'Product not found')
292
+ Odac.set('error', 'Product not found')
293
293
  } else {
294
- Candy.set('product', product)
294
+ Odac.set('product', product)
295
295
  }
296
296
 
297
- Candy.View.skeleton('main').set('content', 'product')
297
+ Odac.View.skeleton('main').set('content', 'product')
298
298
  }
299
299
  ```
300
300
 
301
301
  ```html
302
302
  <!-- View -->
303
- <candy:if condition="error">
303
+ <odac:if condition="error">
304
304
  <div class="alert alert-danger">
305
- <candy var="error" />
305
+ <odac var="error" />
306
306
  </div>
307
- <candy:else>
307
+ <odac:else>
308
308
  <div class="product">
309
- <h1><candy var="product.name" /></h1>
309
+ <h1><odac var="product.name" /></h1>
310
310
  </div>
311
- </candy:if>
311
+ </odac:if>
312
312
  ```
313
313
 
314
314
  ### Legacy Syntax (Backward Compatibility)
315
315
 
316
- CandyPack also supports legacy syntax:
316
+ Odac also supports legacy syntax:
317
317
 
318
318
  ```html
319
319
  <!-- HTML-safe output -->
@@ -325,4 +325,4 @@ CandyPack also supports legacy syntax:
325
325
  {!! user.bio !!}
326
326
  ```
327
327
 
328
- **Note:** The new `<candy>` tag syntax is recommended for all new projects as it provides better IDE support and readability.
328
+ **Note:** The new `<odac>` tag syntax is recommended for all new projects as it provides better IDE support and readability.