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,300 @@
1
+ # Streaming API
2
+
3
+ CandyPack provides a unified streaming API that automatically handles Server-Sent Events (SSE), with future support for WebSocket and HTTP/3.
4
+
5
+ ## Quick Start
6
+
7
+ ### Inline Route (Simple)
8
+
9
+ ```javascript
10
+ // route/www.js
11
+ Candy.Route.get('/hello', async (Candy) => {
12
+ Candy.stream('Hello World')
13
+ })
14
+ ```
15
+
16
+ ### Controller (Recommended)
17
+
18
+ ```javascript
19
+ // route/www.js
20
+ Candy.Route.get('/hello', 'hello')
21
+
22
+ // controller/hello/get/index.js
23
+ module.exports = async (Candy) => {
24
+ Candy.stream('Hello World')
25
+ }
26
+ ```
27
+
28
+ ### JSON Message
29
+
30
+ ```javascript
31
+ // controller/get/index.js
32
+ module.exports = async (Candy) => {
33
+ Candy.stream({ message: 'Hello', time: Date.now() })
34
+ }
35
+ ```
36
+
37
+ ## Multiple Messages
38
+
39
+ ### Callback Pattern
40
+
41
+ ```javascript
42
+ // controller/get/index.js
43
+ module.exports = async (Candy) => {
44
+ Candy.stream((send) => {
45
+ send({ type: 'connected' })
46
+
47
+ setInterval(() => {
48
+ send({ time: Date.now() })
49
+ }, 1000)
50
+ })
51
+ }
52
+ ```
53
+
54
+ ### With Cleanup
55
+
56
+ ```javascript
57
+ // controller/get/index.js
58
+ module.exports = async (Candy) => {
59
+ Candy.stream((send, close) => {
60
+ send({ type: 'connected' })
61
+
62
+ const interval = setInterval(() => {
63
+ send({ time: Date.now() })
64
+ }, 1000)
65
+
66
+ // Return cleanup function
67
+ return () => {
68
+ clearInterval(interval)
69
+ }
70
+ })
71
+ }
72
+ ```
73
+
74
+ ## Automatic Piping
75
+
76
+ ### Array
77
+
78
+ ```javascript
79
+ // controller/get/index.js
80
+ module.exports = async (Candy) => {
81
+ Candy.stream([1, 2, 3, 4, 5])
82
+ }
83
+ ```
84
+
85
+ ### Async Generator
86
+
87
+ ```javascript
88
+ // controller/users/get/index.js
89
+ module.exports = async (Candy) => {
90
+ Candy.stream(async function* () {
91
+ const users = await Candy.Mysql.table('users').get()
92
+
93
+ for (const user of users) {
94
+ yield user
95
+ }
96
+ })
97
+ }
98
+ ```
99
+
100
+ ### Promise
101
+
102
+ ```javascript
103
+ // controller/app/get/index.js
104
+ module.exports = async (Candy) => {
105
+ Candy.stream(
106
+ fetch('https://api.example.com/data')
107
+ .then(r => r.json())
108
+ )
109
+ }
110
+ ```
111
+
112
+ ### Node.js Stream
113
+
114
+ ```javascript
115
+ // controller/file/get/index.js
116
+ module.exports = async (Candy) => {
117
+ const fs = require('fs')
118
+ Candy.stream(fs.createReadStream('large-file.txt'))
119
+ }
120
+ ```
121
+
122
+ ## Advanced Usage
123
+
124
+ ### Full Control
125
+
126
+ ```javascript
127
+ // controller/monitor/get/index.js
128
+ module.exports = async (Candy) => {
129
+ const stream = Candy.stream()
130
+
131
+ stream.send({ type: 'connected' })
132
+
133
+ const interval = setInterval(() => {
134
+ stream.send({ time: Date.now() })
135
+ }, 1000)
136
+
137
+ stream.on('close', () => {
138
+ clearInterval(interval)
139
+ })
140
+ }
141
+ ```
142
+
143
+ ### Error Handling
144
+
145
+ ```javascript
146
+ // controller/data/get/fetch.js
147
+ module.exports = async (Candy) => {
148
+ const stream = Candy.stream()
149
+
150
+ try {
151
+ const data = await fetchData()
152
+ stream.send(data)
153
+ } catch (error) {
154
+ stream.error(error.message)
155
+ }
156
+ }
157
+ ```
158
+
159
+ ## Real-World Examples
160
+
161
+ ### Real-time Logs
162
+
163
+ ```javascript
164
+ // route/www.js
165
+ Candy.Route.get('/logs', 'logs')
166
+
167
+ // controller/logs/get/index.js
168
+ module.exports = async (Candy) => {
169
+ Candy.stream(async function* () {
170
+ const logStream = await getDeploymentLogs()
171
+
172
+ for await (const log of logStream) {
173
+ yield {
174
+ timestamp: Date.now(),
175
+ message: log
176
+ }
177
+ }
178
+ })
179
+ }
180
+ ```
181
+
182
+ ### Database Pagination
183
+
184
+ ```javascript
185
+ // route/www.js
186
+ Candy.Route.get('/posts', 'posts')
187
+
188
+ // controller/posts/get/index.js
189
+ module.exports = async (Candy) => {
190
+ Candy.stream(async function* () {
191
+ let page = 1
192
+ let hasMore = true
193
+
194
+ while (hasMore) {
195
+ const posts = await Candy.Mysql.table('posts')
196
+ .limit(10)
197
+ .offset((page - 1) * 10)
198
+ .get()
199
+
200
+ if (posts.length === 0) {
201
+ hasMore = false
202
+ } else {
203
+ for (const post of posts) {
204
+ yield post
205
+ }
206
+ page++
207
+ }
208
+ }
209
+ })
210
+ }
211
+ ```
212
+
213
+ ## Client-Side Usage
214
+
215
+ ### JavaScript
216
+
217
+ ```javascript
218
+ const eventSource = new EventSource('/events')
219
+
220
+ eventSource.onmessage = (event) => {
221
+ const data = JSON.parse(event.data)
222
+ console.log(data)
223
+ }
224
+
225
+ eventSource.onerror = (error) => {
226
+ console.error('Connection error:', error)
227
+ }
228
+
229
+ // Close connection
230
+ eventSource.close()
231
+ ```
232
+
233
+ ### React Hook
234
+
235
+ ```javascript
236
+ import { useEffect, useState } from 'react'
237
+
238
+ function useStream(url) {
239
+ const [data, setData] = useState(null)
240
+
241
+ useEffect(() => {
242
+ const eventSource = new EventSource(url)
243
+
244
+ eventSource.onmessage = (event) => {
245
+ setData(JSON.parse(event.data))
246
+ }
247
+
248
+ return () => eventSource.close()
249
+ }, [url])
250
+
251
+ return data
252
+ }
253
+
254
+ // Usage
255
+ function Dashboard() {
256
+ const status = useStream('/auth/listen')
257
+
258
+ return <div>{status?.message}</div>
259
+ }
260
+ ```
261
+
262
+ ## Protocol
263
+
264
+ CandyPack uses **Server-Sent Events (SSE)** for streaming:
265
+ - ✅ One-way communication (server → client)
266
+ - ✅ Automatic reconnection
267
+ - ✅ Works over HTTP/2
268
+ - ✅ No extra ports needed
269
+
270
+ ## Technical Details
271
+
272
+ - **Protocol:** HTTP/2 compatible
273
+ - **Port:** Standard HTTPS (443)
274
+ - **Heartbeat:** Automatic (every 30 seconds)
275
+ - **Reconnection:** Automatic (browser handles)
276
+ - **Compression:** Supported via HTTP/2
277
+
278
+ ## Best Practices
279
+
280
+ 1. **Always handle cleanup:** Use the cleanup function or `stream.on('close')`
281
+ 2. **Throttle messages:** Don't send too frequently (use intervals)
282
+ 3. **Handle errors:** Use try-catch and `stream.error()`
283
+ 4. **Close when done:** Call `stream.close()` when finished
284
+ 5. **Test reconnection:** Ensure your app handles connection drops
285
+
286
+ ## Troubleshooting
287
+
288
+ **Connection drops immediately:**
289
+ - Check if you're calling `Candy.return()` or `res.end()`
290
+ - Don't use both streaming and regular responses
291
+
292
+ **Messages not received:**
293
+ - Verify JSON format
294
+ - Check browser console for errors
295
+ - Ensure CORS headers if cross-origin
296
+
297
+ **High memory usage:**
298
+ - Limit number of concurrent connections
299
+ - Implement cleanup properly
300
+ - Use throttling for frequent updates