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,16 +1,16 @@
1
- ## 🔧 Candy.Var - String Manipulation & Validation
1
+ ## 🔧 Odac.Var - String Manipulation & Validation
2
2
 
3
- `Candy.Var` is a powerful utility class for string manipulation, validation, encryption, and formatting. It provides a chainable, fluent interface for common string operations.
3
+ `Odac.Var` is a powerful utility class for string manipulation, validation, encryption, and formatting. It provides a chainable, fluent interface for common string operations.
4
4
 
5
5
  ### Basic Usage
6
6
 
7
7
  ```javascript
8
8
  // Create a Var instance
9
- const result = Candy.Var('hello world').slug()
9
+ const result = Odac.Var('hello world').slug()
10
10
  // Returns: 'hello-world'
11
11
 
12
12
  // Chain multiple operations
13
- const email = Candy.Var(' USER@EXAMPLE.COM ').trim().toLowerCase()
13
+ const email = Odac.Var(' USER@EXAMPLE.COM ').trim().toLowerCase()
14
14
  ```
15
15
 
16
16
  ### String Validation
@@ -21,23 +21,23 @@ Check if a string matches specific patterns:
21
21
 
22
22
  ```javascript
23
23
  // Email validation
24
- Candy.Var('user@example.com').is('email') // true
25
- Candy.Var('invalid-email').is('email') // false
24
+ Odac.Var('user@example.com').is('email') // true
25
+ Odac.Var('invalid-email').is('email') // false
26
26
 
27
27
  // Numeric validation
28
- Candy.Var('12345').is('numeric') // true
29
- Candy.Var('abc123').is('numeric') // false
28
+ Odac.Var('12345').is('numeric') // true
29
+ Odac.Var('abc123').is('numeric') // false
30
30
 
31
31
  // Multiple conditions (AND logic)
32
- Candy.Var('abc123').is('alphanumeric') // true
32
+ Odac.Var('abc123').is('alphanumeric') // true
33
33
  ```
34
34
 
35
35
  #### isAny() - Multiple Validation (OR logic)
36
36
 
37
37
  ```javascript
38
38
  // Check if value matches ANY of the conditions
39
- Candy.Var('user@example.com').isAny('email', 'domain') // true
40
- Candy.Var('example.com').isAny('email', 'domain') // true
39
+ Odac.Var('user@example.com').isAny('email', 'domain') // true
40
+ Odac.Var('example.com').isAny('email', 'domain') // true
41
41
  ```
42
42
 
43
43
  #### Available Validation Types
@@ -67,11 +67,11 @@ Candy.Var('example.com').isAny('email', 'domain') // true
67
67
 
68
68
  ```javascript
69
69
  // Controller validation
70
- module.exports = async function(Candy) {
71
- const email = Candy.Request.post('email')
70
+ module.exports = async function(Odac) {
71
+ const email = Odac.Request.post('email')
72
72
 
73
- if (!Candy.Var(email).is('email')) {
74
- return Candy.return({
73
+ if (!Odac.Var(email).is('email')) {
74
+ return Odac.return({
75
75
  success: false,
76
76
  message: 'Invalid email address'
77
77
  })
@@ -87,40 +87,40 @@ module.exports = async function(Candy) {
87
87
 
88
88
  ```javascript
89
89
  // Single value
90
- Candy.Var('hello world').contains('world') // true
91
- Candy.Var('hello world').contains('foo') // false
90
+ Odac.Var('hello world').contains('world') // true
91
+ Odac.Var('hello world').contains('foo') // false
92
92
 
93
93
  // Multiple values (AND logic - must contain all)
94
- Candy.Var('hello world').contains('hello', 'world') // true
95
- Candy.Var('hello world').contains('hello', 'foo') // false
94
+ Odac.Var('hello world').contains('hello', 'world') // true
95
+ Odac.Var('hello world').contains('hello', 'foo') // false
96
96
  ```
97
97
 
98
98
  #### containsAny() - Check if string contains any value
99
99
 
100
100
  ```javascript
101
101
  // Check if contains ANY of the values (OR logic)
102
- Candy.Var('hello world').containsAny('foo', 'world') // true
103
- Candy.Var('hello world').containsAny('foo', 'bar') // false
102
+ Odac.Var('hello world').containsAny('foo', 'world') // true
103
+ Odac.Var('hello world').containsAny('foo', 'bar') // false
104
104
  ```
105
105
 
106
106
  #### isBegin() - Check if string starts with value
107
107
 
108
108
  ```javascript
109
- Candy.Var('hello world').isBegin('hello') // true
110
- Candy.Var('hello world').isBegin('world') // false
109
+ Odac.Var('hello world').isBegin('hello') // true
110
+ Odac.Var('hello world').isBegin('world') // false
111
111
 
112
112
  // Multiple options
113
- Candy.Var('https://example.com').isBegin('http://', 'https://') // true
113
+ Odac.Var('https://example.com').isBegin('http://', 'https://') // true
114
114
  ```
115
115
 
116
116
  #### isEnd() - Check if string ends with value
117
117
 
118
118
  ```javascript
119
- Candy.Var('hello world').isEnd('world') // true
120
- Candy.Var('hello world').isEnd('hello') // false
119
+ Odac.Var('hello world').isEnd('world') // true
120
+ Odac.Var('hello world').isEnd('hello') // false
121
121
 
122
122
  // Multiple options
123
- Candy.Var('image.jpg').isEnd('.jpg', '.png', '.gif') // true
123
+ Odac.Var('image.jpg').isEnd('.jpg', '.png', '.gif') // true
124
124
  ```
125
125
 
126
126
  ### String Manipulation
@@ -129,47 +129,47 @@ Candy.Var('image.jpg').isEnd('.jpg', '.png', '.gif') // true
129
129
 
130
130
  ```javascript
131
131
  // Simple replacement
132
- Candy.Var('hello world').replace('world', 'universe')
132
+ Odac.Var('hello world').replace('world', 'universe')
133
133
  // Returns: 'hello universe'
134
134
 
135
135
  // Multiple replacements with object
136
- Candy.Var('Hello {{name}}, welcome to {{site}}').replace({
136
+ Odac.Var('Hello {{name}}, welcome to {{site}}').replace({
137
137
  '{{name}}': 'John',
138
- '{{site}}': 'CandyPack'
138
+ '{{site}}': 'Odac'
139
139
  })
140
- // Returns: 'Hello John, welcome to CandyPack'
140
+ // Returns: 'Hello John, welcome to Odac'
141
141
 
142
142
  // Works with arrays/objects recursively
143
143
  const data = {
144
144
  title: 'Welcome {{name}}',
145
145
  message: 'Hello {{name}}'
146
146
  }
147
- Candy.Var(data).replace({'{{name}}': 'John'})
147
+ Odac.Var(data).replace({'{{name}}': 'John'})
148
148
  // Returns: { title: 'Welcome John', message: 'Hello John' }
149
149
  ```
150
150
 
151
151
  #### clear() - Remove specific strings
152
152
 
153
153
  ```javascript
154
- Candy.Var('hello-world-test').clear('-')
154
+ Odac.Var('hello-world-test').clear('-')
155
155
  // Returns: 'helloworldtest'
156
156
 
157
157
  // Remove multiple strings
158
- Candy.Var('a1b2c3').clear('1', '2', '3')
158
+ Odac.Var('a1b2c3').clear('1', '2', '3')
159
159
  // Returns: 'abc'
160
160
  ```
161
161
 
162
162
  #### slug() - Create URL-friendly slug
163
163
 
164
164
  ```javascript
165
- Candy.Var('Hello World!').slug()
165
+ Odac.Var('Hello World!').slug()
166
166
  // Returns: 'hello-world'
167
167
 
168
- Candy.Var('Product Name 2024').slug()
168
+ Odac.Var('Product Name 2024').slug()
169
169
  // Returns: 'product-name-2024'
170
170
 
171
171
  // Custom separator
172
- Candy.Var('Hello World').slug('_')
172
+ Odac.Var('Hello World').slug('_')
173
173
  // Returns: 'hello_world'
174
174
  ```
175
175
 
@@ -177,17 +177,17 @@ Candy.Var('Hello World').slug('_')
177
177
 
178
178
  ```javascript
179
179
  // ? = single character, * = rest of string
180
- Candy.Var('1234567890').format('(???) ???-????')
180
+ Odac.Var('1234567890').format('(???) ???-????')
181
181
  // Returns: '(123) 456-7890'
182
182
 
183
- Candy.Var('TR1234567890').format('?? *')
183
+ Odac.Var('TR1234567890').format('?? *')
184
184
  // Returns: 'TR 1234567890'
185
185
  ```
186
186
 
187
187
  #### html() - Escape HTML
188
188
 
189
189
  ```javascript
190
- Candy.Var('<script>alert("xss")</script>').html()
190
+ Odac.Var('<script>alert("xss")</script>').html()
191
191
  // Returns: '&lt;script&gt;alert("xss")&lt;/script&gt;'
192
192
  ```
193
193
 
@@ -197,46 +197,46 @@ Candy.Var('<script>alert("xss")</script>').html()
197
197
 
198
198
  ```javascript
199
199
  // Hash a password
200
- const hashedPassword = Candy.Var('mypassword').hash()
200
+ const hashedPassword = Odac.Var('mypassword').hash()
201
201
  // Returns: '$2b$10$...' (BCrypt hash)
202
202
 
203
203
  // Custom salt rounds
204
- const hashedPassword = Candy.Var('mypassword').hash(12)
204
+ const hashedPassword = Odac.Var('mypassword').hash(12)
205
205
  ```
206
206
 
207
207
  #### hashCheck() - Verify BCrypt hash
208
208
 
209
209
  ```javascript
210
210
  const hashedPassword = '$2b$10$...'
211
- const isValid = Candy.Var(hashedPassword).hashCheck('mypassword')
211
+ const isValid = Odac.Var(hashedPassword).hashCheck('mypassword')
212
212
  // Returns: true or false
213
213
  ```
214
214
 
215
215
  #### md5() - MD5 hash
216
216
 
217
217
  ```javascript
218
- Candy.Var('hello').md5()
218
+ Odac.Var('hello').md5()
219
219
  // Returns: '5d41402abc4b2a76b9719d911017c592'
220
220
  ```
221
221
 
222
222
  #### encrypt() - AES-256 encryption
223
223
 
224
224
  ```javascript
225
- // Uses key from Candy.Config.encrypt.key
226
- const encrypted = Candy.Var('secret data').encrypt()
225
+ // Uses key from Odac.Config.encrypt.key
226
+ const encrypted = Odac.Var('secret data').encrypt()
227
227
 
228
228
  // Custom encryption key
229
- const encrypted = Candy.Var('secret data').encrypt('my-32-character-encryption-key')
229
+ const encrypted = Odac.Var('secret data').encrypt('my-32-character-encryption-key')
230
230
  ```
231
231
 
232
232
  #### decrypt() - AES-256 decryption
233
233
 
234
234
  ```javascript
235
- // Uses key from Candy.Config.encrypt.key
236
- const decrypted = Candy.Var(encryptedData).decrypt()
235
+ // Uses key from Odac.Config.encrypt.key
236
+ const decrypted = Odac.Var(encryptedData).decrypt()
237
237
 
238
238
  // Custom decryption key
239
- const decrypted = Candy.Var(encryptedData).decrypt('my-32-character-encryption-key')
239
+ const decrypted = Odac.Var(encryptedData).decrypt('my-32-character-encryption-key')
240
240
  ```
241
241
 
242
242
  ### Date Formatting
@@ -246,16 +246,16 @@ const decrypted = Candy.Var(encryptedData).decrypt('my-32-character-encryption-k
246
246
  ```javascript
247
247
  const timestamp = '2024-03-15 14:30:45'
248
248
 
249
- Candy.Var(timestamp).date('Y-m-d')
249
+ Odac.Var(timestamp).date('Y-m-d')
250
250
  // Returns: '2024-03-15'
251
251
 
252
- Candy.Var(timestamp).date('d/m/Y')
252
+ Odac.Var(timestamp).date('d/m/Y')
253
253
  // Returns: '15/03/2024'
254
254
 
255
- Candy.Var(timestamp).date('H:i:s')
255
+ Odac.Var(timestamp).date('H:i:s')
256
256
  // Returns: '14:30:45'
257
257
 
258
- Candy.Var(timestamp).date('Y-m-d H:i')
258
+ Odac.Var(timestamp).date('Y-m-d H:i')
259
259
  // Returns: '2024-03-15 14:30'
260
260
  ```
261
261
 
@@ -274,10 +274,10 @@ Candy.Var(timestamp).date('Y-m-d H:i')
274
274
 
275
275
  ```javascript
276
276
  // Save content to file
277
- Candy.Var('Hello World').save('/path/to/file.txt')
277
+ Odac.Var('Hello World').save('/path/to/file.txt')
278
278
 
279
279
  // Automatically creates directories if needed
280
- Candy.Var(jsonData).save('/path/to/nested/dir/data.json')
280
+ Odac.Var(jsonData).save('/path/to/nested/dir/data.json')
281
281
  ```
282
282
 
283
283
  ### Practical Examples
@@ -285,117 +285,117 @@ Candy.Var(jsonData).save('/path/to/nested/dir/data.json')
285
285
  #### User Registration with Validation
286
286
 
287
287
  ```javascript
288
- module.exports = async function(Candy) {
289
- const email = Candy.Request.post('email')
290
- const password = Candy.Request.post('password')
291
- const username = Candy.Request.post('username')
288
+ module.exports = async function(Odac) {
289
+ const email = Odac.Request.post('email')
290
+ const password = Odac.Request.post('password')
291
+ const username = Odac.Request.post('username')
292
292
 
293
293
  // Validate email
294
- if (!Candy.Var(email).is('email')) {
295
- return Candy.return({
294
+ if (!Odac.Var(email).is('email')) {
295
+ return Odac.return({
296
296
  success: false,
297
297
  message: 'Invalid email address'
298
298
  })
299
299
  }
300
300
 
301
301
  // Validate username (alphanumeric only)
302
- if (!Candy.Var(username).is('alphanumeric')) {
303
- return Candy.return({
302
+ if (!Odac.Var(username).is('alphanumeric')) {
303
+ return Odac.return({
304
304
  success: false,
305
305
  message: 'Username must be alphanumeric'
306
306
  })
307
307
  }
308
308
 
309
309
  // Hash password
310
- const hashedPassword = Candy.Var(password).hash()
310
+ const hashedPassword = Odac.Var(password).hash()
311
311
 
312
312
  // Create slug for profile URL
313
- const profileSlug = Candy.Var(username).slug()
313
+ const profileSlug = Odac.Var(username).slug()
314
314
 
315
315
  // Save user
316
- await Candy.Mysql.table('users').insert({
316
+ await Odac.Mysql.table('users').insert({
317
317
  email: email,
318
318
  username: username,
319
319
  password: hashedPassword,
320
320
  slug: profileSlug
321
321
  })
322
322
 
323
- return Candy.return({success: true})
323
+ return Odac.return({success: true})
324
324
  }
325
325
  ```
326
326
 
327
327
  #### Login with Password Verification
328
328
 
329
329
  ```javascript
330
- module.exports = async function(Candy) {
331
- const email = Candy.Request.post('email')
332
- const password = Candy.Request.post('password')
330
+ module.exports = async function(Odac) {
331
+ const email = Odac.Request.post('email')
332
+ const password = Odac.Request.post('password')
333
333
 
334
334
  // Find user
335
- const user = await Candy.Mysql.table('users')
335
+ const user = await Odac.Mysql.table('users')
336
336
  .where('email', email)
337
337
  .first()
338
338
 
339
339
  if (!user) {
340
- return Candy.return({
340
+ return Odac.return({
341
341
  success: false,
342
342
  message: 'User not found'
343
343
  })
344
344
  }
345
345
 
346
346
  // Verify password
347
- const isValid = Candy.Var(user.password).hashCheck(password)
347
+ const isValid = Odac.Var(user.password).hashCheck(password)
348
348
 
349
349
  if (!isValid) {
350
- return Candy.return({
350
+ return Odac.return({
351
351
  success: false,
352
352
  message: 'Invalid password'
353
353
  })
354
354
  }
355
355
 
356
356
  // Login successful
357
- Candy.Auth.login(user.id)
358
- return Candy.return({success: true})
357
+ Odac.Auth.login(user.id)
358
+ return Odac.return({success: true})
359
359
  }
360
360
  ```
361
361
 
362
362
  #### URL Slug Generation
363
363
 
364
364
  ```javascript
365
- module.exports = async function(Candy) {
366
- const title = Candy.Request.post('title')
365
+ module.exports = async function(Odac) {
366
+ const title = Odac.Request.post('title')
367
367
 
368
368
  // Create URL-friendly slug
369
- const slug = Candy.Var(title).slug()
369
+ const slug = Odac.Var(title).slug()
370
370
 
371
371
  // Check if slug exists
372
- const exists = await Candy.Mysql.table('posts')
372
+ const exists = await Odac.Mysql.table('posts')
373
373
  .where('slug', slug)
374
374
  .first()
375
375
 
376
376
  if (exists) {
377
377
  // Add timestamp to make unique
378
378
  const uniqueSlug = `${slug}-${Date.now()}`
379
- await Candy.Mysql.table('posts').insert({
379
+ await Odac.Mysql.table('posts').insert({
380
380
  title: title,
381
381
  slug: uniqueSlug
382
382
  })
383
383
  } else {
384
- await Candy.Mysql.table('posts').insert({
384
+ await Odac.Mysql.table('posts').insert({
385
385
  title: title,
386
386
  slug: slug
387
387
  })
388
388
  }
389
389
 
390
- return Candy.return({success: true})
390
+ return Odac.return({success: true})
391
391
  }
392
392
  ```
393
393
 
394
394
  #### Template Variable Replacement
395
395
 
396
396
  ```javascript
397
- module.exports = async function(Candy) {
398
- const user = await Candy.Auth.user()
397
+ module.exports = async function(Odac) {
398
+ const user = await Odac.Auth.user()
399
399
 
400
400
  // Email template
401
401
  const template = `
@@ -409,45 +409,45 @@ module.exports = async function(Candy) {
409
409
  `
410
410
 
411
411
  // Replace variables
412
- const emailContent = Candy.Var(template).replace({
412
+ const emailContent = Odac.Var(template).replace({
413
413
  '{{name}}': user.name,
414
414
  '{{email}}': user.email,
415
415
  '{{url}}': 'https://example.com/dashboard',
416
- '{{site}}': 'CandyPack'
416
+ '{{site}}': 'Odac'
417
417
  })
418
418
 
419
419
  // Send email
420
- await Candy.Mail.send({
420
+ await Odac.Mail.send({
421
421
  to: user.email,
422
422
  subject: 'Account Verified',
423
423
  body: emailContent
424
424
  })
425
425
 
426
- return Candy.return({success: true})
426
+ return Odac.return({success: true})
427
427
  }
428
428
  ```
429
429
 
430
430
  #### Phone Number Formatting
431
431
 
432
432
  ```javascript
433
- module.exports = async function(Candy) {
434
- const phone = Candy.Request.post('phone')
433
+ module.exports = async function(Odac) {
434
+ const phone = Odac.Request.post('phone')
435
435
 
436
436
  // Remove all non-numeric characters
437
- const cleanPhone = Candy.Var(phone).clear('-', ' ', '(', ')', '+')
437
+ const cleanPhone = Odac.Var(phone).clear('-', ' ', '(', ')', '+')
438
438
 
439
439
  // Validate it's numeric
440
- if (!Candy.Var(cleanPhone).is('numeric')) {
441
- return Candy.return({
440
+ if (!Odac.Var(cleanPhone).is('numeric')) {
441
+ return Odac.return({
442
442
  success: false,
443
443
  message: 'Invalid phone number'
444
444
  })
445
445
  }
446
446
 
447
447
  // Format for display
448
- const formattedPhone = Candy.Var(cleanPhone).format('(???) ???-????')
448
+ const formattedPhone = Odac.Var(cleanPhone).format('(???) ???-????')
449
449
 
450
- return Candy.return({
450
+ return Odac.return({
451
451
  success: true,
452
452
  phone: formattedPhone
453
453
  })
@@ -457,31 +457,31 @@ module.exports = async function(Candy) {
457
457
  #### Data Encryption for Storage
458
458
 
459
459
  ```javascript
460
- module.exports = async function(Candy) {
461
- const creditCard = Candy.Request.post('credit_card')
460
+ module.exports = async function(Odac) {
461
+ const creditCard = Odac.Request.post('credit_card')
462
462
 
463
463
  // Encrypt sensitive data
464
- const encryptedCard = Candy.Var(creditCard).encrypt()
464
+ const encryptedCard = Odac.Var(creditCard).encrypt()
465
465
 
466
466
  // Save encrypted data
467
- await Candy.Mysql.table('payments').insert({
468
- user_id: Candy.Auth.id(),
467
+ await Odac.Mysql.table('payments').insert({
468
+ user_id: Odac.Auth.id(),
469
469
  card: encryptedCard
470
470
  })
471
471
 
472
- return Candy.return({success: true})
472
+ return Odac.return({success: true})
473
473
  }
474
474
 
475
475
  // Later, to retrieve and decrypt
476
- module.exports = async function(Candy) {
477
- const payment = await Candy.Mysql.table('payments')
478
- .where('user_id', Candy.Auth.id())
476
+ module.exports = async function(Odac) {
477
+ const payment = await Odac.Mysql.table('payments')
478
+ .where('user_id', Odac.Auth.id())
479
479
  .first()
480
480
 
481
481
  // Decrypt data
482
- const creditCard = Candy.Var(payment.card).decrypt()
482
+ const creditCard = Odac.Var(payment.card).decrypt()
483
483
 
484
- return Candy.return({
484
+ return Odac.return({
485
485
  card: creditCard
486
486
  })
487
487
  }
@@ -498,7 +498,7 @@ module.exports = async function(Candy) {
498
498
 
499
499
  ### Notes
500
500
 
501
- - `Candy.Var()` returns the processed string value, not a Var instance (except for chaining)
501
+ - `Odac.Var()` returns the processed string value, not a Var instance (except for chaining)
502
502
  - Encryption uses AES-256-CBC with a fixed IV
503
503
  - BCrypt hashing is one-way and cannot be decrypted
504
504
  - Date formatting works with any valid JavaScript date string