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
@@ -108,19 +108,19 @@ describe('Mail Module', () => {
108
108
  result: jest.fn((success, data) => ({success, data}))
109
109
  }
110
110
 
111
- // Setup global Candy mocks
112
- global.Candy.setMock('core', 'Config', mockConfig)
113
- global.Candy.setMock('server', 'DNS', mockDNS)
114
- global.Candy.setMock('server', 'Api', mockApi)
115
- global.Candy.setMock('server', 'Log', {
111
+ // Setup global Odac mocks
112
+ global.Odac.setMock('core', 'Config', mockConfig)
113
+ global.Odac.setMock('server', 'DNS', mockDNS)
114
+ global.Odac.setMock('server', 'Api', mockApi)
115
+ global.Odac.setMock('server', 'Log', {
116
116
  init: jest.fn().mockReturnValue({
117
117
  log: jest.fn(),
118
118
  error: jest.fn()
119
119
  })
120
120
  })
121
121
 
122
- // Setup Candy.core mock
123
- jest.spyOn(global.Candy, 'core').mockImplementation(name => {
122
+ // Setup Odac.core mock
123
+ jest.spyOn(global.Odac, 'core').mockImplementation(name => {
124
124
  if (name === 'Config') return mockConfig
125
125
  return {init: jest.fn()}
126
126
  })
@@ -225,7 +225,7 @@ describe('Mail Module', () => {
225
225
  Mail.check()
226
226
 
227
227
  // Assert
228
- expect(fs.mkdirSync).toHaveBeenCalledWith('/home/user/.candypack/cert/dkim', {recursive: true})
228
+ expect(fs.mkdirSync).toHaveBeenCalledWith('/home/user/.odac/cert/dkim', {recursive: true})
229
229
  })
230
230
 
231
231
  test('should write DKIM private and public keys to files', () => {
@@ -234,11 +234,11 @@ describe('Mail Module', () => {
234
234
 
235
235
  // Assert
236
236
  expect(fs.writeFileSync).toHaveBeenCalledWith(
237
- '/home/user/.candypack/cert/dkim/example.com.key',
237
+ '/home/user/.odac/cert/dkim/example.com.key',
238
238
  '-----BEGIN PRIVATE KEY-----\nmock-private-key\n-----END PRIVATE KEY-----'
239
239
  )
240
240
  expect(fs.writeFileSync).toHaveBeenCalledWith(
241
- '/home/user/.candypack/cert/dkim/example.com.pub',
241
+ '/home/user/.odac/cert/dkim/example.com.pub',
242
242
  '-----BEGIN PUBLIC KEY-----\nmock-public-key\n-----END PUBLIC KEY-----'
243
243
  )
244
244
  })
@@ -250,8 +250,8 @@ describe('Mail Module', () => {
250
250
  // Assert
251
251
  expect(mockConfig.config.websites['example.com'].cert).toEqual({
252
252
  dkim: {
253
- private: '/home/user/.candypack/cert/dkim/example.com.key',
254
- public: '/home/user/.candypack/cert/dkim/example.com.pub'
253
+ private: '/home/user/.odac/cert/dkim/example.com.key',
254
+ public: '/home/user/.odac/cert/dkim/example.com.pub'
255
255
  }
256
256
  })
257
257
  })
@@ -309,8 +309,8 @@ describe('Mail Module', () => {
309
309
 
310
310
  // Assert
311
311
  expect(forge.pki.rsa.generateKeyPair).toHaveBeenCalledTimes(2)
312
- expect(fs.writeFileSync).toHaveBeenCalledWith('/home/user/.candypack/cert/dkim/example.com.key', expect.any(String))
313
- expect(fs.writeFileSync).toHaveBeenCalledWith('/home/user/.candypack/cert/dkim/test.com.key', expect.any(String))
312
+ expect(fs.writeFileSync).toHaveBeenCalledWith('/home/user/.odac/cert/dkim/example.com.key', expect.any(String))
313
+ expect(fs.writeFileSync).toHaveBeenCalledWith('/home/user/.odac/cert/dkim/test.com.key', expect.any(String))
314
314
  })
315
315
  })
316
316
 
@@ -759,7 +759,7 @@ describe('Mail Module', () => {
759
759
  expect.objectContaining({
760
760
  logger: true,
761
761
  secure: false,
762
- banner: 'CandyPack',
762
+ banner: 'Odac',
763
763
  size: 1024 * 1024 * 10,
764
764
  authOptional: true
765
765
  })
@@ -789,7 +789,7 @@ describe('Mail Module', () => {
789
789
  expect.objectContaining({
790
790
  logger: true,
791
791
  secure: false,
792
- banner: 'CandyPack'
792
+ banner: 'Odac'
793
793
  })
794
794
  )
795
795
 
@@ -813,7 +813,7 @@ describe('Mail Module', () => {
813
813
  Mail.init()
814
814
 
815
815
  // Assert
816
- expect(sqlite3.verbose().Database).toHaveBeenCalledWith('/home/user/.candypack/db/mail', expect.any(Function))
816
+ expect(sqlite3.verbose().Database).toHaveBeenCalledWith('/home/user/.odac/db/mail', expect.any(Function))
817
817
  })
818
818
 
819
819
  test('should create mail database tables on initialization', () => {
@@ -867,7 +867,7 @@ describe('Mail Module', () => {
867
867
 
868
868
  // Mock error logging
869
869
  const mockError = jest.fn()
870
- global.Candy.setMock('server', 'Log', {
870
+ global.Odac.setMock('server', 'Log', {
871
871
  init: jest.fn().mockReturnValue({
872
872
  log: jest.fn(),
873
873
  error: mockError
@@ -893,7 +893,7 @@ describe('Mail Module', () => {
893
893
  Mail.init()
894
894
 
895
895
  // Assert
896
- expect(fs.mkdirSync).toHaveBeenCalledWith('/home/user/.candypack/db', {recursive: true})
896
+ expect(fs.mkdirSync).toHaveBeenCalledWith('/home/user/.odac/db', {recursive: true})
897
897
  })
898
898
 
899
899
  test('should not initialize if no domains have MX records', () => {
@@ -918,7 +918,7 @@ describe('Mail Module', () => {
918
918
  test('should handle SMTP server errors', () => {
919
919
  // Arrange
920
920
  const mockError = jest.fn()
921
- global.Candy.setMock('server', 'Log', {
921
+ global.Odac.setMock('server', 'Log', {
922
922
  init: jest.fn().mockReturnValue({
923
923
  log: mockError,
924
924
  error: jest.fn()
@@ -6,7 +6,7 @@ const selfsigned = require('selfsigned')
6
6
  // Import test utilities
7
7
  const {setupGlobalMocks, cleanupGlobalMocks} = require('./__mocks__/testHelpers')
8
8
  const {createMockWebsiteConfig} = require('./__mocks__/testFactories')
9
- const {mockCandy} = require('./__mocks__/globalCandy')
9
+ const {mockOdac} = require('./__mocks__/globalOdac')
10
10
 
11
11
  // Mock all dependencies
12
12
  jest.mock('fs')
@@ -37,10 +37,10 @@ describe('SSL', () => {
37
37
  return result
38
38
  })
39
39
 
40
- // Get mock instances from global Candy
41
- mockConfig = mockCandy.core('Config')
42
- mockLog = mockCandy.server('Log').init('SSL')
43
- mockDNS = mockCandy.server('DNS')
40
+ // Get mock instances from global Odac
41
+ mockConfig = mockOdac.core('Config')
42
+ mockLog = mockOdac.server('Log').init('SSL')
43
+ mockDNS = mockOdac.server('DNS')
44
44
 
45
45
  // Set up DNS mock methods
46
46
  mockDNS.record = jest.fn()
@@ -173,14 +173,14 @@ describe('SSL', () => {
173
173
  'example.com': createMockWebsiteConfig('example.com')
174
174
  }
175
175
  mockConfig.config.ssl = {
176
- key: '/home/test/.candypack/cert/ssl/candypack.key',
177
- cert: '/home/test/.candypack/cert/ssl/candypack.crt',
176
+ key: '/home/test/.odac/cert/ssl/odac.key',
177
+ cert: '/home/test/.odac/cert/ssl/odac.crt',
178
178
  expiry: Date.now() + 86400000 // Valid
179
179
  }
180
180
 
181
181
  // Mock self-signed certificate files as missing
182
182
  fs.existsSync.mockImplementation(path => {
183
- if (path.includes('candypack.key') || path.includes('candypack.crt')) {
183
+ if (path.includes('odac.key') || path.includes('odac.crt')) {
184
184
  return false
185
185
  }
186
186
  return true
@@ -259,8 +259,8 @@ describe('SSL', () => {
259
259
 
260
260
  await SSL.check()
261
261
 
262
- expect(selfsigned.generate).toHaveBeenCalledWith([{name: 'commonName', value: 'CandyPack'}], {days: 365, keySize: 2048})
263
- expect(fs.mkdirSync).toHaveBeenCalledWith('/home/test/.candypack/cert/ssl', {recursive: true})
262
+ expect(selfsigned.generate).toHaveBeenCalledWith([{name: 'commonName', value: 'Odac'}], {days: 365, keySize: 2048})
263
+ expect(fs.mkdirSync).toHaveBeenCalledWith('/home/test/.odac/cert/ssl', {recursive: true})
264
264
  expect(fs.writeFileSync).toHaveBeenCalledTimes(2)
265
265
  })
266
266
 
@@ -340,7 +340,7 @@ describe('SSL', () => {
340
340
  describe('renew method', () => {
341
341
  beforeEach(() => {
342
342
  // Set up the API mock to return proper result format
343
- const mockApi = mockCandy.server('Api')
343
+ const mockApi = mockOdac.server('Api')
344
344
  mockApi.result = jest.fn((success, message) => ({success, data: message}))
345
345
  })
346
346
 
@@ -781,7 +781,7 @@ describe('SSL', () => {
781
781
 
782
782
  // Mock directory doesn't exist to trigger creation
783
783
  fs.existsSync.mockImplementation(path => {
784
- if (path.includes('.candypack/cert/ssl')) {
784
+ if (path.includes('.odac/cert/ssl')) {
785
785
  return false
786
786
  }
787
787
  return true
@@ -789,9 +789,9 @@ describe('SSL', () => {
789
789
 
790
790
  await SSL.check()
791
791
 
792
- expect(fs.mkdirSync).toHaveBeenCalledWith('/home/test/.candypack/cert/ssl', {recursive: true})
793
- expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.candypack/cert/ssl/example.com.key', 'mock-key')
794
- expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.candypack/cert/ssl/example.com.crt', 'mock-certificate')
792
+ expect(fs.mkdirSync).toHaveBeenCalledWith('/home/test/.odac/cert/ssl', {recursive: true})
793
+ expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.odac/cert/ssl/example.com.key', 'mock-key')
794
+ expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.odac/cert/ssl/example.com.crt', 'mock-certificate')
795
795
  })
796
796
 
797
797
  it('should not create directory if it already exists', async () => {
@@ -807,8 +807,8 @@ describe('SSL', () => {
807
807
  await SSL.check()
808
808
 
809
809
  expect(fs.mkdirSync).not.toHaveBeenCalled()
810
- expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.candypack/cert/ssl/example.com.key', 'mock-key')
811
- expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.candypack/cert/ssl/example.com.crt', 'mock-certificate')
810
+ expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.odac/cert/ssl/example.com.key', 'mock-key')
811
+ expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.odac/cert/ssl/example.com.crt', 'mock-certificate')
812
812
  })
813
813
 
814
814
  it('should update website configuration with new certificate', async () => {
@@ -821,8 +821,8 @@ describe('SSL', () => {
821
821
  await SSL.check()
822
822
 
823
823
  expect(mockWebsite.cert.ssl).toEqual({
824
- key: '/home/test/.candypack/cert/ssl/example.com.key',
825
- cert: '/home/test/.candypack/cert/ssl/example.com.crt',
824
+ key: '/home/test/.odac/cert/ssl/example.com.key',
825
+ cert: '/home/test/.odac/cert/ssl/example.com.crt',
826
826
  expiry: expect.any(Number)
827
827
  })
828
828
  })
@@ -854,8 +854,8 @@ describe('SSL', () => {
854
854
  await SSL.check()
855
855
 
856
856
  expect(mockWebsite.cert.ssl).toEqual({
857
- key: '/home/test/.candypack/cert/ssl/example.com.key',
858
- cert: '/home/test/.candypack/cert/ssl/example.com.crt',
857
+ key: '/home/test/.odac/cert/ssl/example.com.key',
858
+ cert: '/home/test/.odac/cert/ssl/example.com.crt',
859
859
  expiry: expect.any(Number)
860
860
  })
861
861
  expect(mockConfig.config.websites['example.com']).toBe(mockWebsite)
@@ -872,8 +872,8 @@ describe('SSL', () => {
872
872
 
873
873
  // Configuration should be updated with new certificate info
874
874
  expect(mockConfig.config.websites['example.com'].cert.ssl).toBeDefined()
875
- expect(mockConfig.config.websites['example.com'].cert.ssl.key).toBe('/home/test/.candypack/cert/ssl/example.com.key')
876
- expect(mockConfig.config.websites['example.com'].cert.ssl.cert).toBe('/home/test/.candypack/cert/ssl/example.com.crt')
875
+ expect(mockConfig.config.websites['example.com'].cert.ssl.key).toBe('/home/test/.odac/cert/ssl/example.com.key')
876
+ expect(mockConfig.config.websites['example.com'].cert.ssl.cert).toBe('/home/test/.odac/cert/ssl/example.com.crt')
877
877
  })
878
878
  })
879
879
  })
@@ -975,7 +975,7 @@ describe('SSL', () => {
975
975
 
976
976
  await SSL.check()
977
977
 
978
- expect(selfsigned.generate).toHaveBeenCalledWith([{name: 'commonName', value: 'CandyPack'}], {days: 365, keySize: 2048})
978
+ expect(selfsigned.generate).toHaveBeenCalledWith([{name: 'commonName', value: 'Odac'}], {days: 365, keySize: 2048})
979
979
  })
980
980
 
981
981
  it('should generate self-signed certificate when SSL config is expired', async () => {
@@ -983,14 +983,14 @@ describe('SSL', () => {
983
983
  'example.com': createMockWebsiteConfig('example.com')
984
984
  }
985
985
  mockConfig.config.ssl = {
986
- key: '/home/test/.candypack/cert/ssl/candypack.key',
987
- cert: '/home/test/.candypack/cert/ssl/candypack.crt',
986
+ key: '/home/test/.odac/cert/ssl/odac.key',
987
+ cert: '/home/test/.odac/cert/ssl/odac.crt',
988
988
  expiry: Date.now() - 86400000 // Expired yesterday
989
989
  }
990
990
 
991
991
  await SSL.check()
992
992
 
993
- expect(selfsigned.generate).toHaveBeenCalledWith([{name: 'commonName', value: 'CandyPack'}], {days: 365, keySize: 2048})
993
+ expect(selfsigned.generate).toHaveBeenCalledWith([{name: 'commonName', value: 'Odac'}], {days: 365, keySize: 2048})
994
994
  })
995
995
 
996
996
  it('should use correct certificate attributes for self-signed generation', async () => {
@@ -1001,7 +1001,7 @@ describe('SSL', () => {
1001
1001
 
1002
1002
  await SSL.check()
1003
1003
 
1004
- expect(selfsigned.generate).toHaveBeenCalledWith([{name: 'commonName', value: 'CandyPack'}], {days: 365, keySize: 2048})
1004
+ expect(selfsigned.generate).toHaveBeenCalledWith([{name: 'commonName', value: 'Odac'}], {days: 365, keySize: 2048})
1005
1005
  })
1006
1006
 
1007
1007
  it('should use correct options for self-signed certificate generation', async () => {
@@ -1021,8 +1021,8 @@ describe('SSL', () => {
1021
1021
  'example.com': createMockWebsiteConfig('example.com')
1022
1022
  }
1023
1023
  mockConfig.config.ssl = {
1024
- key: '/home/test/.candypack/cert/ssl/candypack.key',
1025
- cert: '/home/test/.candypack/cert/ssl/candypack.crt',
1024
+ key: '/home/test/.odac/cert/ssl/odac.key',
1025
+ cert: '/home/test/.odac/cert/ssl/odac.crt',
1026
1026
  expiry: Date.now() + 86400000 // Valid for another day
1027
1027
  }
1028
1028
 
@@ -1039,15 +1039,15 @@ describe('SSL', () => {
1039
1039
  'example.com': createMockWebsiteConfig('example.com')
1040
1040
  }
1041
1041
  mockConfig.config.ssl = {
1042
- key: '/home/test/.candypack/cert/ssl/candypack.key',
1043
- cert: '/home/test/.candypack/cert/ssl/candypack.crt',
1042
+ key: '/home/test/.odac/cert/ssl/odac.key',
1043
+ cert: '/home/test/.odac/cert/ssl/odac.crt',
1044
1044
  expiry: Date.now() + 86400000 // Valid expiry
1045
1045
  }
1046
1046
 
1047
1047
  // Mock key file missing but cert file exists
1048
1048
  fs.existsSync.mockImplementation(path => {
1049
- if (path.includes('candypack.key')) return false
1050
- if (path.includes('candypack.crt')) return true
1049
+ if (path.includes('odac.key')) return false
1050
+ if (path.includes('odac.crt')) return true
1051
1051
  return true
1052
1052
  })
1053
1053
 
@@ -1061,15 +1061,15 @@ describe('SSL', () => {
1061
1061
  'example.com': createMockWebsiteConfig('example.com')
1062
1062
  }
1063
1063
  mockConfig.config.ssl = {
1064
- key: '/home/test/.candypack/cert/ssl/candypack.key',
1065
- cert: '/home/test/.candypack/cert/ssl/candypack.crt',
1064
+ key: '/home/test/.odac/cert/ssl/odac.key',
1065
+ cert: '/home/test/.odac/cert/ssl/odac.crt',
1066
1066
  expiry: Date.now() + 86400000 // Valid expiry
1067
1067
  }
1068
1068
 
1069
1069
  // Mock cert file missing but key file exists
1070
1070
  fs.existsSync.mockImplementation(path => {
1071
- if (path.includes('candypack.key')) return true
1072
- if (path.includes('candypack.crt')) return false
1071
+ if (path.includes('odac.key')) return true
1072
+ if (path.includes('odac.crt')) return false
1073
1073
  return true
1074
1074
  })
1075
1075
 
@@ -1088,13 +1088,13 @@ describe('SSL', () => {
1088
1088
 
1089
1089
  // Mock directory doesn't exist
1090
1090
  fs.existsSync.mockImplementation(path => {
1091
- if (path.includes('.candypack/cert/ssl')) return false
1091
+ if (path.includes('.odac/cert/ssl')) return false
1092
1092
  return true
1093
1093
  })
1094
1094
 
1095
1095
  await SSL.check()
1096
1096
 
1097
- expect(fs.mkdirSync).toHaveBeenCalledWith('/home/test/.candypack/cert/ssl', {recursive: true})
1097
+ expect(fs.mkdirSync).toHaveBeenCalledWith('/home/test/.odac/cert/ssl', {recursive: true})
1098
1098
  })
1099
1099
 
1100
1100
  it('should not create SSL directory if it already exists', async () => {
@@ -1120,7 +1120,7 @@ describe('SSL', () => {
1120
1120
  await SSL.check()
1121
1121
 
1122
1122
  expect(fs.writeFileSync).toHaveBeenCalledWith(
1123
- '/home/test/.candypack/cert/ssl/candypack.key',
1123
+ '/home/test/.odac/cert/ssl/odac.key',
1124
1124
  '-----BEGIN PRIVATE KEY-----\nmock-private-key\n-----END PRIVATE KEY-----'
1125
1125
  )
1126
1126
  })
@@ -1134,7 +1134,7 @@ describe('SSL', () => {
1134
1134
  await SSL.check()
1135
1135
 
1136
1136
  expect(fs.writeFileSync).toHaveBeenCalledWith(
1137
- '/home/test/.candypack/cert/ssl/candypack.crt',
1137
+ '/home/test/.odac/cert/ssl/odac.crt',
1138
1138
  '-----BEGIN CERTIFICATE-----\nmock-certificate\n-----END CERTIFICATE-----'
1139
1139
  )
1140
1140
  })
@@ -1148,8 +1148,8 @@ describe('SSL', () => {
1148
1148
  await SSL.check()
1149
1149
 
1150
1150
  expect(mockConfig.config.ssl).toEqual({
1151
- key: '/home/test/.candypack/cert/ssl/candypack.key',
1152
- cert: '/home/test/.candypack/cert/ssl/candypack.crt',
1151
+ key: '/home/test/.odac/cert/ssl/odac.key',
1152
+ cert: '/home/test/.odac/cert/ssl/odac.crt',
1153
1153
  expiry: expect.any(Number)
1154
1154
  })
1155
1155
  })
@@ -1171,8 +1171,8 @@ describe('SSL', () => {
1171
1171
 
1172
1172
  it('should preserve existing SSL configuration when certificate is valid', async () => {
1173
1173
  const existingSSL = {
1174
- key: '/home/test/.candypack/cert/ssl/candypack.key',
1175
- cert: '/home/test/.candypack/cert/ssl/candypack.crt',
1174
+ key: '/home/test/.odac/cert/ssl/odac.key',
1175
+ cert: '/home/test/.odac/cert/ssl/odac.crt',
1176
1176
  expiry: Date.now() + 86400000 // Valid for another day
1177
1177
  }
1178
1178
 
@@ -1217,7 +1217,7 @@ describe('SSL', () => {
1217
1217
 
1218
1218
  // Mock fs.writeFileSync to throw an error only for self-signed cert files
1219
1219
  fs.writeFileSync.mockImplementation(path => {
1220
- if (path.includes('candypack.key') || path.includes('candypack.crt')) {
1220
+ if (path.includes('odac.key') || path.includes('odac.crt')) {
1221
1221
  throw new Error('File write failed')
1222
1222
  }
1223
1223
  })
@@ -1372,8 +1372,8 @@ describe('SSL', () => {
1372
1372
 
1373
1373
  await SSL.check()
1374
1374
 
1375
- expect(mockConfig.config.ssl.key).toBe('/home/test/.candypack/cert/ssl/candypack.key')
1376
- expect(mockConfig.config.ssl.cert).toBe('/home/test/.candypack/cert/ssl/candypack.crt')
1375
+ expect(mockConfig.config.ssl.key).toBe('/home/test/.odac/cert/ssl/odac.key')
1376
+ expect(mockConfig.config.ssl.cert).toBe('/home/test/.odac/cert/ssl/odac.crt')
1377
1377
  expect(typeof mockConfig.config.ssl.expiry).toBe('number')
1378
1378
  expect(mockConfig.config.ssl.expiry).toBeGreaterThan(Date.now())
1379
1379
  })
@@ -1409,13 +1409,13 @@ describe('SSL', () => {
1409
1409
 
1410
1410
  // Verify key file content
1411
1411
  expect(fs.writeFileSync).toHaveBeenCalledWith(
1412
- '/home/test/.candypack/cert/ssl/candypack.key',
1412
+ '/home/test/.odac/cert/ssl/odac.key',
1413
1413
  expect.stringContaining('-----BEGIN PRIVATE KEY-----')
1414
1414
  )
1415
1415
 
1416
1416
  // Verify certificate file content
1417
1417
  expect(fs.writeFileSync).toHaveBeenCalledWith(
1418
- '/home/test/.candypack/cert/ssl/candypack.crt',
1418
+ '/home/test/.odac/cert/ssl/odac.crt',
1419
1419
  expect.stringContaining('-----BEGIN CERTIFICATE-----')
1420
1420
  )
1421
1421
  })
@@ -1431,7 +1431,7 @@ describe('SSL', () => {
1431
1431
 
1432
1432
  await SSL.check()
1433
1433
 
1434
- expect(selfsigned.generate).toHaveBeenCalledWith([{name: 'commonName', value: 'CandyPack'}], {days: 365, keySize: 2048})
1434
+ expect(selfsigned.generate).toHaveBeenCalledWith([{name: 'commonName', value: 'Odac'}], {days: 365, keySize: 2048})
1435
1435
  })
1436
1436
 
1437
1437
  it('should validate certificate generation parameters are secure', async () => {
@@ -1483,8 +1483,8 @@ describe('SSL', () => {
1483
1483
  await SSL.check()
1484
1484
 
1485
1485
  // Should still write the files even with malformed data
1486
- expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.candypack/cert/ssl/candypack.key', 'invalid-key-data')
1487
- expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.candypack/cert/ssl/candypack.crt', 'invalid-cert-data')
1486
+ expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.odac/cert/ssl/odac.key', 'invalid-key-data')
1487
+ expect(fs.writeFileSync).toHaveBeenCalledWith('/home/test/.odac/cert/ssl/odac.crt', 'invalid-cert-data')
1488
1488
  })
1489
1489
  })
1490
1490
  })
@@ -28,11 +28,11 @@ class TestServer {
28
28
  check: jest.fn()
29
29
  }
30
30
 
31
- // Store original global Candy if it exists
32
- this.originalCandy = global.Candy
31
+ // Store original global Odac if it exists
32
+ this.originalCandy = global.Odac
33
33
 
34
- // Setup isolated Candy mock for this instance
35
- global.Candy = {
34
+ // Setup isolated Odac mock for this instance
35
+ global.Odac = {
36
36
  core: jest.fn(module => {
37
37
  if (module === 'Config') {
38
38
  return {config: this.mockConfig}
@@ -64,34 +64,34 @@ class TestServer {
64
64
  }
65
65
 
66
66
  init() {
67
- global.Candy.core('Config').config.server.pid = process.pid
68
- global.Candy.core('Config').config.server.started = Date.now()
69
- global.Candy.server('Service')
70
- global.Candy.server('DNS')
71
- global.Candy.server('Web')
72
- global.Candy.server('Mail')
73
- global.Candy.server('Api')
67
+ global.Odac.core('Config').config.server.pid = process.pid
68
+ global.Odac.core('Config').config.server.started = Date.now()
69
+ global.Odac.server('Service')
70
+ global.Odac.server('DNS')
71
+ global.Odac.server('Web')
72
+ global.Odac.server('Mail')
73
+ global.Odac.server('Api')
74
74
 
75
75
  // Setup health checks
76
76
  setTimeout(() => {
77
77
  this.intervalId = setInterval(() => {
78
78
  try {
79
- global.Candy.server('Service').check()
79
+ global.Odac.server('Service').check()
80
80
  } catch (e) {
81
81
  // Ignore service check errors
82
82
  }
83
83
  try {
84
- global.Candy.server('SSL').check()
84
+ global.Odac.server('SSL').check()
85
85
  } catch (e) {
86
86
  // Ignore SSL check errors
87
87
  }
88
88
  try {
89
- global.Candy.server('Web').check()
89
+ global.Odac.server('Web').check()
90
90
  } catch (e) {
91
91
  // Ignore Web check errors
92
92
  }
93
93
  try {
94
- global.Candy.server('Mail').check()
94
+ global.Odac.server('Mail').check()
95
95
  } catch (e) {
96
96
  // Ignore Mail check errors
97
97
  }
@@ -101,12 +101,12 @@ class TestServer {
101
101
 
102
102
  stop() {
103
103
  try {
104
- global.Candy.server('Service').stopAll()
104
+ global.Odac.server('Service').stopAll()
105
105
  } catch (e) {
106
106
  // Ignore service stop errors
107
107
  }
108
108
  try {
109
- global.Candy.server('Web').stopAll()
109
+ global.Odac.server('Web').stopAll()
110
110
  } catch (e) {
111
111
  // Ignore web stop errors
112
112
  }
@@ -117,11 +117,11 @@ class TestServer {
117
117
 
118
118
  destroy() {
119
119
  this.stop()
120
- // Restore original Candy if it existed
120
+ // Restore original Odac if it existed
121
121
  if (this.originalCandy) {
122
- global.Candy = this.originalCandy
122
+ global.Odac = this.originalCandy
123
123
  } else {
124
- delete global.Candy
124
+ delete global.Odac
125
125
  }
126
126
  }
127
127
  }
@@ -134,8 +134,8 @@ describe('Server', () => {
134
134
  jest.clearAllTimers()
135
135
  jest.useFakeTimers()
136
136
 
137
- // Clear any existing global Candy
138
- delete global.Candy
137
+ // Clear any existing global Odac
138
+ delete global.Odac
139
139
  })
140
140
 
141
141
  afterEach(() => {
@@ -143,7 +143,7 @@ describe('Server', () => {
143
143
  server.destroy()
144
144
  }
145
145
  jest.useRealTimers()
146
- delete global.Candy
146
+ delete global.Odac
147
147
  })
148
148
 
149
149
  describe('initialization', () => {
@@ -182,14 +182,14 @@ describe('Server', () => {
182
182
  server = new TestServer()
183
183
 
184
184
  // Verify all services are initialized
185
- expect(global.Candy.server).toHaveBeenCalledWith('Service')
186
- expect(global.Candy.server).toHaveBeenCalledWith('DNS')
187
- expect(global.Candy.server).toHaveBeenCalledWith('Web')
188
- expect(global.Candy.server).toHaveBeenCalledWith('Mail')
189
- expect(global.Candy.server).toHaveBeenCalledWith('Api')
185
+ expect(global.Odac.server).toHaveBeenCalledWith('Service')
186
+ expect(global.Odac.server).toHaveBeenCalledWith('DNS')
187
+ expect(global.Odac.server).toHaveBeenCalledWith('Web')
188
+ expect(global.Odac.server).toHaveBeenCalledWith('Mail')
189
+ expect(global.Odac.server).toHaveBeenCalledWith('Api')
190
190
 
191
191
  // Verify call order
192
- const serverCalls = global.Candy.server.mock.calls.map(call => call[0])
192
+ const serverCalls = global.Odac.server.mock.calls.map(call => call[0])
193
193
  expect(serverCalls).toEqual(['Service', 'DNS', 'Web', 'Mail', 'Api'])
194
194
  })
195
195
 
@@ -252,9 +252,9 @@ describe('Server', () => {
252
252
  // Create a modified TestServer that throws during DNS initialization
253
253
  class ErrorTestServer extends TestServer {
254
254
  init() {
255
- global.Candy.core('Config').config.server.pid = process.pid
256
- global.Candy.core('Config').config.server.started = Date.now()
257
- global.Candy.server('Service')
255
+ global.Odac.core('Config').config.server.pid = process.pid
256
+ global.Odac.core('Config').config.server.started = Date.now()
257
+ global.Odac.server('Service')
258
258
 
259
259
  // This should throw
260
260
  throw new Error('DNS initialization failed')
@@ -273,10 +273,10 @@ describe('Server', () => {
273
273
  jest.advanceTimersByTime(2000)
274
274
 
275
275
  // Verify that the same service instances are being called during health checks
276
- expect(global.Candy.server).toHaveBeenCalledWith('Service')
277
- expect(global.Candy.server).toHaveBeenCalledWith('SSL')
278
- expect(global.Candy.server).toHaveBeenCalledWith('Web')
279
- expect(global.Candy.server).toHaveBeenCalledWith('Mail')
276
+ expect(global.Odac.server).toHaveBeenCalledWith('Service')
277
+ expect(global.Odac.server).toHaveBeenCalledWith('SSL')
278
+ expect(global.Odac.server).toHaveBeenCalledWith('Web')
279
+ expect(global.Odac.server).toHaveBeenCalledWith('Mail')
280
280
  })
281
281
  })
282
282
 
@@ -726,8 +726,8 @@ describe('Server', () => {
726
726
  test('should handle config access errors gracefully', () => {
727
727
  // Create a function that simulates the Server initialization with config error
728
728
  const createServerWithConfigError = () => {
729
- // Setup global Candy mock that throws on Config access
730
- global.Candy = {
729
+ // Setup global Odac mock that throws on Config access
730
+ global.Odac = {
731
731
  core: jest.fn(module => {
732
732
  if (module === 'Config') {
733
733
  throw new Error('Config access failed')
@@ -738,7 +738,7 @@ describe('Server', () => {
738
738
  }
739
739
 
740
740
  // Simulate the Server initialization process
741
- global.Candy.core('Config').config.server.pid = process.pid
741
+ global.Odac.core('Config').config.server.pid = process.pid
742
742
  }
743
743
 
744
744
  expect(() => {