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
@@ -59,8 +59,8 @@ class Mysql {
59
59
 
60
60
  async #define(table) {
61
61
  return new Promise(resolve => {
62
- if (!Candy.Mysql.db[this.#database]) Candy.Mysql.db[this.#database] = {}
63
- this.#table[table] = Candy.Mysql.db[this.#database][table]
62
+ if (!Odac.Mysql.db[this.#database]) Odac.Mysql.db[this.#database] = {}
63
+ this.#table[table] = Odac.Mysql.db[this.#database][table]
64
64
  if (this.#table[table]) {
65
65
  this.#defining = false
66
66
  return resolve(true)
@@ -81,7 +81,7 @@ class Mysql {
81
81
  }
82
82
  if (!this.#table[table]) this.#table[table] = {}
83
83
  this.#table[table].columns = columns
84
- Candy.Mysql.db[this.#database][table] = this.#table[table]
84
+ Odac.Mysql.db[this.#database][table] = this.#table[table]
85
85
  this.#defining = false
86
86
  return resolve(true)
87
87
  })
@@ -98,11 +98,11 @@ class Mysql {
98
98
  }
99
99
 
100
100
  #error(err, query) {
101
- err = 'CandyPack Mysql Error: ' + (err?.message ?? 'Unknown error').trim() + '\n'
101
+ err = 'Odac Mysql Error: ' + (err?.message ?? 'Unknown error').trim() + '\n'
102
102
  if (query) err += 'Query: ' + query + '\n'
103
103
  while (this.#stack.length > 0) {
104
104
  let line = this.#stack.shift().replace('at', '')
105
- if (line.includes('/node_modules/candypack/framework/src/')) break
105
+ if (line.includes('/node_modules/odac/framework/src/')) break
106
106
  else if (!line.includes('(node:')) err += line + '\n'
107
107
  }
108
108
  console.error(err)
@@ -163,7 +163,7 @@ class Mysql {
163
163
  // $md5_query = md5($query);
164
164
  // $md5_table = md5($this->arr['table']);
165
165
  // $file = "cache/mysql/".md5(Mysql::$name)."/$md5_table"."_$md5_query";
166
- // $cache = Candy::storage($file)->get('cache');
166
+ // $cache = Odac::storage($file)->get('cache');
167
167
  // if(isset($cache->date) && ($cache->date >= (time() - $this->arr['cache']))) return $cache->data;
168
168
  // }
169
169
  let query = this.query('get')
@@ -182,7 +182,7 @@ class Mysql {
182
182
  // if(isset($cache)){
183
183
  // $cache->data = $data;
184
184
  // $cache->date = time();
185
- // Candy::storage($file)->set('cache', $cache);
185
+ // Odac::storage($file)->set('cache', $cache);
186
186
  // }
187
187
  return data
188
188
  }
@@ -244,7 +244,7 @@ class Mysql {
244
244
  // $md5_query = md5($query);
245
245
  // $md5_table = md5($this->arr['table']);
246
246
  // $file = "cache/mysql/".md5(Mysql::$name)."/$md5_table"."_$md5_query"."_r";
247
- // $cache = Candy::storage($file)->get('cache');
247
+ // $cache = Odac::storage($file)->get('cache');
248
248
  // if(isset($cache->date) && ($cache->date >= (time() - $this->arr['cache']))) return $cache->data;
249
249
  // }
250
250
  let query = this.query('get')
@@ -254,7 +254,7 @@ class Mysql {
254
254
  // if(isset($cache)){
255
255
  // $cache->data = $rows;
256
256
  // $cache->date = time();
257
- // Candy::storage($file)->set('cache', $cache);
257
+ // Odac::storage($file)->set('cache', $cache);
258
258
  // }
259
259
  return rows
260
260
  }
@@ -263,7 +263,7 @@ class Mysql {
263
263
  return new Promise(resolve => {
264
264
  if (!query) return resolve(false)
265
265
  if (!this.#conn) return resolve(false)
266
- if (this.#conn.state == 'disconnected') Candy.Mysql.init()
266
+ if (this.#conn.state == 'disconnected') Odac.Mysql.init()
267
267
  const args = params ? [query, params] : [query]
268
268
  args.push((err, result) => {
269
269
  if (err) return resolve(this.#error(err, query))
@@ -309,7 +309,7 @@ class Mysql {
309
309
 
310
310
  groupBy(...args) {
311
311
  this.#arr['group by'] = this.#arr['group by'] ?? ''
312
- let select = this.#arr['group by'].split(',')
312
+ let select = this.#arr['group by'] ? this.#arr['group by'].split(',') : []
313
313
  // if(count(func_get_args())==1 && is_array(func_get_args()[0])){
314
314
  // if(isset(func_get_args()[0]['ct']) && isset(func_get_args()[0]['v']) && func_get_args()[0]['ct'] == $GLOBALS['candy_token_mysql']){
315
315
  // $select[] = func_get_args()[0]['v'];
@@ -407,33 +407,33 @@ class Mysql {
407
407
  break
408
408
  } else if (!this.#arr.select) {
409
409
  continue
410
- } else if (Candy.Var(this.#arr.select).contains(' AS "' + col + '"')) {
410
+ } else if (Odac.Var(this.#arr.select).contains(' AS "' + col + '"')) {
411
411
  // $exp = explode(' ,',explode(" AS \"$col\"",$this->arr['select'])[0]);
412
- // $real_col = explode('.',Candy::var(trim(end($exp)))->clear('`'));
412
+ // $real_col = explode('.',Odac::var(trim(end($exp)))->clear('`'));
413
413
  // $real_table = trim($real_col[0]);
414
414
  // $real_col = trim($real_col[1]);
415
415
  // $this->types[$col] = $this->types[$col] = $this->table[$real_table]['columns'][$real_col]['Type'] ?? $this->types[$col];
416
416
  break
417
- } else if (Candy.Var(this.#arr.select).containsAny(' `' + col + '`', ' `' + key + '`.`' + col + '`')) {
417
+ } else if (Odac.Var(this.#arr.select).containsAny(' `' + col + '`', ' `' + key + '`.`' + col + '`')) {
418
418
  this.types[col] = this.#table[key].columns[col].Type ?? this.types[col]
419
419
  }
420
420
  }
421
421
  }
422
422
  if (action == 'decode') {
423
- if (Candy.Var(this.types[col]).isBegin('tinyint(1)')) value = value ? true : false
424
- else if (Candy.Var(this.types[col]).isBegin('int')) value = parseInt(value)
425
- else if (Candy.Var(this.types[col]).isBegin('double')) value = parseFloat(value)
426
- else if (Candy.Var(this.types[col]).isBegin('float')) value = parseFloat(value)
427
- else if (Candy.Var(this.types[col]).isBegin('boolean')) value = parseInt(value)
428
- else if (Candy.Var(this.types[col]).isBegin('json')) value = JSON.parse(value)
423
+ if (Odac.Var(this.types[col]).isBegin('tinyint(1)')) value = value ? true : false
424
+ else if (Odac.Var(this.types[col]).isBegin('int')) value = parseInt(value)
425
+ else if (Odac.Var(this.types[col]).isBegin('double')) value = parseFloat(value)
426
+ else if (Odac.Var(this.types[col]).isBegin('float')) value = parseFloat(value)
427
+ else if (Odac.Var(this.types[col]).isBegin('boolean')) value = parseInt(value)
428
+ else if (Odac.Var(this.types[col]).isBegin('json')) value = JSON.parse(value)
429
429
  } else if (!(value instanceof Raw)) {
430
- if (Candy.Var(this.types[col]).isBegin('tinyint(1)')) value = parseInt(value)
431
- else if (Candy.Var(this.types[col]).isBegin('int')) value = parseInt(value)
432
- else if (Candy.Var(this.types[col]).isBegin('double')) value = parseFloat(value)
433
- else if (Candy.Var(this.types[col]).isBegin('float')) value = parseFloat(value)
434
- else if (Candy.Var(this.types[col]).isBegin('boolean')) value = parseInt(value)
435
- else if (Candy.Var(this.types[col]).isBegin('json')) value = JSON.stringify(value)
436
- else if (Candy.Var(this.types[col]).isBegin('date', 'datetime', 'timestamp')) value = Candy.Var(value).date('Y-m-d H:i:s')
430
+ if (Odac.Var(this.types[col]).isBegin('tinyint(1)')) value = parseInt(value)
431
+ else if (Odac.Var(this.types[col]).isBegin('int')) value = parseInt(value)
432
+ else if (Odac.Var(this.types[col]).isBegin('double')) value = parseFloat(value)
433
+ else if (Odac.Var(this.types[col]).isBegin('float')) value = parseFloat(value)
434
+ else if (Odac.Var(this.types[col]).isBegin('boolean')) value = parseInt(value)
435
+ else if (Odac.Var(this.types[col]).isBegin('json')) value = JSON.stringify(value)
436
+ else if (Odac.Var(this.types[col]).isBegin('date', 'datetime', 'timestamp')) value = Odac.Var(value).date('Y-m-d H:i:s')
437
437
  }
438
438
  return value
439
439
  }
@@ -513,22 +513,22 @@ module.exports = {
513
513
  db: {},
514
514
  init: function () {
515
515
  return new Promise(resolve => {
516
- if (!Candy.Config.database) return resolve(false)
517
- let multiple = typeof Candy.Config.database[Object.keys(Candy.Config.database)[0]] === 'object'
518
- let dbs = multiple ? Candy.Config.database : {default: Candy.Config.database}
516
+ if (!Odac.Config.database) return resolve(false)
517
+ let multiple = typeof Odac.Config.database[Object.keys(Odac.Config.database)[0]] === 'object'
518
+ let dbs = multiple ? Odac.Config.database : {default: Odac.Config.database}
519
519
  for (let key of Object.keys(dbs)) {
520
520
  let db = dbs[key]
521
521
  if (db.type && db.type != 'mysql') continue
522
- Candy.Mysql.conn[key] = mysql.createConnection({
522
+ Odac.Mysql.conn[key] = mysql.createConnection({
523
523
  host: db.host ?? '127.0.0.1',
524
524
  user: db.user,
525
525
  password: db.password,
526
526
  database: db.database,
527
527
  stringifyObjects: true
528
528
  })
529
- Candy.Mysql.conn[key].connect(err => {
529
+ Odac.Mysql.conn[key].connect(err => {
530
530
  if (err) {
531
- console.error(`CandyPack Mysql Error: Failed to connect to database '${key}'`)
531
+ console.error(`Odac Mysql Error: Failed to connect to database '${key}'`)
532
532
  console.error(`Host: ${db.host ?? '127.0.0.1'}`)
533
533
  console.error(`User: ${db.user}`)
534
534
  console.error(`Database: ${db.database}`)
@@ -536,16 +536,16 @@ module.exports = {
536
536
  return resolve(false)
537
537
  }
538
538
  })
539
- Candy.Mysql.conn[key].query('SHOW TABLES', (err, result) => {
539
+ Odac.Mysql.conn[key].query('SHOW TABLES', (err, result) => {
540
540
  if (err) {
541
- console.error(`CandyPack Mysql Error: Failed to query tables from database '${key}'`)
541
+ console.error(`Odac Mysql Error: Failed to query tables from database '${key}'`)
542
542
  console.error(`Error: ${err.message}`)
543
543
  return resolve(false)
544
544
  }
545
545
  for (let table of result)
546
546
  for (let key of Object.keys(table)) {
547
547
  let t = () => {
548
- new Mysql(table[key], Candy.Mysql.conn['default'])
548
+ new Mysql(table[key], Odac.Mysql.conn['default'])
549
549
  }
550
550
  t()
551
551
  }
@@ -555,16 +555,16 @@ module.exports = {
555
555
  })
556
556
  },
557
557
  database: function (name) {
558
- if (!Candy.Mysql.conn[name]) return null
559
- return new Mysql(name, Candy.Mysql.conn[name])
558
+ if (!Odac.Mysql.conn[name]) return null
559
+ return new Mysql(name, Odac.Mysql.conn[name])
560
560
  },
561
561
  run: function (query, params) {
562
- if (!Candy.Mysql.conn['default']) return Promise.resolve(false)
563
- return new Mysql(null, Candy.Mysql.conn['default']).run(query, params)
562
+ if (!Odac.Mysql.conn['default']) return Promise.resolve(false)
563
+ return new Mysql(null, Odac.Mysql.conn['default']).run(query, params)
564
564
  },
565
565
  table: function (name) {
566
- if (!Candy.Mysql.conn['default']) return null
567
- return new Mysql(name, Candy.Mysql.conn['default'])
566
+ if (!Odac.Mysql.conn['default']) return null
567
+ return new Mysql(name, Odac.Mysql.conn['default'])
568
568
  },
569
569
  raw: function (query) {
570
570
  if (typeof query !== 'string') {
package/src/Odac.js ADDED
@@ -0,0 +1,112 @@
1
+ module.exports = {
2
+ init: async function () {
3
+ global.Odac = this.instance()
4
+ await global.Odac.Env.init()
5
+ await global.Odac.Config.init()
6
+ await global.Odac.Mysql.init()
7
+ await global.Odac.Route.init()
8
+ await global.Odac.Server.init()
9
+ global.Odac.instance = this.instance
10
+ global.__ = value => {
11
+ return value
12
+ }
13
+ },
14
+
15
+ instance(id, req, res) {
16
+ let _odac = {}
17
+
18
+ _odac.Config = require('./Config.js')
19
+ _odac.Env = require('./Env.js')
20
+ _odac.Mail = (...args) => new (require('./Mail.js'))(...args)
21
+ _odac.Mysql = require('./Mysql.js')
22
+ _odac.Route = global.Odac?.Route ?? new (require('./Route.js'))()
23
+ _odac.Server = require('./Server.js')
24
+ _odac.Var = (...args) => new (require('./Var.js'))(...args)
25
+
26
+ if (req) {
27
+ _odac.Request = new (require('./Request.js'))(id, req, res, _odac)
28
+ _odac.Auth = new (require('./Auth.js'))(_odac.Request)
29
+ _odac.Token = new (require('./Token.js'))(_odac.Request)
30
+ _odac.Lang = new (require('./Lang.js'))(_odac)
31
+ if (res) {
32
+ _odac.View = new (require('./View.js'))(_odac)
33
+ }
34
+
35
+ _odac._intervals = []
36
+ _odac._timeouts = []
37
+ _odac.setInterval = function (callback, delay, ...args) {
38
+ const id = setInterval(callback, delay, ...args)
39
+ _odac._intervals.push(id)
40
+ return id
41
+ }
42
+ _odac.setTimeout = function (callback, delay, ...args) {
43
+ const id = setTimeout(callback, delay, ...args)
44
+ _odac._timeouts.push(id)
45
+ return id
46
+ }
47
+ _odac.clearInterval = function (id) {
48
+ const index = _odac._intervals.indexOf(id)
49
+ if (index > -1) _odac._intervals.splice(index, 1)
50
+ clearInterval(id)
51
+ }
52
+ _odac.clearTimeout = function (id) {
53
+ const index = _odac._timeouts.indexOf(id)
54
+ if (index > -1) _odac._timeouts.splice(index, 1)
55
+ clearTimeout(id)
56
+ }
57
+ _odac.cleanup = function () {
58
+ for (const id of _odac._intervals) clearInterval(id)
59
+ for (const id of _odac._timeouts) clearTimeout(id)
60
+ _odac._intervals = []
61
+ _odac._timeouts = []
62
+ }
63
+
64
+ if (global.Odac?.Route?.class) {
65
+ for (const name in global.Odac.Route.class) {
66
+ const Module = global.Odac.Route.class[name].module
67
+ _odac[name] = typeof Module === 'function' ? new Module(_odac) : Module
68
+ }
69
+ }
70
+
71
+ _odac.__ = function (...args) {
72
+ return _odac.Lang.get(...args)
73
+ }
74
+ _odac.abort = function (code) {
75
+ return _odac.Request.abort(code)
76
+ }
77
+ _odac.cookie = function (key, value, options) {
78
+ return _odac.Request.cookie(key, value, options)
79
+ }
80
+ _odac.direct = function (url) {
81
+ return _odac.Request.redirect(url)
82
+ }
83
+ _odac.env = function (key, defaultValue) {
84
+ return _odac.Env.get(key, defaultValue)
85
+ }
86
+ _odac.return = function (data) {
87
+ return _odac.Request.end(data)
88
+ }
89
+ _odac.request = function (key) {
90
+ return _odac.Request.request(key)
91
+ }
92
+ _odac.set = function (key, value) {
93
+ return _odac.Request.set(key, value)
94
+ }
95
+ _odac.token = function (hash) {
96
+ return hash ? _odac.Token.check(hash) : _odac.Token.generate()
97
+ }
98
+ _odac.validator = function () {
99
+ return new (require('./Validator.js'))(_odac.Request)
100
+ }
101
+ _odac.write = function (value) {
102
+ return _odac.Request.write(value)
103
+ }
104
+ _odac.stream = function (input) {
105
+ _odac.Request.clearTimeout()
106
+ return new (require('./Stream'))(_odac.Request.req, _odac.Request.res, input, _odac)
107
+ }
108
+ }
109
+
110
+ return _odac
111
+ }
112
+ }
@@ -1,12 +1,12 @@
1
1
  const nodeCrypto = require('crypto')
2
2
 
3
- class CandyRequest {
4
- #candy
3
+ class OdacRequest {
4
+ #odac
5
5
  #complete = false
6
6
  #cookies = {received: [], sent: []}
7
7
  data = {post: {}, get: {}, url: {}}
8
8
  #event = {data: [], end: []}
9
- #headers = {Server: 'CandyPack'}
9
+ #headers = {Server: 'Odac'}
10
10
  #status = 200
11
11
  #timeout = null
12
12
  #earlyHints = null
@@ -16,30 +16,32 @@ class CandyRequest {
16
16
  clientSkeleton = null
17
17
  page = null
18
18
 
19
- constructor(id, req, res, candy) {
19
+ constructor(id, req, res, odac) {
20
20
  this.id = id
21
21
  this.req = req
22
22
  this.res = res
23
- this.#candy = candy
23
+ this.#odac = odac
24
24
  this.method = req.method.toLowerCase()
25
25
  this.url = req.url
26
26
  this.host = req.headers.host
27
- this.ssl = this.header('x-candy-connection-ssl') === 'true'
28
- this.ip = (this.header('x-candy-connection-remoteaddress') ?? req.connection.remoteAddress).replace('::ffff:', '')
29
- delete this.req.headers['x-candy-connection-ssl']
30
- delete this.req.headers['x-candy-connection-remoteaddress']
27
+ this.ssl = this.header('x-odac-connection-ssl') === 'true'
28
+ this.ip = (this.header('x-odac-connection-remoteaddress') ?? req.connection.remoteAddress).replace('::ffff:', '')
29
+ delete this.req.headers['x-odac-connection-ssl']
30
+ delete this.req.headers['x-odac-connection-remoteaddress']
31
31
  let route = req.headers.host.split('.')[0]
32
- if (!Candy.Route.routes[route]) route = 'www'
32
+ if (!Odac.Route.routes[route]) route = 'www'
33
33
  this.route = route
34
- this.#timeout = setTimeout(() => !this.res.finished && this.abort(408), Candy.Config.request.timeout)
34
+ if (this.res) {
35
+ this.#timeout = setTimeout(() => !this.res.finished && this.abort(408), Odac.Config.request.timeout)
36
+ }
35
37
  this.#data()
36
- if (!Candy.Request) Candy.Request = {}
37
- if (!this.cookie('candy_client') || !this.session('_client') || this.session('_client') !== this.cookie('candy_client')) {
38
+ if (!Odac.Request) Odac.Request = {}
39
+ if (!this.cookie('odac_client') || !this.session('_client') || this.session('_client') !== this.cookie('odac_client')) {
38
40
  let client = nodeCrypto
39
41
  .createHash('md5')
40
42
  .update(this.ip + this.id + Date.now().toString() + Math.random().toString())
41
43
  .digest('hex')
42
- this.cookie('candy_client', client, {expires: null, httpOnly: false})
44
+ this.cookie('odac_client', client, {expires: null, httpOnly: false})
43
45
  this.session('_client', client)
44
46
  }
45
47
  }
@@ -48,8 +50,8 @@ class CandyRequest {
48
50
  async abort(code) {
49
51
  this.status(code)
50
52
  let result = {401: 'Unauthorized', 404: 'Not Found', 408: 'Request Timeout'}[code] ?? null
51
- if (Candy.Route.routes[this.route].error && Candy.Route.routes[this.route].error[code])
52
- result = await Candy.Route.routes[this.route].error[code].cache(this.#candy)
53
+ if (Odac.Route.routes[this.route].error && Odac.Route.routes[this.route].error[code])
54
+ result = await Odac.Route.routes[this.route].error[code].cache(this.#odac)
53
55
  this.end(result)
54
56
  }
55
57
 
@@ -179,8 +181,8 @@ class CandyRequest {
179
181
  print() {
180
182
  if (this.res.headersSent) return
181
183
 
182
- if (this.#earlyHints && this.#earlyHints.length > 0 && global.Candy?.View?.EarlyHints) {
183
- global.Candy.View.EarlyHints.send(this.res, this.#earlyHints)
184
+ if (this.#earlyHints && this.#earlyHints.length > 0 && global.Odac?.View?.EarlyHints) {
185
+ global.Odac.View.EarlyHints.send(this.res, this.#earlyHints)
184
186
  }
185
187
 
186
188
  this.#headers['Set-Cookie'] = this.#cookies.sent
@@ -225,8 +227,8 @@ class CandyRequest {
225
227
 
226
228
  // - SESSION
227
229
  session(key, value) {
228
- if (!Candy.Request.session) Candy.Request.session = {}
229
- if (!Candy.Request.sessionLocks) Candy.Request.sessionLocks = {}
230
+ if (!Odac.Request.session) Odac.Request.session = {}
231
+ if (!Odac.Request.sessionLocks) Odac.Request.sessionLocks = {}
230
232
 
231
233
  let pri = nodeCrypto
232
234
  .createHash('md5')
@@ -234,45 +236,45 @@ class CandyRequest {
234
236
  .digest('hex')
235
237
  let pub = this.cookie('candy_session')
236
238
 
237
- if (!pub || !Candy.Request.session[pub + '-' + pri]) {
239
+ if (!pub || !Odac.Request.session[pub + '-' + pri]) {
238
240
  const lockKey = `${this.ip}-${pri}`
239
241
  const now = Date.now()
240
242
 
241
- if (Candy.Request.sessionLocks[lockKey]) {
242
- const lock = Candy.Request.sessionLocks[lockKey]
243
- if (now - lock.timestamp < 5000 && Candy.Request.session[`${lock.sessionId}-${pri}`]) {
243
+ if (Odac.Request.sessionLocks[lockKey]) {
244
+ const lock = Odac.Request.sessionLocks[lockKey]
245
+ if (now - lock.timestamp < 5000 && Odac.Request.session[`${lock.sessionId}-${pri}`]) {
244
246
  pub = lock.sessionId
245
247
  } else {
246
- delete Candy.Request.sessionLocks[lockKey]
248
+ delete Odac.Request.sessionLocks[lockKey]
247
249
  }
248
250
  }
249
251
 
250
252
  if (!pub) {
251
- const sessionLockValues = Object.values(Candy.Request.sessionLocks)
253
+ const sessionLockValues = Object.values(Odac.Request.sessionLocks)
252
254
  const activeSessions = new Set(sessionLockValues.map(l => l.sessionId))
253
255
  do {
254
256
  pub = nodeCrypto
255
257
  .createHash('md5')
256
258
  .update(this.ip + this.id + Date.now().toString() + Math.random().toString())
257
259
  .digest('hex')
258
- } while (Candy.Request.session[`${pub}-${pri}`] || activeSessions.has(pub))
260
+ } while (Odac.Request.session[`${pub}-${pri}`] || activeSessions.has(pub))
259
261
 
260
- Candy.Request.sessionLocks[lockKey] = {sessionId: pub, timestamp: now}
261
- Candy.Request.session[`${pub}-${pri}`] = {}
262
+ Odac.Request.sessionLocks[lockKey] = {sessionId: pub, timestamp: now}
263
+ Odac.Request.session[`${pub}-${pri}`] = {}
262
264
  this.cookie('candy_session', `${pub}`)
263
265
 
264
266
  setTimeout(() => {
265
- if (Candy.Request.sessionLocks[lockKey]?.timestamp === now) {
266
- delete Candy.Request.sessionLocks[lockKey]
267
+ if (Odac.Request.sessionLocks[lockKey]?.timestamp === now) {
268
+ delete Odac.Request.sessionLocks[lockKey]
267
269
  }
268
270
  }, 5000)
269
271
  }
270
272
  }
271
273
 
272
- if (!Candy.Request.session[pub + '-' + pri]) Candy.Request.session[pub + '-' + pri] = {}
273
- if (value === undefined) return Candy.Request.session[pub + '-' + pri][key] ?? null
274
- else if (value === null) delete Candy.Request.session[pub + '-' + pri][key]
275
- else Candy.Request.session[pub + '-' + pri][key] = value
274
+ if (!Odac.Request.session[pub + '-' + pri]) Odac.Request.session[pub + '-' + pri] = {}
275
+ if (value === undefined) return Odac.Request.session[pub + '-' + pri][key] ?? null
276
+ else if (value === null) delete Odac.Request.session[pub + '-' + pri][key]
277
+ else Odac.Request.session[pub + '-' + pri][key] = value
276
278
  }
277
279
 
278
280
  // - SET
@@ -298,4 +300,4 @@ class CandyRequest {
298
300
  }
299
301
  }
300
302
 
301
- module.exports = CandyRequest
303
+ module.exports = OdacRequest