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,370 @@
1
+ # AJAX Navigation Configuration
2
+
3
+ Learn how to configure and customize AJAX navigation in your CandyPack application.
4
+
5
+ ## Prerequisites
6
+
7
+ Before configuring AJAX navigation, ensure your skeleton template is properly set up. See the [Quick Start guide](01-quick-start.md#skeleton-structure-required) for skeleton setup instructions.
8
+
9
+ **Key requirements:**
10
+ - Skeleton placeholders must be UPPERCASE and wrapped in HTML tags (e.g., `<main>{{ CONTENT }}</main>`)
11
+ - Controller keys are lowercase (e.g., `content: 'home'`)
12
+ - Frontend selectors target the HTML tags (e.g., `content: 'main'` targets `<main>` tag)
13
+
14
+ **Mapping example:**
15
+ - Skeleton: `<main>{{ CONTENT }}</main>`
16
+ - Controller: `content: 'home'`
17
+ - Frontend: `update: { content: 'main' }`
18
+
19
+ ## Configuration Options
20
+
21
+ ### Basic Configuration
22
+
23
+ The simplest way to enable AJAX navigation:
24
+
25
+ ```javascript
26
+ Candy.action({
27
+ navigate: 'main' // Update <main> element
28
+ })
29
+ ```
30
+
31
+ ### Full Configuration
32
+
33
+ All available options:
34
+
35
+ ```javascript
36
+ Candy.action({
37
+ navigate: {
38
+ // Which links to intercept
39
+ links: 'a[href^="/"]', // Default: all internal links
40
+
41
+ // Which elements to update
42
+ update: {
43
+ content: 'main',
44
+ header: 'header',
45
+ sidebar: '#sidebar'
46
+ },
47
+
48
+ // Callback after navigation
49
+ on: function(page, variables) {
50
+ console.log('Navigated to:', page)
51
+ console.log('Server data:', variables)
52
+ }
53
+ }
54
+ })
55
+ ```
56
+
57
+ ## Link Selectors
58
+
59
+ ### Default Behavior
60
+
61
+ By default, all internal links (starting with `/`) are intercepted:
62
+
63
+ ```javascript
64
+ navigate: true // Uses 'a[href^="/"]'
65
+ ```
66
+
67
+ ### Custom Selectors
68
+
69
+ Target specific links:
70
+
71
+ ```javascript
72
+ navigate: {
73
+ links: 'nav a', // Only navigation links
74
+ update: 'main'
75
+ }
76
+ ```
77
+
78
+ ```javascript
79
+ navigate: {
80
+ links: 'a.ajax-link', // Only links with class
81
+ update: 'main'
82
+ }
83
+ ```
84
+
85
+ ### Excluding Links
86
+
87
+ Exclude specific links from AJAX navigation:
88
+
89
+ ```html
90
+ <!-- Using data attribute -->
91
+ <a href="/download.pdf" data-navigate="false">Download</a>
92
+
93
+ <!-- Using CSS class -->
94
+ <a href="/logout" class="no-navigate">Logout</a>
95
+ ```
96
+
97
+ Both methods work automatically - no additional configuration needed!
98
+
99
+ ## Element Updates
100
+
101
+ ### Single Element
102
+
103
+ Update one element:
104
+
105
+ ```javascript
106
+ navigate: 'main' // Shorthand
107
+ // or
108
+ navigate: {
109
+ update: 'main'
110
+ }
111
+ ```
112
+
113
+ ### Multiple Elements
114
+
115
+ Update multiple elements simultaneously:
116
+
117
+ ```javascript
118
+ navigate: {
119
+ update: {
120
+ content: 'main',
121
+ header: 'header',
122
+ sidebar: '#sidebar',
123
+ breadcrumb: '.breadcrumb'
124
+ }
125
+ }
126
+ ```
127
+
128
+ The keys (content, header, etc.) must match the view parts defined in your controller:
129
+
130
+ ```javascript
131
+ // In controller
132
+ Candy.View.set({
133
+ header: 'main',
134
+ content: 'about',
135
+ sidebar: 'main'
136
+ })
137
+ ```
138
+
139
+ ## Callbacks
140
+
141
+ ### Navigation Callback
142
+
143
+ Execute code after each navigation:
144
+
145
+ ```javascript
146
+ navigate: {
147
+ update: 'main',
148
+ on: function(page, variables) {
149
+ // page: current page name (e.g., 'about')
150
+ // variables: data from server
151
+
152
+ // Update page title
153
+ document.title = variables.title || page
154
+
155
+ // Track analytics
156
+ if (window.gtag) {
157
+ gtag('event', 'page_view', {
158
+ page_path: window.location.pathname
159
+ })
160
+ }
161
+
162
+ // Update active navigation
163
+ updateActiveNav()
164
+ }
165
+ }
166
+ ```
167
+
168
+ ### Page-Specific Actions
169
+
170
+ Run code for specific pages:
171
+
172
+ ```javascript
173
+ Candy.action({
174
+ navigate: {
175
+ update: 'main',
176
+ on: (page, vars) => console.log('Navigated to:', page)
177
+ },
178
+
179
+ page: {
180
+ index: function(variables) {
181
+ console.log('Home page loaded')
182
+ },
183
+ about: function(variables) {
184
+ console.log('About page:', variables.title)
185
+ }
186
+ }
187
+ })
188
+ ```
189
+
190
+ ## Disabling Navigation
191
+
192
+ ### Disable Completely
193
+
194
+ ```javascript
195
+ Candy.action({
196
+ navigate: false // No AJAX navigation
197
+ })
198
+ ```
199
+
200
+ ### Disable for Specific Links
201
+
202
+ ```html
203
+ <!-- Data attribute -->
204
+ <a href="/download" data-navigate="false">Download</a>
205
+
206
+ <!-- CSS class -->
207
+ <a href="/logout" class="no-navigate">Logout</a>
208
+
209
+ <!-- External links (automatic) -->
210
+ <a href="https://example.com">External</a>
211
+ ```
212
+
213
+ ## Server-Side Configuration
214
+
215
+ ### Sending Variables
216
+
217
+ In your controller, send data to the client:
218
+
219
+ ```javascript
220
+ module.exports = function(Candy) {
221
+ // Set variables for AJAX responses
222
+ Candy.set({
223
+ title: 'About Page',
224
+ user: {name: 'John', role: 'admin'},
225
+ stats: {views: 1234}
226
+ }, true) // true = include in AJAX
227
+
228
+ Candy.View.skeleton('main')
229
+ Candy.View.set({
230
+ header: 'main',
231
+ content: 'about',
232
+ footer: 'main'
233
+ })
234
+ }
235
+ ```
236
+
237
+ ### Accessing Variables
238
+
239
+ Access server variables in your callback:
240
+
241
+ ```javascript
242
+ navigate: {
243
+ update: 'main',
244
+ on: function(page, variables) {
245
+ console.log(variables.title) // 'About Page'
246
+ console.log(variables.user.name) // 'John'
247
+ console.log(variables.stats.views) // 1234
248
+ }
249
+ }
250
+ ```
251
+
252
+ ## Advanced Examples
253
+
254
+ ### Loading Indicator
255
+
256
+ Show a loading spinner during navigation:
257
+
258
+ ```javascript
259
+ Candy.action({
260
+ navigate: {
261
+ update: 'main',
262
+ on: (page, vars) => {
263
+ hideLoadingSpinner()
264
+ }
265
+ },
266
+
267
+ click: {
268
+ 'a[href^="/"]': function(e) {
269
+ if (!this.hasAttribute('data-navigate') &&
270
+ !this.classList.contains('no-navigate')) {
271
+ showLoadingSpinner()
272
+ }
273
+ }
274
+ }
275
+ })
276
+
277
+ function showLoadingSpinner() {
278
+ document.getElementById('spinner').style.display = 'block'
279
+ }
280
+
281
+ function hideLoadingSpinner() {
282
+ document.getElementById('spinner').style.display = 'none'
283
+ }
284
+ ```
285
+
286
+ ### Progress Bar
287
+
288
+ Animated progress bar:
289
+
290
+ ```javascript
291
+ let progressBar = document.getElementById('progress')
292
+
293
+ Candy.action({
294
+ navigate: {
295
+ update: 'main',
296
+ on: () => {
297
+ progressBar.style.width = '100%'
298
+ setTimeout(() => {
299
+ progressBar.style.width = '0%'
300
+ }, 300)
301
+ }
302
+ },
303
+
304
+ click: {
305
+ 'a[href^="/"]': function() {
306
+ if (!this.hasAttribute('data-navigate')) {
307
+ progressBar.style.width = '30%'
308
+ }
309
+ }
310
+ }
311
+ })
312
+ ```
313
+
314
+ ### Conditional Navigation
315
+
316
+ Confirm before navigating:
317
+
318
+ ```javascript
319
+ Candy.action({
320
+ navigate: {
321
+ update: 'main'
322
+ },
323
+
324
+ click: {
325
+ 'a[href^="/"]': function(e) {
326
+ if (hasUnsavedChanges() &&
327
+ !this.hasAttribute('data-navigate')) {
328
+ if (!confirm('You have unsaved changes. Continue?')) {
329
+ e.preventDefault()
330
+ e.stopPropagation()
331
+ }
332
+ }
333
+ }
334
+ }
335
+ })
336
+ ```
337
+
338
+ ## Best Practices
339
+
340
+ 1. **Keep it Simple**: Start with minimal configuration
341
+ 2. **Progressive Enhancement**: Ensure links work without JavaScript
342
+ 3. **Loading States**: Always show loading indicators
343
+ 4. **Error Handling**: Handle failed requests gracefully
344
+ 5. **SEO**: Ensure content is accessible to search engines
345
+ 6. **Performance**: Only update necessary elements
346
+
347
+ ## Troubleshooting
348
+
349
+ ### Links Not Working
350
+
351
+ - Check that `navigate` is enabled
352
+ - Verify link selector matches your links
353
+ - Check browser console for errors
354
+
355
+ ### Elements Not Updating
356
+
357
+ - Ensure element selectors are correct
358
+ - Verify view parts are defined in controller
359
+ - Check that skeleton has correct placeholders
360
+
361
+ ### Variables Not Available
362
+
363
+ - Confirm `Candy.set(data, true)` has `true` parameter
364
+ - Check variables are set before `View.print()`
365
+
366
+ ## Next Steps
367
+
368
+ - Learn about [Form Handling](../03-forms/01-form-handling.md)
369
+ - Explore [API Requests](../04-api-requests/01-get-post.md)
370
+ - Check [Advanced Usage](03-advanced-usage.md)