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
package/cli/src/Cli.js DELETED
@@ -1,348 +0,0 @@
1
- require('../../core/Candy.js')
2
-
3
- const childProcess = require('child_process')
4
- const readline = require('readline')
5
-
6
- class Cli {
7
- #backgrounds = {red: 41, green: 42, yellow: 43, blue: 44, magenta: 45, white: 47, gray: 100}
8
- colors = {red: 31, green: 32, yellow: 33, blue: 34, magenta: 35, white: 37, gray: 90}
9
- rl
10
- boot() {
11
- if (!this.booting) this.booting = true
12
- else return
13
- return new Promise(resolve => {
14
- console.log(__('Starting CandyPack Server...'))
15
- const child = childProcess.spawn('node', [__dirname + '/../../watchdog/index.js'], {
16
- detached: true,
17
- stdio: 'ignore'
18
- })
19
- child.unref()
20
- setTimeout(() => {
21
- Candy.core('Config').reload()
22
- resolve()
23
- }, 1000)
24
- })
25
- }
26
-
27
- close() {
28
- if (this.rl) this.rl.close()
29
- this.rl = null
30
- }
31
-
32
- color(text, color, ...args) {
33
- let output = text
34
- if (this.colors[color]) output = '\x1b[' + this.colors[color] + 'm' + output + '\x1b[0m'
35
- for (const arg of args) {
36
- if (this.#backgrounds[arg]) output = '\x1b[' + this.#backgrounds[arg] + 'm' + output + '\x1b[0m'
37
- if (arg == 'bold') output = '\x1b[1m' + output + '\x1b[0m'
38
- }
39
- return output
40
- }
41
-
42
- #format(text, raw) {
43
- if (typeof text !== 'string') return text
44
- let output = text.toString()
45
- if (output.toString().length > 1) {
46
- let begin = ''
47
- let end = ''
48
- while (output.substr(output.length - 1) == ' ') {
49
- end += ' '
50
- output = output.substr(0, output.length - 1)
51
- }
52
- while (output.substr(0, 1) == ' ') {
53
- begin += ' '
54
- output = output.substr(1)
55
- }
56
- if (output.substr(output.length - 1) == ':') {
57
- end = ':'
58
- output = output.substr(0, output.length - 1)
59
- }
60
- output = begin + output + end
61
- }
62
- if (!raw) {
63
- if (text == 'CandyPack') output = this.color(output, 'magenta')
64
- if (text == __('Running')) output = this.color(output, 'green')
65
- if (text == '\u2713') output = this.color(output, 'green')
66
- if (text == '\u2717') output = this.color(output, 'red')
67
- }
68
- return output
69
- }
70
-
71
- async #detail(command, obj) {
72
- let result = ''
73
- let space = 0
74
- if (obj.title) result += '\n\x1b[90m' + (await obj.title) + '\x1b\n'
75
- if (obj.description) {
76
- let args = ''
77
- if (obj.args) {
78
- // Only show positional arguments (not prefix arguments starting with -)
79
- let positionalArgs = obj.args.filter(arg => !arg.startsWith('-'))
80
-
81
- if (positionalArgs.length > 0) {
82
- args += ' <' + positionalArgs.join('> <') + '>'
83
- }
84
- }
85
- let line = '\x1b[91mcandy ' + command + '\x1b[0m\x1b[90m' + args + '\x1b[0m : ' + __(obj.description)
86
- result += line
87
- line = line.split(':')[0]
88
- if (line.length > space) space = line.length
89
- }
90
- if (obj.sub) {
91
- let lines = []
92
- for (const sub in obj.sub) {
93
- let detail = await this.#detail(command + ' ' + sub, obj.sub[sub])
94
- lines.push(detail.result)
95
- if (detail.space > space) space = detail.space
96
- }
97
- result += lines.join('\n')
98
- }
99
-
100
- return {result: result, space: space}
101
- }
102
-
103
- async help(commands) {
104
- let result = []
105
- let space = 0
106
- if (typeof commands == 'string') {
107
- let obj = Candy.core('Commands')
108
- let command = commands.shift()
109
- if (!obj[command]) return console.log(__(`'%s' is not a valid command.`, this.color(`candy ${commands.join(' ')}`, 'yellow')))
110
- obj = obj[command]
111
- while (commands.length > 0 && commands.length && obj.sub[commands[0]]) {
112
- command = commands.shift()
113
- if (!obj.sub[command]) return console.log(__(`'%s' is not a valid command.`, this.color(`candy ${commands.join(' ')}`, 'yellow')))
114
- obj = obj.sub[command]
115
- }
116
- let detail = await this.#detail(command, obj)
117
- if (detail.space > space) space = detail.space
118
- let lines = detail.result.split('\n')
119
- for (let line of lines) result.push(line)
120
- } else {
121
- const isAuthenticated = !!(Candy.core('Config').config.hub && Candy.core('Config').config.hub.token)
122
- for (const command in Candy.core('Commands')) {
123
- if (commands && commands !== true && commands[0] !== command) continue
124
- if (isAuthenticated && command === 'auth') continue
125
- let obj = Candy.core('Commands')[command]
126
- if (commands === true && !obj.action) continue
127
- let detail = await this.#detail(command, obj)
128
- if (detail.space > space) space = detail.space
129
- let lines = detail.result.split('\n')
130
- for (let line of lines) result.push(line)
131
- }
132
- result = result.map(line => {
133
- if (line.includes(':')) {
134
- let parts = line.split(':')
135
- parts[0] = parts[0] + ' '.repeat(space - parts[0].length)
136
- line = parts.join(':')
137
- }
138
- return line
139
- })
140
- }
141
- result.push('')
142
- for (let line of result) console.log(line)
143
- }
144
-
145
- icon(status, selected) {
146
- if (status == 'errored') return this.color(' ! ', 'red', selected ? 'white' : null)
147
- if (status == 'progress') return this.color(' - ', 'gray', selected ? 'white' : null)
148
- if (status == 'running') return this.color(' \u25B6 ', 'green', selected ? 'white' : null)
149
- if (status == 'stopped') return this.color(' \u23F8 ', 'yellow', selected ? 'white' : null)
150
- if (status == 'success') return this.color(' \u2713 ', 'green', selected ? 'white' : null)
151
- return ' '
152
- }
153
-
154
- async init() {
155
- console.log('\n', this.#format('CandyPack'), '\n')
156
- if (!(await Candy.cli('Connector').check())) await this.boot()
157
- let args = process.argv.slice(2)
158
- let cmds = process.argv.slice(2)
159
- if (args.length == 0) return this.#status()
160
- let command = args.shift()
161
- if (!Candy.core('Commands')[command])
162
- return console.log(__(`'%s' is not a valid command.`, this.color(`candy ${cmds.join(' ')}`, 'yellow')))
163
- let action = Candy.core('Commands')[command]
164
- while (args.length > 0 && !action.args) {
165
- command = args.shift()
166
- if (!action.sub || !action.sub[command]) return this.help(cmds)
167
- action = action.sub[command]
168
- }
169
- if (action.action) return action.action(args)
170
- else return this.help(cmds)
171
- }
172
-
173
- #length(text) {
174
- return (
175
- this.#value(text, true)
176
- .toString()
177
- // eslint-disable-next-line no-control-regex
178
- .replace(/\x1b\[[0-9;]*m/g, '').length
179
- )
180
- }
181
-
182
- formatDate(date) {
183
- const YYYY = date.getFullYear()
184
- const MM = String(date.getMonth() + 1).padStart(2, '0')
185
- const DD = String(date.getDate()).padStart(2, '0')
186
- const HH = String(date.getHours()).padStart(2, '0')
187
- const mm = String(date.getMinutes()).padStart(2, '0')
188
- const ss = String(date.getSeconds()).padStart(2, '0')
189
- return `${YYYY}-${MM}-${DD} ${HH}:${mm}:${ss}`
190
- }
191
-
192
- async log(...args) {
193
- let output = []
194
- for (let i = 0; i < args.length; i++) {
195
- if (typeof args[i] != 'string') output.push(args[i])
196
- else output.push(this.#format(args[i]))
197
- }
198
- console.log(...output)
199
- }
200
-
201
- spacing(text, len, direction) {
202
- if (direction == 'right') return ' '.repeat(len - this.#length(text)) + text
203
- if (direction == 'center')
204
- return ' '.repeat(Math.floor((len - this.#length(text)) / 2)) + text + ' '.repeat(Math.ceil((len - this.#length(text)) / 2))
205
- if (this.#length(text) > len) return text.substr(0, text.length - this.#length(text) + len)
206
- return text + ' '.repeat(len - this.#length(text))
207
- }
208
-
209
- async #status() {
210
- let status = {
211
- online: false,
212
- services: 0,
213
- auth: false,
214
- uptime: 0
215
- }
216
- status.online = await Candy.cli('Connector').check()
217
- var uptime = Date.now() - Candy.core('Config').config.server.started
218
- let seconds = Math.floor(uptime / 1000)
219
- let minutes = Math.floor(seconds / 60)
220
- let hours = Math.floor(minutes / 60)
221
- let days = Math.floor(hours / 24)
222
- seconds %= 60
223
- minutes %= 60
224
- hours %= 24
225
- let uptimeString = ''
226
- if (days) uptimeString += days + 'd '
227
- if (hours) uptimeString += hours + 'h '
228
- if (minutes && !days) uptimeString += minutes + 'm '
229
- if (seconds && !hours) uptimeString += seconds + 's'
230
- status.uptime = uptimeString
231
- status.services = Candy.core('Config').config.services ? Object.keys(Candy.core('Config').config.services).length : 0
232
- status.websites = Candy.core('Config').config.websites ? Object.keys(Candy.core('Config').config.websites).length : 0
233
- status.auth = !!(Candy.core('Config').config.hub && Candy.core('Config').config.hub.token)
234
- var args = process.argv.slice(2)
235
- if (args.length == 0) {
236
- let length = 0
237
- for (let i = 0; i < 2; i++) {
238
- for (let iterator of ['Status', 'Uptime', 'Websites', 'Services', 'Auth']) {
239
- let title = __(iterator)
240
- if (title.length > length) length = title.length
241
- if (i) {
242
- let space = ''
243
- for (let j = 0; j < length - title.length; j++) space += ' '
244
- switch (iterator) {
245
- case 'Status':
246
- console.log(title + space + ' : ' + (status.online ? '\x1b[32m ' + __('Online') : '\x1b[33m ' + __('Offline')) + '\x1b[0m')
247
- break
248
- case 'Uptime':
249
- if (status.online) console.log(title + space + ' : ' + '\x1b[32m ' + status.uptime + '\x1b[0m')
250
- break
251
- case 'Websites':
252
- if (status.online) console.log(title + space + ' : ' + '\x1b[32m ' + status.websites + '\x1b[0m')
253
- break
254
- case 'Services':
255
- if (status.online) console.log(title + space + ' : ' + '\x1b[32m ' + status.services + '\x1b[0m')
256
- break
257
- case 'Auth':
258
- console.log(
259
- title + space + ' : ' + (status.auth ? '\x1b[32m ' + __('Logged in') : '\x1b[33m ' + __('Not logged in')) + '\x1b[0m'
260
- )
261
- break
262
- }
263
- }
264
- }
265
- }
266
- if (!status.auth) console.log(__('Login on %s to manage all your server operations.', '\x1b[95mhttps://candypack.dev\x1b[0m'))
267
- console.log()
268
- console.log(__('Commands:'))
269
- length = 0
270
- this.help(true)
271
- console.log('')
272
- }
273
- }
274
-
275
- table(input) {
276
- let result = ''
277
- let width = []
278
- for (const row of input) {
279
- for (const key of Object.keys(row)) {
280
- if (input.indexOf(row) == 0) width[key] = this.#length(key)
281
- if (this.#length(row[key]) > width[key]) width[key] = this.#length(row[key])
282
- }
283
- }
284
- for (const row of input) {
285
- let insert = ''
286
- if (input.indexOf(row) == 0) {
287
- result += '┌─'
288
- for (const key of Object.keys(row)) result += '─'.repeat(width[key]) + '─┬─'
289
- result = this.color(result.substr(0, result.length - 3) + '─┐\n', 'gray')
290
- result += this.color('│ ', 'gray')
291
- for (const key of Object.keys(row)) {
292
- result += this.color(this.#value(key), 'blue') + ' '.repeat(width[key] - this.#length(key)) + this.color(' │ ', 'gray')
293
- }
294
- result += '\n'
295
- }
296
- insert += '├─'
297
- for (const key of Object.keys(row)) insert += '─'.repeat(width[key]) + '─┼─'
298
- insert = insert.substr(0, insert.length - 3) + '─┤\n'
299
- insert += '│ '
300
- result += this.color(insert, 'gray')
301
- for (const key of Object.keys(row)) {
302
- result += this.#value(row[key]) + ' '.repeat(width[key] - this.#length(row[key])) + this.color(' │ ', 'gray')
303
- }
304
- result += '\n'
305
- }
306
- let insert = '└─'
307
- for (const key of Object.keys(input[0])) insert += '─'.repeat(width[key]) + '─┴─'
308
- insert = insert.substr(0, insert.length - 3) + '─┘'
309
- result += this.color(insert, 'gray')
310
- console.log(result)
311
- }
312
-
313
- #value(text, raw) {
314
- if (!text) return ''
315
- let result = ''
316
- if (typeof text == 'object') result = this.#format(text.content)
317
- else result = this.#format(text, raw)
318
- return result
319
- }
320
-
321
- parseArg(args, prefixes) {
322
- if (!args || !prefixes) return null
323
-
324
- for (let i = 0; i < args.length; i++) {
325
- if (prefixes.includes(args[i]) && i + 1 < args.length) {
326
- return args[i + 1]
327
- }
328
- }
329
- return null
330
- }
331
-
332
- question(question) {
333
- return new Promise(resolve => {
334
- if (!this.rl) {
335
- this.rl = readline.createInterface({
336
- input: process.stdin,
337
- output: process.stdout
338
- })
339
- }
340
- this.rl.question(question, answer => {
341
- this.close()
342
- return resolve(answer.trim())
343
- })
344
- })
345
- }
346
- }
347
-
348
- module.exports = new Cli()
@@ -1,93 +0,0 @@
1
- const findProcess = require('find-process').default
2
- const net = require('net')
3
-
4
- class Connector {
5
- constructor() {
6
- this.socket = null
7
- this.connected = false
8
- this.connecting = false
9
- this.manualClose = false
10
- }
11
-
12
- #connect() {
13
- if (this.connected || this.connecting) return
14
- this.connecting = true
15
- this.socket = net.createConnection({port: 1453, host: '127.0.0.1'}, () => {
16
- this.connected = true
17
- this.connecting = false
18
- })
19
-
20
- this.socket.on('data', raw => {
21
- raw = raw.toString()
22
- if (raw.includes('\r\n')) {
23
- raw = raw.split('\r\n')
24
- } else {
25
- raw = [raw]
26
- }
27
- for (let payload of raw) {
28
- try {
29
- payload = JSON.parse(payload)
30
- } catch {
31
- continue
32
- }
33
- if (payload.message) {
34
- if (payload.status) {
35
- if (this.lastProcess == payload.process) {
36
- process.stdout.clearLine(0)
37
- process.stdout.cursorTo(0)
38
- } else {
39
- this.lastProcess = payload.process
40
- process.stdout.write('\n')
41
- }
42
- process.stdout.write(Candy.cli('Cli').icon(payload.status) + payload.message + '\r')
43
- } else {
44
- if (this.lastProcess) process.stdout.write('\n')
45
- if (payload.result) {
46
- console.log(payload.message)
47
- } else {
48
- console.error(payload.message)
49
- }
50
- if (!this.manualClose) this.socket.end()
51
- this.connected = false
52
- this.connecting = false
53
- this.lastProcess = null
54
- }
55
- }
56
- }
57
- })
58
-
59
- this.socket.on('error', err => {
60
- console.error('Socket error:', err.message)
61
- })
62
- }
63
-
64
- call(command) {
65
- if (!command) return
66
- this.manualClose = false
67
- this.#connect()
68
- this.socket.write(
69
- JSON.stringify({
70
- auth: Candy.core('Config').config.api.auth,
71
- action: command.action,
72
- data: command.data
73
- })
74
- )
75
- }
76
-
77
- check() {
78
- return new Promise(resolve => {
79
- if (!Candy.core('Config').config.server.watchdog) return resolve(false)
80
- findProcess('pid', Candy.core('Config').config.server.watchdog)
81
- .then(list => {
82
- if (list.length > 0 && list[0].name == 'node') return resolve(true)
83
- return resolve(false)
84
- })
85
- .catch(err => {
86
- console.error('Error checking process:', err)
87
- return resolve(false)
88
- })
89
- })
90
- }
91
- }
92
-
93
- module.exports = new Connector()