odac 0.9.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 (213) hide show
  1. package/.editorconfig +21 -0
  2. package/.github/workflows/auto-pr-description.yml +49 -0
  3. package/.github/workflows/release.yml +32 -0
  4. package/.github/workflows/test-coverage.yml +58 -0
  5. package/.husky/pre-commit +2 -0
  6. package/.kiro/steering/code-style.md +56 -0
  7. package/.kiro/steering/product.md +20 -0
  8. package/.kiro/steering/structure.md +77 -0
  9. package/.kiro/steering/tech.md +87 -0
  10. package/.prettierrc +10 -0
  11. package/.releaserc.js +134 -0
  12. package/AGENTS.md +84 -0
  13. package/CHANGELOG.md +181 -0
  14. package/CODE_OF_CONDUCT.md +83 -0
  15. package/CONTRIBUTING.md +63 -0
  16. package/LICENSE +661 -0
  17. package/README.md +57 -0
  18. package/SECURITY.md +26 -0
  19. package/bin/candy +10 -0
  20. package/bin/candypack +10 -0
  21. package/cli/index.js +3 -0
  22. package/cli/src/Cli.js +348 -0
  23. package/cli/src/Connector.js +93 -0
  24. package/cli/src/Monitor.js +416 -0
  25. package/core/Candy.js +87 -0
  26. package/core/Commands.js +239 -0
  27. package/core/Config.js +1094 -0
  28. package/core/Lang.js +52 -0
  29. package/core/Log.js +43 -0
  30. package/core/Process.js +26 -0
  31. package/docs/backend/01-overview/01-whats-in-the-candy-box.md +9 -0
  32. package/docs/backend/01-overview/02-super-handy-helper-functions.md +9 -0
  33. package/docs/backend/01-overview/03-development-server.md +79 -0
  34. package/docs/backend/02-structure/01-typical-project-layout.md +39 -0
  35. package/docs/backend/03-config/00-configuration-overview.md +214 -0
  36. package/docs/backend/03-config/01-database-connection.md +60 -0
  37. package/docs/backend/03-config/02-static-route-mapping-optional.md +20 -0
  38. package/docs/backend/03-config/03-request-timeout.md +11 -0
  39. package/docs/backend/03-config/04-environment-variables.md +227 -0
  40. package/docs/backend/03-config/05-early-hints.md +352 -0
  41. package/docs/backend/04-routing/01-basic-page-routes.md +28 -0
  42. package/docs/backend/04-routing/02-controller-less-view-routes.md +43 -0
  43. package/docs/backend/04-routing/03-api-and-data-routes.md +20 -0
  44. package/docs/backend/04-routing/04-authentication-aware-routes.md +48 -0
  45. package/docs/backend/04-routing/05-advanced-routing.md +14 -0
  46. package/docs/backend/04-routing/06-error-pages.md +101 -0
  47. package/docs/backend/04-routing/07-cron-jobs.md +149 -0
  48. package/docs/backend/05-controllers/01-how-to-build-a-controller.md +17 -0
  49. package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +20 -0
  50. package/docs/backend/05-controllers/03-controller-classes.md +93 -0
  51. package/docs/backend/05-forms/01-custom-forms.md +395 -0
  52. package/docs/backend/05-forms/02-automatic-database-insert.md +297 -0
  53. package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +96 -0
  54. package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +40 -0
  55. package/docs/backend/07-views/01-the-view-directory.md +73 -0
  56. package/docs/backend/07-views/02-rendering-a-view.md +179 -0
  57. package/docs/backend/07-views/03-template-syntax.md +181 -0
  58. package/docs/backend/07-views/03-variables.md +328 -0
  59. package/docs/backend/07-views/04-request-data.md +231 -0
  60. package/docs/backend/07-views/05-conditionals.md +290 -0
  61. package/docs/backend/07-views/06-loops.md +353 -0
  62. package/docs/backend/07-views/07-translations.md +358 -0
  63. package/docs/backend/07-views/08-backend-javascript.md +398 -0
  64. package/docs/backend/07-views/09-comments.md +297 -0
  65. package/docs/backend/08-database/01-database-connection.md +99 -0
  66. package/docs/backend/08-database/02-using-mysql.md +322 -0
  67. package/docs/backend/09-validation/01-the-validator-service.md +424 -0
  68. package/docs/backend/10-authentication/01-user-logins-with-authjs.md +53 -0
  69. package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +55 -0
  70. package/docs/backend/10-authentication/03-register.md +134 -0
  71. package/docs/backend/10-authentication/04-candy-register-forms.md +676 -0
  72. package/docs/backend/10-authentication/05-session-management.md +159 -0
  73. package/docs/backend/10-authentication/06-candy-login-forms.md +596 -0
  74. package/docs/backend/11-mail/01-the-mail-service.md +42 -0
  75. package/docs/backend/12-streaming/01-streaming-overview.md +300 -0
  76. package/docs/backend/13-utilities/01-candy-var.md +504 -0
  77. package/docs/frontend/01-overview/01-introduction.md +146 -0
  78. package/docs/frontend/02-ajax-navigation/01-quick-start.md +608 -0
  79. package/docs/frontend/02-ajax-navigation/02-configuration.md +370 -0
  80. package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +519 -0
  81. package/docs/frontend/03-forms/01-form-handling.md +420 -0
  82. package/docs/frontend/04-api-requests/01-get-post.md +443 -0
  83. package/docs/frontend/05-streaming/01-client-streaming.md +163 -0
  84. package/docs/index.json +452 -0
  85. package/docs/server/01-installation/01-quick-install.md +19 -0
  86. package/docs/server/01-installation/02-manual-installation-via-npm.md +9 -0
  87. package/docs/server/02-get-started/01-core-concepts.md +7 -0
  88. package/docs/server/02-get-started/02-basic-commands.md +57 -0
  89. package/docs/server/02-get-started/03-cli-reference.md +276 -0
  90. package/docs/server/02-get-started/04-cli-quick-reference.md +102 -0
  91. package/docs/server/03-service/01-start-a-new-service.md +57 -0
  92. package/docs/server/03-service/02-delete-a-service.md +48 -0
  93. package/docs/server/04-web/01-create-a-website.md +36 -0
  94. package/docs/server/04-web/02-list-websites.md +9 -0
  95. package/docs/server/04-web/03-delete-a-website.md +29 -0
  96. package/docs/server/05-subdomain/01-create-a-subdomain.md +32 -0
  97. package/docs/server/05-subdomain/02-list-subdomains.md +33 -0
  98. package/docs/server/05-subdomain/03-delete-a-subdomain.md +41 -0
  99. package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +34 -0
  100. package/docs/server/07-mail/01-create-a-mail-account.md +23 -0
  101. package/docs/server/07-mail/02-delete-a-mail-account.md +20 -0
  102. package/docs/server/07-mail/03-list-mail-accounts.md +20 -0
  103. package/docs/server/07-mail/04-change-account-password.md +23 -0
  104. package/eslint.config.mjs +120 -0
  105. package/framework/index.js +4 -0
  106. package/framework/src/Auth.js +309 -0
  107. package/framework/src/Candy.js +81 -0
  108. package/framework/src/Config.js +79 -0
  109. package/framework/src/Env.js +60 -0
  110. package/framework/src/Lang.js +57 -0
  111. package/framework/src/Mail.js +83 -0
  112. package/framework/src/Mysql.js +575 -0
  113. package/framework/src/Request.js +301 -0
  114. package/framework/src/Route/Cron.js +128 -0
  115. package/framework/src/Route/Internal.js +439 -0
  116. package/framework/src/Route.js +455 -0
  117. package/framework/src/Server.js +15 -0
  118. package/framework/src/Stream.js +163 -0
  119. package/framework/src/Token.js +37 -0
  120. package/framework/src/Validator.js +271 -0
  121. package/framework/src/Var.js +211 -0
  122. package/framework/src/View/EarlyHints.js +190 -0
  123. package/framework/src/View/Form.js +600 -0
  124. package/framework/src/View.js +513 -0
  125. package/framework/web/candy.js +838 -0
  126. package/jest.config.js +22 -0
  127. package/locale/de-DE.json +80 -0
  128. package/locale/en-US.json +79 -0
  129. package/locale/es-ES.json +80 -0
  130. package/locale/fr-FR.json +80 -0
  131. package/locale/pt-BR.json +80 -0
  132. package/locale/ru-RU.json +80 -0
  133. package/locale/tr-TR.json +85 -0
  134. package/locale/zh-CN.json +80 -0
  135. package/package.json +86 -0
  136. package/server/index.js +5 -0
  137. package/server/src/Api.js +88 -0
  138. package/server/src/DNS.js +940 -0
  139. package/server/src/Hub.js +535 -0
  140. package/server/src/Mail.js +571 -0
  141. package/server/src/SSL.js +180 -0
  142. package/server/src/Server.js +27 -0
  143. package/server/src/Service.js +248 -0
  144. package/server/src/Subdomain.js +64 -0
  145. package/server/src/Web/Firewall.js +170 -0
  146. package/server/src/Web/Proxy.js +134 -0
  147. package/server/src/Web.js +451 -0
  148. package/server/src/mail/imap.js +1091 -0
  149. package/server/src/mail/server.js +32 -0
  150. package/server/src/mail/smtp.js +786 -0
  151. package/test/cli/Cli.test.js +36 -0
  152. package/test/core/Candy.test.js +234 -0
  153. package/test/core/Commands.test.js +538 -0
  154. package/test/core/Config.test.js +1435 -0
  155. package/test/core/Lang.test.js +250 -0
  156. package/test/core/Process.test.js +156 -0
  157. package/test/framework/Route.test.js +239 -0
  158. package/test/framework/View/EarlyHints.test.js +282 -0
  159. package/test/scripts/check-coverage.js +132 -0
  160. package/test/server/Api.test.js +647 -0
  161. package/test/server/Client.test.js +338 -0
  162. package/test/server/DNS.test.js +2050 -0
  163. package/test/server/DNS.test.js.bak +2084 -0
  164. package/test/server/Log.test.js +73 -0
  165. package/test/server/Mail.account.test_.js +460 -0
  166. package/test/server/Mail.init.test_.js +411 -0
  167. package/test/server/Mail.test_.js +1340 -0
  168. package/test/server/SSL.test_.js +1491 -0
  169. package/test/server/Server.test.js +765 -0
  170. package/test/server/Service.test_.js +1127 -0
  171. package/test/server/Subdomain.test.js +440 -0
  172. package/test/server/Web/Firewall.test.js +175 -0
  173. package/test/server/Web.test_.js +1562 -0
  174. package/test/server/__mocks__/acme-client.js +17 -0
  175. package/test/server/__mocks__/bcrypt.js +50 -0
  176. package/test/server/__mocks__/child_process.js +389 -0
  177. package/test/server/__mocks__/crypto.js +432 -0
  178. package/test/server/__mocks__/fs.js +450 -0
  179. package/test/server/__mocks__/globalCandy.js +227 -0
  180. package/test/server/__mocks__/http-proxy.js +105 -0
  181. package/test/server/__mocks__/http.js +575 -0
  182. package/test/server/__mocks__/https.js +272 -0
  183. package/test/server/__mocks__/index.js +249 -0
  184. package/test/server/__mocks__/mail/server.js +100 -0
  185. package/test/server/__mocks__/mail/smtp.js +31 -0
  186. package/test/server/__mocks__/mailparser.js +81 -0
  187. package/test/server/__mocks__/net.js +369 -0
  188. package/test/server/__mocks__/node-forge.js +328 -0
  189. package/test/server/__mocks__/os.js +320 -0
  190. package/test/server/__mocks__/path.js +291 -0
  191. package/test/server/__mocks__/selfsigned.js +8 -0
  192. package/test/server/__mocks__/server/src/mail/server.js +100 -0
  193. package/test/server/__mocks__/server/src/mail/smtp.js +31 -0
  194. package/test/server/__mocks__/smtp-server.js +106 -0
  195. package/test/server/__mocks__/sqlite3.js +394 -0
  196. package/test/server/__mocks__/testFactories.js +299 -0
  197. package/test/server/__mocks__/testHelpers.js +363 -0
  198. package/test/server/__mocks__/tls.js +229 -0
  199. package/watchdog/index.js +3 -0
  200. package/watchdog/src/Watchdog.js +156 -0
  201. package/web/config.json +5 -0
  202. package/web/controller/page/about.js +27 -0
  203. package/web/controller/page/index.js +34 -0
  204. package/web/package.json +18 -0
  205. package/web/public/assets/css/style.css +1835 -0
  206. package/web/public/assets/js/app.js +96 -0
  207. package/web/route/www.js +19 -0
  208. package/web/skeleton/main.html +22 -0
  209. package/web/view/content/about.html +65 -0
  210. package/web/view/content/home.html +205 -0
  211. package/web/view/footer/main.html +11 -0
  212. package/web/view/head/main.html +5 -0
  213. package/web/view/header/main.html +14 -0
@@ -0,0 +1,48 @@
1
+ ## 🔐 Authentication-Aware Routes
2
+
3
+ These methods let you define routes that require authentication. Only logged-in users can access these routes.
4
+
5
+ #### `auth.page(path, controller)`
6
+ Defines a page route that requires authentication.
7
+
8
+ ```javascript
9
+ // Only authenticated users can access the dashboard
10
+ Candy.Route.auth.page('/dashboard', 'dashboard.index');
11
+ ```
12
+
13
+ #### `auth.page(path, viewConfig)`
14
+ Defines a controller-less page route that requires authentication.
15
+
16
+ ```javascript
17
+ // Only authenticated users can see this view
18
+ Candy.Route.auth.page('/profile', {
19
+ skeleton: 'main',
20
+ head: 'profile.head',
21
+ content: 'profile',
22
+ script: 'profile'
23
+ });
24
+ ```
25
+
26
+ #### `auth.get(path, controller, options)`
27
+ Defines a GET route that requires authentication.
28
+
29
+ ```javascript
30
+ // API endpoint for authenticated users only
31
+ Candy.Route.auth.get('/api/user/profile', 'api.user.profile');
32
+ ```
33
+
34
+ #### `auth.post(path, controller, options)`
35
+ Defines a POST route that requires authentication.
36
+
37
+ ```javascript
38
+ // Only authenticated users can update their profile
39
+ Candy.Route.auth.post('/api/user/update', 'api.user.update');
40
+ ```
41
+
42
+ #### CSRF Token Protection
43
+ By default, all POST and GET routes have CSRF token protection enabled. You can disable it with the `token` option:
44
+
45
+ ```javascript
46
+ // Disable CSRF token check for this route
47
+ Candy.Route.auth.post('/api/webhook', 'api.webhook', {token: false});
48
+ ```
@@ -0,0 +1,14 @@
1
+ ## 🛠️ Advanced Routing
2
+
3
+ #### `set(type, path, controller, options)`
4
+ This is the powerful base method that all other routing methods use internally. You can use it to create routes for any custom type.
5
+
6
+ - `type`: A string defining the route type (e.g., `page`, `post`, `#page` for authenticated pages, etc.).
7
+
8
+ ```javascript
9
+ // This is equivalent to Candy.Route.post('/register', 'auth.register')
10
+ Candy.Route.set('post', '/register', 'auth.register');
11
+
12
+ // This creates an authenticated page route
13
+ Candy.Route.set('#page', '/account', 'account.settings');
14
+ ```
@@ -0,0 +1,101 @@
1
+ ## 🚨 Error Pages
2
+
3
+ CandyPack framework provides built-in error handling with customizable error pages for different HTTP status codes. You can define custom error pages to provide a better user experience when things go wrong.
4
+
5
+ #### `error(statusCode, controller)`
6
+ Maps HTTP error status codes to custom controller handlers. This allows you to create branded error pages instead of showing generic browser error messages.
7
+
8
+ - `statusCode`: The HTTP status code to handle (e.g., `404`, `500`).
9
+ - `controller`: The name of the controller file to handle this error.
10
+
11
+ ```javascript
12
+ // Custom 404 Not Found page
13
+ Candy.Route.error(404, 'errors/not-found');
14
+
15
+ // Custom 500 Internal Server Error page
16
+ Candy.Route.error(500, 'errors/server-error');
17
+
18
+ // Custom 403 Forbidden page
19
+ Candy.Route.error(403, 'errors/forbidden');
20
+ ```
21
+
22
+ #### Common Error Status Codes
23
+
24
+ - **404 Not Found**: Page or resource doesn't exist
25
+ - **403 Forbidden**: Access denied to the resource
26
+ - **500 Internal Server Error**: Server-side error occurred
27
+ - **401 Unauthorized**: Authentication required
28
+ - **400 Bad Request**: Invalid request format
29
+
30
+ #### Error Controller Example
31
+
32
+ Create error controllers in your `controller/errors/` directory:
33
+
34
+ ```javascript
35
+ // controller/errors/not-found.js
36
+ module.exports = function() {
37
+ Candy.response.status(404);
38
+ return Candy.view('errors/404', {
39
+ title: 'Page Not Found',
40
+ message: 'The page you are looking for could not be found.'
41
+ });
42
+ };
43
+ ```
44
+
45
+ ```javascript
46
+ // controller/errors/server-error.js
47
+ module.exports = function() {
48
+ Candy.response.status(500);
49
+ return Candy.view('errors/500', {
50
+ title: 'Server Error',
51
+ message: 'Something went wrong on our end. Please try again later.'
52
+ });
53
+ };
54
+ ```
55
+
56
+ #### Error Views
57
+
58
+ Create corresponding view templates in your `view/errors/` directory:
59
+
60
+ ```html
61
+ <!-- view/errors/404.html -->
62
+ <!DOCTYPE html>
63
+ <html>
64
+ <head>
65
+ <title>{{title}}</title>
66
+ </head>
67
+ <body>
68
+ <h1>404 - Page Not Found</h1>
69
+ <p>{{message}}</p>
70
+ <a href="/">Go back to homepage</a>
71
+ </body>
72
+ </html>
73
+ ```
74
+
75
+ #### Default Error Handling
76
+
77
+ If no custom error page is defined, CandyPack will fall back to its built-in error responses. It's recommended to at least define custom 404 and 500 error pages for a professional user experience.
78
+
79
+ #### Error Context
80
+
81
+ Error controllers receive the same Candy context as regular controllers, allowing you to:
82
+
83
+ - Access request information (`Candy.request`)
84
+ - Use database connections (`Candy.db`)
85
+ - Render views with data (`Candy.view`)
86
+ - Redirect users (`Candy.redirect`)
87
+ - Log error details for debugging
88
+
89
+ ```javascript
90
+ // controller/errors/server-error.js
91
+ module.exports = function() {
92
+ // Log the error for debugging
93
+ console.error('Server error occurred:', Candy.request.url);
94
+
95
+ Candy.response.status(500);
96
+ return Candy.view('errors/500', {
97
+ title: 'Oops! Something went wrong',
98
+ supportEmail: 'support@yoursite.com'
99
+ });
100
+ };
101
+ ```
@@ -0,0 +1,149 @@
1
+ # Cron Jobs
2
+
3
+ The CandyPack framework provides a built-in cron system for running automated tasks. This system checks every minute and executes jobs based on specified conditions.
4
+
5
+ ## Basic Usage
6
+
7
+ Use the `Candy.Route.cron()` method to define cron jobs:
8
+
9
+ ```javascript
10
+ // With controller file
11
+ Candy.Route.cron('backup').everyDay(1) // Runs every day
12
+
13
+ // With direct function
14
+ Candy.Route.cron(() => {
15
+ console.log('Task executed!')
16
+ }).everyHour(2) // Runs every 2 hours
17
+ ```
18
+
19
+ ## Controller Files
20
+
21
+ Controller files for cron jobs are created in the `controller/cron/` directory:
22
+
23
+ ```javascript
24
+ // controller/cron/backup.js
25
+ module.exports = () => {
26
+ console.log('Backup process started')
27
+ // Backup code...
28
+ }
29
+ ```
30
+
31
+ For module-based organization:
32
+
33
+ ```javascript
34
+ // controller/admin/cron/cleanup.js
35
+ module.exports = () => {
36
+ console.log('Cleanup process')
37
+ }
38
+
39
+ // Usage
40
+ Candy.Route.cron('admin.cleanup').everyDay(1)
41
+ ```
42
+
43
+ ## Direct Function Usage
44
+
45
+ You can also define cron jobs with inline functions:
46
+
47
+ ```javascript
48
+ // Simple inline function
49
+ Candy.Route.cron(() => console.log('Simple task running')).everyMinute(5)
50
+
51
+ // Async function
52
+ Candy.Route.cron(async () => {
53
+ const data = await fetchSomeData()
54
+ console.log('Async task completed', data)
55
+ }).everyHour(1)
56
+
57
+ // Function with parameters
58
+ const cleanupTask = (directory) => {
59
+ console.log(`Cleaning up ${directory}`)
60
+ // Cleanup logic...
61
+ }
62
+
63
+ Candy.Route.cron(() => cleanupTask('/tmp')).everyDay(1)
64
+ ```
65
+
66
+ ## Time Conditions
67
+
68
+ ### Specific Time Values
69
+
70
+ ```javascript
71
+ Candy.Route.cron('task')
72
+
73
+ // Minute (0-59)
74
+ .minute(30) // At 30th minute
75
+
76
+ // Hour (0-23)
77
+ .hour(14) // At 14:00
78
+
79
+ // Day (1-31)
80
+ .day(15) // On the 15th of the month
81
+
82
+ // Week day (0-6, 0=Sunday)
83
+ .weekDay(1) // On Monday
84
+
85
+ // Month (1-12)
86
+ .month(6) // In June
87
+
88
+ // Year
89
+ .year(2024) // In 2024
90
+
91
+ // Year day (1-365)
92
+ .yearDay(100) // On the 100th day of the year
93
+ ```
94
+
95
+ ### Periodic Execution
96
+
97
+ ```javascript
98
+ Candy.Route.cron('periodic')
99
+
100
+ // Every N minutes
101
+ .everyMinute(5) // Every 5 minutes
102
+
103
+ // Every N hours
104
+ .everyHour(3) // Every 3 hours
105
+
106
+ // Every N days
107
+ .everyDay(2) // Every 2 days
108
+
109
+ // Every N weeks
110
+ .everyWeekDay(1) // Every week
111
+
112
+ // Every N months
113
+ .everyMonth(2) // Every 2 months
114
+
115
+ // Every N years
116
+ .everyYear(1) // Every year
117
+ ```
118
+
119
+ ## Combination Usage
120
+
121
+ You can combine multiple conditions:
122
+
123
+ ```javascript
124
+ // Every day at 14:30
125
+ Candy.Route.cron('daily-report')
126
+ .hour(14)
127
+ .minute(30)
128
+
129
+ // Mondays at 09:00
130
+ Candy.Route.cron('weekly-task')
131
+ .weekDay(1)
132
+ .hour(9)
133
+ .minute(0)
134
+
135
+ // First day of every month at midnight
136
+ Candy.Route.cron('monthly-cleanup')
137
+ .day(1)
138
+ .hour(0)
139
+ .minute(0)
140
+ ```
141
+
142
+ ## Important Notes
143
+
144
+ - The cron system checks every minute
145
+ - Jobs run at the first suitable time after their last update
146
+ - If the same job is defined multiple times, the last definition takes precedence
147
+ - Controller files are re-required on each execution
148
+ - Inline functions are stored in memory and executed directly
149
+ - If a job fails, it stops but the system continues
@@ -0,0 +1,17 @@
1
+ ## 🏗️ How to Build a Controller
2
+
3
+ A controller is just a JavaScript module that exports a function. This function automatically gets the magical `Candy` context object we talked about in the overview.
4
+
5
+ #### A Simple "Hello World" Controller
6
+
7
+ Check out this basic example from `controller/page/index.js`:
8
+
9
+ ```javascript
10
+ // This function is our controller!
11
+ module.exports = function (Candy) {
12
+ // It simply returns a string.
13
+ return 'Welcome to my awesome CandyPack server!'
14
+ }
15
+ ```
16
+
17
+ This little guy is responsible for handling the homepage route (`/`). When it runs, it just sends a simple string back to the user's browser.
@@ -0,0 +1,20 @@
1
+ ## 🤝 Your trusty `Candy` Assistant
2
+
3
+ Remember the `Candy` object? It's your best friend inside a controller. It's passed to your controller function and gives you all the tools you need for the current request.
4
+
5
+ #### Awesome Services at Your Fingertips
6
+
7
+ * `Candy.Request`: Info about the user's request.
8
+ * `Candy.View`: Renders your HTML pages.
9
+ * `Candy.Auth`: Manages user logins.
10
+ * `Candy.Token`: Protects your forms.
11
+ * `Candy.Lang`: Helps with different languages.
12
+
13
+ #### Handy Helper Functions
14
+
15
+ * `Candy.return(data)`: Send back a response.
16
+ * `Candy.direct(url)`: Redirect the user to a new page.
17
+ * `Candy.cookie(key, value)`: Set a browser cookie.
18
+ * `Candy.validator()`: Check user input easily.
19
+
20
+ With controllers and the `Candy` object, you have everything you need to start building powerful application logic!
@@ -0,0 +1,93 @@
1
+ ## 🎓 Controller Classes
2
+
3
+ While simple function exports work great for basic controllers, you can also organize your code using classes. This is especially useful when you want to share logic between multiple methods or keep related functionality together.
4
+
5
+ #### Creating a Controller Class
6
+
7
+ A controller class receives the `Candy` object in its constructor, giving you access to all services throughout your class methods:
8
+
9
+ ```javascript
10
+ // controller/User.js
11
+ class User {
12
+ constructor(Candy) {
13
+ this.Candy = Candy
14
+ }
15
+
16
+ async getProfile() {
17
+ const user = await this.Candy.Auth.user()
18
+ return this.Candy.return({
19
+ success: true,
20
+ user: user
21
+ })
22
+ }
23
+
24
+ async updateProfile() {
25
+ const validator = this.Candy.validator()
26
+ validator.post('name').required().min(3)
27
+ validator.post('email').required().email()
28
+
29
+ if (await validator.error()) {
30
+ return validator.result()
31
+ }
32
+
33
+ const name = await this.Candy.request('name')
34
+ const email = await this.Candy.request('email')
35
+
36
+ // Update user in database
37
+ await this.Candy.Mysql.query('UPDATE users SET name = ?, email = ? WHERE id = ?', [
38
+ name,
39
+ email,
40
+ this.Candy.Auth.user().id
41
+ ])
42
+
43
+ return this.Candy.return({
44
+ success: true,
45
+ message: 'Profile updated successfully'
46
+ })
47
+ }
48
+ }
49
+
50
+ module.exports = User
51
+ ```
52
+
53
+ #### Using Controller Classes in Routes
54
+
55
+ Once you've created a controller class, you can use it in your routes just like any other controller:
56
+
57
+ ```javascript
58
+ // route/www.js
59
+ Candy.Route.buff = 'www'
60
+
61
+ // Access class methods using dot notation
62
+ Candy.Route.get('/profile', 'User.getProfile')
63
+ Candy.Route.post('/profile/update', 'User.updateProfile')
64
+ ```
65
+
66
+ #### Accessing Classes in Controllers
67
+
68
+ Controller classes are automatically instantiated for each request and attached to the `Candy` object. You can access them from any controller:
69
+
70
+ ```javascript
71
+ module.exports = async function (Candy) {
72
+ // Access your User class
73
+ const profile = await Candy.User.getProfile()
74
+
75
+ return Candy.return(profile)
76
+ }
77
+ ```
78
+
79
+ #### Benefits of Controller Classes
80
+
81
+ - **Organization**: Group related methods together
82
+ - **Reusability**: Share logic between different routes
83
+ - **Maintainability**: Easier to manage complex controllers
84
+ - **Context**: The `Candy` object is always available via `this.Candy`
85
+
86
+ #### Class vs Function Controllers
87
+
88
+ Both approaches work perfectly fine. Use what makes sense for your project:
89
+
90
+ - **Functions**: Great for simple, single-purpose controllers
91
+ - **Classes**: Better for complex logic with multiple related methods
92
+
93
+ The framework automatically detects whether your export is a class or a function and handles it accordingly.