odac 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/.editorconfig +21 -0
  2. package/.github/workflows/auto-pr-description.yml +49 -0
  3. package/.github/workflows/release.yml +32 -0
  4. package/.github/workflows/test-coverage.yml +58 -0
  5. package/.husky/pre-commit +2 -0
  6. package/.kiro/steering/code-style.md +56 -0
  7. package/.kiro/steering/product.md +20 -0
  8. package/.kiro/steering/structure.md +77 -0
  9. package/.kiro/steering/tech.md +87 -0
  10. package/.prettierrc +10 -0
  11. package/.releaserc.js +134 -0
  12. package/AGENTS.md +84 -0
  13. package/CHANGELOG.md +181 -0
  14. package/CODE_OF_CONDUCT.md +83 -0
  15. package/CONTRIBUTING.md +63 -0
  16. package/LICENSE +661 -0
  17. package/README.md +57 -0
  18. package/SECURITY.md +26 -0
  19. package/bin/candy +10 -0
  20. package/bin/candypack +10 -0
  21. package/cli/index.js +3 -0
  22. package/cli/src/Cli.js +348 -0
  23. package/cli/src/Connector.js +93 -0
  24. package/cli/src/Monitor.js +416 -0
  25. package/core/Candy.js +87 -0
  26. package/core/Commands.js +239 -0
  27. package/core/Config.js +1094 -0
  28. package/core/Lang.js +52 -0
  29. package/core/Log.js +43 -0
  30. package/core/Process.js +26 -0
  31. package/docs/backend/01-overview/01-whats-in-the-candy-box.md +9 -0
  32. package/docs/backend/01-overview/02-super-handy-helper-functions.md +9 -0
  33. package/docs/backend/01-overview/03-development-server.md +79 -0
  34. package/docs/backend/02-structure/01-typical-project-layout.md +39 -0
  35. package/docs/backend/03-config/00-configuration-overview.md +214 -0
  36. package/docs/backend/03-config/01-database-connection.md +60 -0
  37. package/docs/backend/03-config/02-static-route-mapping-optional.md +20 -0
  38. package/docs/backend/03-config/03-request-timeout.md +11 -0
  39. package/docs/backend/03-config/04-environment-variables.md +227 -0
  40. package/docs/backend/03-config/05-early-hints.md +352 -0
  41. package/docs/backend/04-routing/01-basic-page-routes.md +28 -0
  42. package/docs/backend/04-routing/02-controller-less-view-routes.md +43 -0
  43. package/docs/backend/04-routing/03-api-and-data-routes.md +20 -0
  44. package/docs/backend/04-routing/04-authentication-aware-routes.md +48 -0
  45. package/docs/backend/04-routing/05-advanced-routing.md +14 -0
  46. package/docs/backend/04-routing/06-error-pages.md +101 -0
  47. package/docs/backend/04-routing/07-cron-jobs.md +149 -0
  48. package/docs/backend/05-controllers/01-how-to-build-a-controller.md +17 -0
  49. package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +20 -0
  50. package/docs/backend/05-controllers/03-controller-classes.md +93 -0
  51. package/docs/backend/05-forms/01-custom-forms.md +395 -0
  52. package/docs/backend/05-forms/02-automatic-database-insert.md +297 -0
  53. package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +96 -0
  54. package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +40 -0
  55. package/docs/backend/07-views/01-the-view-directory.md +73 -0
  56. package/docs/backend/07-views/02-rendering-a-view.md +179 -0
  57. package/docs/backend/07-views/03-template-syntax.md +181 -0
  58. package/docs/backend/07-views/03-variables.md +328 -0
  59. package/docs/backend/07-views/04-request-data.md +231 -0
  60. package/docs/backend/07-views/05-conditionals.md +290 -0
  61. package/docs/backend/07-views/06-loops.md +353 -0
  62. package/docs/backend/07-views/07-translations.md +358 -0
  63. package/docs/backend/07-views/08-backend-javascript.md +398 -0
  64. package/docs/backend/07-views/09-comments.md +297 -0
  65. package/docs/backend/08-database/01-database-connection.md +99 -0
  66. package/docs/backend/08-database/02-using-mysql.md +322 -0
  67. package/docs/backend/09-validation/01-the-validator-service.md +424 -0
  68. package/docs/backend/10-authentication/01-user-logins-with-authjs.md +53 -0
  69. package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +55 -0
  70. package/docs/backend/10-authentication/03-register.md +134 -0
  71. package/docs/backend/10-authentication/04-candy-register-forms.md +676 -0
  72. package/docs/backend/10-authentication/05-session-management.md +159 -0
  73. package/docs/backend/10-authentication/06-candy-login-forms.md +596 -0
  74. package/docs/backend/11-mail/01-the-mail-service.md +42 -0
  75. package/docs/backend/12-streaming/01-streaming-overview.md +300 -0
  76. package/docs/backend/13-utilities/01-candy-var.md +504 -0
  77. package/docs/frontend/01-overview/01-introduction.md +146 -0
  78. package/docs/frontend/02-ajax-navigation/01-quick-start.md +608 -0
  79. package/docs/frontend/02-ajax-navigation/02-configuration.md +370 -0
  80. package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +519 -0
  81. package/docs/frontend/03-forms/01-form-handling.md +420 -0
  82. package/docs/frontend/04-api-requests/01-get-post.md +443 -0
  83. package/docs/frontend/05-streaming/01-client-streaming.md +163 -0
  84. package/docs/index.json +452 -0
  85. package/docs/server/01-installation/01-quick-install.md +19 -0
  86. package/docs/server/01-installation/02-manual-installation-via-npm.md +9 -0
  87. package/docs/server/02-get-started/01-core-concepts.md +7 -0
  88. package/docs/server/02-get-started/02-basic-commands.md +57 -0
  89. package/docs/server/02-get-started/03-cli-reference.md +276 -0
  90. package/docs/server/02-get-started/04-cli-quick-reference.md +102 -0
  91. package/docs/server/03-service/01-start-a-new-service.md +57 -0
  92. package/docs/server/03-service/02-delete-a-service.md +48 -0
  93. package/docs/server/04-web/01-create-a-website.md +36 -0
  94. package/docs/server/04-web/02-list-websites.md +9 -0
  95. package/docs/server/04-web/03-delete-a-website.md +29 -0
  96. package/docs/server/05-subdomain/01-create-a-subdomain.md +32 -0
  97. package/docs/server/05-subdomain/02-list-subdomains.md +33 -0
  98. package/docs/server/05-subdomain/03-delete-a-subdomain.md +41 -0
  99. package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +34 -0
  100. package/docs/server/07-mail/01-create-a-mail-account.md +23 -0
  101. package/docs/server/07-mail/02-delete-a-mail-account.md +20 -0
  102. package/docs/server/07-mail/03-list-mail-accounts.md +20 -0
  103. package/docs/server/07-mail/04-change-account-password.md +23 -0
  104. package/eslint.config.mjs +120 -0
  105. package/framework/index.js +4 -0
  106. package/framework/src/Auth.js +309 -0
  107. package/framework/src/Candy.js +81 -0
  108. package/framework/src/Config.js +79 -0
  109. package/framework/src/Env.js +60 -0
  110. package/framework/src/Lang.js +57 -0
  111. package/framework/src/Mail.js +83 -0
  112. package/framework/src/Mysql.js +575 -0
  113. package/framework/src/Request.js +301 -0
  114. package/framework/src/Route/Cron.js +128 -0
  115. package/framework/src/Route/Internal.js +439 -0
  116. package/framework/src/Route.js +455 -0
  117. package/framework/src/Server.js +15 -0
  118. package/framework/src/Stream.js +163 -0
  119. package/framework/src/Token.js +37 -0
  120. package/framework/src/Validator.js +271 -0
  121. package/framework/src/Var.js +211 -0
  122. package/framework/src/View/EarlyHints.js +190 -0
  123. package/framework/src/View/Form.js +600 -0
  124. package/framework/src/View.js +513 -0
  125. package/framework/web/candy.js +838 -0
  126. package/jest.config.js +22 -0
  127. package/locale/de-DE.json +80 -0
  128. package/locale/en-US.json +79 -0
  129. package/locale/es-ES.json +80 -0
  130. package/locale/fr-FR.json +80 -0
  131. package/locale/pt-BR.json +80 -0
  132. package/locale/ru-RU.json +80 -0
  133. package/locale/tr-TR.json +85 -0
  134. package/locale/zh-CN.json +80 -0
  135. package/package.json +86 -0
  136. package/server/index.js +5 -0
  137. package/server/src/Api.js +88 -0
  138. package/server/src/DNS.js +940 -0
  139. package/server/src/Hub.js +535 -0
  140. package/server/src/Mail.js +571 -0
  141. package/server/src/SSL.js +180 -0
  142. package/server/src/Server.js +27 -0
  143. package/server/src/Service.js +248 -0
  144. package/server/src/Subdomain.js +64 -0
  145. package/server/src/Web/Firewall.js +170 -0
  146. package/server/src/Web/Proxy.js +134 -0
  147. package/server/src/Web.js +451 -0
  148. package/server/src/mail/imap.js +1091 -0
  149. package/server/src/mail/server.js +32 -0
  150. package/server/src/mail/smtp.js +786 -0
  151. package/test/cli/Cli.test.js +36 -0
  152. package/test/core/Candy.test.js +234 -0
  153. package/test/core/Commands.test.js +538 -0
  154. package/test/core/Config.test.js +1435 -0
  155. package/test/core/Lang.test.js +250 -0
  156. package/test/core/Process.test.js +156 -0
  157. package/test/framework/Route.test.js +239 -0
  158. package/test/framework/View/EarlyHints.test.js +282 -0
  159. package/test/scripts/check-coverage.js +132 -0
  160. package/test/server/Api.test.js +647 -0
  161. package/test/server/Client.test.js +338 -0
  162. package/test/server/DNS.test.js +2050 -0
  163. package/test/server/DNS.test.js.bak +2084 -0
  164. package/test/server/Log.test.js +73 -0
  165. package/test/server/Mail.account.test_.js +460 -0
  166. package/test/server/Mail.init.test_.js +411 -0
  167. package/test/server/Mail.test_.js +1340 -0
  168. package/test/server/SSL.test_.js +1491 -0
  169. package/test/server/Server.test.js +765 -0
  170. package/test/server/Service.test_.js +1127 -0
  171. package/test/server/Subdomain.test.js +440 -0
  172. package/test/server/Web/Firewall.test.js +175 -0
  173. package/test/server/Web.test_.js +1562 -0
  174. package/test/server/__mocks__/acme-client.js +17 -0
  175. package/test/server/__mocks__/bcrypt.js +50 -0
  176. package/test/server/__mocks__/child_process.js +389 -0
  177. package/test/server/__mocks__/crypto.js +432 -0
  178. package/test/server/__mocks__/fs.js +450 -0
  179. package/test/server/__mocks__/globalCandy.js +227 -0
  180. package/test/server/__mocks__/http-proxy.js +105 -0
  181. package/test/server/__mocks__/http.js +575 -0
  182. package/test/server/__mocks__/https.js +272 -0
  183. package/test/server/__mocks__/index.js +249 -0
  184. package/test/server/__mocks__/mail/server.js +100 -0
  185. package/test/server/__mocks__/mail/smtp.js +31 -0
  186. package/test/server/__mocks__/mailparser.js +81 -0
  187. package/test/server/__mocks__/net.js +369 -0
  188. package/test/server/__mocks__/node-forge.js +328 -0
  189. package/test/server/__mocks__/os.js +320 -0
  190. package/test/server/__mocks__/path.js +291 -0
  191. package/test/server/__mocks__/selfsigned.js +8 -0
  192. package/test/server/__mocks__/server/src/mail/server.js +100 -0
  193. package/test/server/__mocks__/server/src/mail/smtp.js +31 -0
  194. package/test/server/__mocks__/smtp-server.js +106 -0
  195. package/test/server/__mocks__/sqlite3.js +394 -0
  196. package/test/server/__mocks__/testFactories.js +299 -0
  197. package/test/server/__mocks__/testHelpers.js +363 -0
  198. package/test/server/__mocks__/tls.js +229 -0
  199. package/watchdog/index.js +3 -0
  200. package/watchdog/src/Watchdog.js +156 -0
  201. package/web/config.json +5 -0
  202. package/web/controller/page/about.js +27 -0
  203. package/web/controller/page/index.js +34 -0
  204. package/web/package.json +18 -0
  205. package/web/public/assets/css/style.css +1835 -0
  206. package/web/public/assets/js/app.js +96 -0
  207. package/web/route/www.js +19 -0
  208. package/web/skeleton/main.html +22 -0
  209. package/web/view/content/about.html +65 -0
  210. package/web/view/content/home.html +205 -0
  211. package/web/view/footer/main.html +11 -0
  212. package/web/view/head/main.html +5 -0
  213. package/web/view/header/main.html +14 -0
@@ -0,0 +1,328 @@
1
+ /**
2
+ * Mock implementation of node-forge for server tests
3
+ */
4
+
5
+ // Mock RSA key pair
6
+ const createMockKeyPair = (keySize = 2048) => {
7
+ return {
8
+ privateKey: {
9
+ n: 'mock-private-key-modulus',
10
+ e: 'mock-private-key-exponent',
11
+ d: 'mock-private-key-private-exponent',
12
+ p: 'mock-private-key-prime1',
13
+ q: 'mock-private-key-prime2',
14
+ dP: 'mock-private-key-exponent1',
15
+ dQ: 'mock-private-key-exponent2',
16
+ qInv: 'mock-private-key-coefficient'
17
+ },
18
+ publicKey: {
19
+ n: 'mock-public-key-modulus',
20
+ e: 'mock-public-key-exponent'
21
+ }
22
+ }
23
+ }
24
+
25
+ // Mock certificate
26
+ const createMockCertificate = () => {
27
+ return {
28
+ version: 2,
29
+ serialNumber: '01',
30
+ validity: {
31
+ notBefore: new Date(),
32
+ notAfter: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000) // 1 year
33
+ },
34
+ subject: {
35
+ attributes: [
36
+ {name: 'commonName', value: 'example.com'},
37
+ {name: 'organizationName', value: 'Test Organization'}
38
+ ]
39
+ },
40
+ issuer: {
41
+ attributes: [
42
+ {name: 'commonName', value: 'Test CA'},
43
+ {name: 'organizationName', value: 'Test CA Organization'}
44
+ ]
45
+ },
46
+ extensions: [],
47
+ publicKey: createMockKeyPair().publicKey,
48
+ sign: jest.fn(),
49
+ verify: jest.fn(() => true)
50
+ }
51
+ }
52
+
53
+ const forge = {
54
+ // PKI (Public Key Infrastructure)
55
+ pki: {
56
+ // RSA key generation
57
+ rsa: {
58
+ generateKeyPair: jest.fn((keySize, options, callback) => {
59
+ if (typeof options === 'function') {
60
+ callback = options
61
+ options = {}
62
+ }
63
+
64
+ const keyPair = createMockKeyPair(keySize)
65
+
66
+ if (callback) {
67
+ setTimeout(() => callback(null, keyPair), 0)
68
+ } else {
69
+ return keyPair
70
+ }
71
+ }),
72
+
73
+ setPublicKey: jest.fn((n, e) => {
74
+ return {
75
+ n: n,
76
+ e: e,
77
+ encrypt: jest.fn(data => 'encrypted-' + data),
78
+ verify: jest.fn(() => true)
79
+ }
80
+ }),
81
+
82
+ setPrivateKey: jest.fn((n, e, d, p, q, dP, dQ, qInv) => {
83
+ return {
84
+ n,
85
+ e,
86
+ d,
87
+ p,
88
+ q,
89
+ dP,
90
+ dQ,
91
+ qInv,
92
+ decrypt: jest.fn(data => data.replace('encrypted-', '')),
93
+ sign: jest.fn(data => 'signature-' + data)
94
+ }
95
+ })
96
+ },
97
+
98
+ // Key conversion functions
99
+ privateKeyToPem: jest.fn(privateKey => {
100
+ return (
101
+ '-----BEGIN PRIVATE KEY-----\n' +
102
+ 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7VJTUt9Us8cKB\n' +
103
+ 'UO4Op/DYDyBcjGh5aAFur4wEGoDf3iLnjN8V9RYubK+wJK8E4Hauv7o+8gMn\n' +
104
+ '-----END PRIVATE KEY-----'
105
+ )
106
+ }),
107
+
108
+ publicKeyToPem: jest.fn(publicKey => {
109
+ return (
110
+ '-----BEGIN PUBLIC KEY-----\n' +
111
+ 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1L7VLPHCgVDuDqfw\n' +
112
+ '2A8gXIxoeWgBbq+MBBqA394i54zfFfUWLmyvsCStBOB2rr+6PvIDJ\n' +
113
+ '-----END PUBLIC KEY-----'
114
+ )
115
+ }),
116
+
117
+ privateKeyFromPem: jest.fn(pem => {
118
+ return createMockKeyPair().privateKey
119
+ }),
120
+
121
+ publicKeyFromPem: jest.fn(pem => {
122
+ return createMockKeyPair().publicKey
123
+ }),
124
+
125
+ // Certificate functions
126
+ createCertificate: jest.fn(() => {
127
+ return createMockCertificate()
128
+ }),
129
+
130
+ certificateToPem: jest.fn(cert => {
131
+ return (
132
+ '-----BEGIN CERTIFICATE-----\n' +
133
+ 'MIIDXTCCAkWgAwIBAgIJAJC1HiIAZAiIMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\n' +
134
+ 'BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n' +
135
+ '-----END CERTIFICATE-----'
136
+ )
137
+ }),
138
+
139
+ certificateFromPem: jest.fn(pem => {
140
+ return createMockCertificate()
141
+ }),
142
+
143
+ // Certificate signing request
144
+ createCertificationRequest: jest.fn(() => {
145
+ return {
146
+ version: 0,
147
+ subject: {
148
+ attributes: []
149
+ },
150
+ publicKey: null,
151
+ attributes: [],
152
+ sign: jest.fn(),
153
+ verify: jest.fn(() => true)
154
+ }
155
+ }),
156
+
157
+ certificationRequestToPem: jest.fn(csr => {
158
+ return (
159
+ '-----BEGIN CERTIFICATE REQUEST-----\n' +
160
+ 'MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx\n' +
161
+ 'ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN\n' +
162
+ '-----END CERTIFICATE REQUEST-----'
163
+ )
164
+ }),
165
+
166
+ certificationRequestFromPem: jest.fn(pem => {
167
+ return {
168
+ version: 0,
169
+ subject: {attributes: []},
170
+ publicKey: createMockKeyPair().publicKey,
171
+ attributes: [],
172
+ verify: jest.fn(() => true)
173
+ }
174
+ })
175
+ },
176
+
177
+ // Message digests
178
+ md: {
179
+ sha1: {
180
+ create: jest.fn(() => ({
181
+ update: jest.fn(),
182
+ digest: jest.fn(() => ({
183
+ toHex: jest.fn(() => 'mock-sha1-hash'),
184
+ bytes: jest.fn(() => 'mock-sha1-bytes')
185
+ }))
186
+ }))
187
+ },
188
+
189
+ sha256: {
190
+ create: jest.fn(() => ({
191
+ update: jest.fn(),
192
+ digest: jest.fn(() => ({
193
+ toHex: jest.fn(() => 'mock-sha256-hash'),
194
+ bytes: jest.fn(() => 'mock-sha256-bytes')
195
+ }))
196
+ }))
197
+ },
198
+
199
+ sha512: {
200
+ create: jest.fn(() => ({
201
+ update: jest.fn(),
202
+ digest: jest.fn(() => ({
203
+ toHex: jest.fn(() => 'mock-sha512-hash'),
204
+ bytes: jest.fn(() => 'mock-sha512-bytes')
205
+ }))
206
+ }))
207
+ },
208
+
209
+ md5: {
210
+ create: jest.fn(() => ({
211
+ update: jest.fn(),
212
+ digest: jest.fn(() => ({
213
+ toHex: jest.fn(() => 'mock-md5-hash'),
214
+ bytes: jest.fn(() => 'mock-md5-bytes')
215
+ }))
216
+ }))
217
+ }
218
+ },
219
+
220
+ // HMAC
221
+ hmac: {
222
+ create: jest.fn(() => ({
223
+ start: jest.fn(),
224
+ update: jest.fn(),
225
+ digest: jest.fn(() => ({
226
+ toHex: jest.fn(() => 'mock-hmac-hash'),
227
+ bytes: jest.fn(() => 'mock-hmac-bytes')
228
+ }))
229
+ }))
230
+ },
231
+
232
+ // Random number generation
233
+ random: {
234
+ getBytesSync: jest.fn(count => {
235
+ return Array(count)
236
+ .fill(0)
237
+ .map(() => String.fromCharCode(Math.floor(Math.random() * 256)))
238
+ .join('')
239
+ }),
240
+
241
+ getBytes: jest.fn((count, callback) => {
242
+ const bytes = Array(count)
243
+ .fill(0)
244
+ .map(() => String.fromCharCode(Math.floor(Math.random() * 256)))
245
+ .join('')
246
+ setTimeout(() => callback(null, bytes), 0)
247
+ })
248
+ },
249
+
250
+ // Utilities
251
+ util: {
252
+ encode64: jest.fn(data => {
253
+ return Buffer.from(data).toString('base64')
254
+ }),
255
+
256
+ decode64: jest.fn(data => {
257
+ return Buffer.from(data, 'base64').toString()
258
+ }),
259
+
260
+ bytesToHex: jest.fn(bytes => {
261
+ return Array.from(bytes)
262
+ .map(b => b.toString(16).padStart(2, '0'))
263
+ .join('')
264
+ }),
265
+
266
+ hexToBytes: jest.fn(hex => {
267
+ const bytes = []
268
+ for (let i = 0; i < hex.length; i += 2) {
269
+ bytes.push(parseInt(hex.substr(i, 2), 16))
270
+ }
271
+ return bytes
272
+ }),
273
+
274
+ createBuffer: jest.fn(data => {
275
+ return {
276
+ data: data || '',
277
+ length: function () {
278
+ return this.data.length
279
+ },
280
+ at: function (i) {
281
+ return this.data.charCodeAt(i)
282
+ },
283
+ put: function (data) {
284
+ this.data += data
285
+ },
286
+ putByte: function (byte) {
287
+ this.data += String.fromCharCode(byte)
288
+ },
289
+ putBytes: function (bytes) {
290
+ this.data += bytes
291
+ },
292
+ bytes: function () {
293
+ return this.data
294
+ },
295
+ toHex: function () {
296
+ return forge.util.bytesToHex(this.data)
297
+ }
298
+ }
299
+ })
300
+ },
301
+
302
+ // ASN.1 utilities
303
+ asn1: {
304
+ create: jest.fn((tagClass, type, constructed, value) => {
305
+ return {
306
+ tagClass: tagClass,
307
+ type: type,
308
+ constructed: constructed,
309
+ value: value || []
310
+ }
311
+ }),
312
+
313
+ toDer: jest.fn(obj => {
314
+ return forge.util.createBuffer('mock-der-data')
315
+ }),
316
+
317
+ fromDer: jest.fn(der => {
318
+ return {
319
+ tagClass: 0,
320
+ type: 16,
321
+ constructed: true,
322
+ value: []
323
+ }
324
+ })
325
+ }
326
+ }
327
+
328
+ module.exports = forge
@@ -0,0 +1,320 @@
1
+ /**
2
+ * Mock implementation of the os module for server tests
3
+ * Provides comprehensive mocking of operating system utilities
4
+ */
5
+
6
+ const os = {
7
+ // System information
8
+ arch: jest.fn(() => 'x64'),
9
+ platform: jest.fn(() => 'linux'),
10
+ type: jest.fn(() => 'Linux'),
11
+ release: jest.fn(() => '5.4.0-74-generic'),
12
+ version: jest.fn(() => '#83-Ubuntu SMP Sat May 8 02:35:39 UTC 2021'),
13
+ machine: jest.fn(() => 'x86_64'),
14
+
15
+ // Hostname
16
+ hostname: jest.fn(() => 'test-hostname'),
17
+
18
+ // User information
19
+ userInfo: jest.fn((options = {}) => {
20
+ return {
21
+ uid: 1000,
22
+ gid: 1000,
23
+ username: 'testuser',
24
+ homedir: '/home/testuser',
25
+ shell: '/bin/bash'
26
+ }
27
+ }),
28
+
29
+ // Directory paths
30
+ homedir: jest.fn(() => '/home/testuser'),
31
+ tmpdir: jest.fn(() => '/tmp'),
32
+
33
+ // System constants
34
+ EOL: '\n',
35
+
36
+ // CPU information
37
+ cpus: jest.fn(() => [
38
+ {
39
+ model: 'Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz',
40
+ speed: 3700,
41
+ times: {
42
+ user: 252020,
43
+ nice: 0,
44
+ sys: 30340,
45
+ idle: 1070356870,
46
+ irq: 0
47
+ }
48
+ },
49
+ {
50
+ model: 'Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz',
51
+ speed: 3700,
52
+ times: {
53
+ user: 306920,
54
+ nice: 0,
55
+ sys: 26980,
56
+ idle: 1071569080,
57
+ irq: 0
58
+ }
59
+ }
60
+ ]),
61
+
62
+ // Memory information
63
+ totalmem: jest.fn(() => 17179869184), // 16 GB
64
+ freemem: jest.fn(() => 8589934592), // 8 GB
65
+
66
+ // Load average (Unix-like systems only)
67
+ loadavg: jest.fn(() => [0.2, 0.1, 0.05]),
68
+
69
+ // Uptime
70
+ uptime: jest.fn(() => 86400), // 1 day in seconds
71
+
72
+ // Network interfaces
73
+ networkInterfaces: jest.fn(() => ({
74
+ lo: [
75
+ {
76
+ address: '127.0.0.1',
77
+ netmask: '255.0.0.0',
78
+ family: 'IPv4',
79
+ mac: '00:00:00:00:00:00',
80
+ internal: true,
81
+ cidr: '127.0.0.1/8'
82
+ },
83
+ {
84
+ address: '::1',
85
+ netmask: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
86
+ family: 'IPv6',
87
+ mac: '00:00:00:00:00:00',
88
+ internal: true,
89
+ cidr: '::1/128',
90
+ scopeid: 0
91
+ }
92
+ ],
93
+ eth0: [
94
+ {
95
+ address: '192.168.1.100',
96
+ netmask: '255.255.255.0',
97
+ family: 'IPv4',
98
+ mac: '01:02:03:04:05:06',
99
+ internal: false,
100
+ cidr: '192.168.1.100/24'
101
+ },
102
+ {
103
+ address: 'fe80::a00:27ff:fe4e:66a1',
104
+ netmask: 'ffff:ffff:ffff:ffff::',
105
+ family: 'IPv6',
106
+ mac: '01:02:03:04:05:06',
107
+ internal: false,
108
+ cidr: 'fe80::a00:27ff:fe4e:66a1/64',
109
+ scopeid: 1
110
+ }
111
+ ]
112
+ })),
113
+
114
+ // Priority constants
115
+ constants: {
116
+ // Signals
117
+ signals: {
118
+ SIGHUP: 1,
119
+ SIGINT: 2,
120
+ SIGQUIT: 3,
121
+ SIGILL: 4,
122
+ SIGTRAP: 5,
123
+ SIGABRT: 6,
124
+ SIGIOT: 6,
125
+ SIGBUS: 7,
126
+ SIGFPE: 8,
127
+ SIGKILL: 9,
128
+ SIGUSR1: 10,
129
+ SIGSEGV: 11,
130
+ SIGUSR2: 12,
131
+ SIGPIPE: 13,
132
+ SIGALRM: 14,
133
+ SIGTERM: 15,
134
+ SIGCHLD: 17,
135
+ SIGCONT: 18,
136
+ SIGSTOP: 19,
137
+ SIGTSTP: 20,
138
+ SIGTTIN: 21,
139
+ SIGTTOU: 22,
140
+ SIGURG: 23,
141
+ SIGXCPU: 24,
142
+ SIGXFSZ: 25,
143
+ SIGVTALRM: 26,
144
+ SIGPROF: 27,
145
+ SIGWINCH: 28,
146
+ SIGIO: 29,
147
+ SIGPOLL: 29,
148
+ SIGPWR: 30,
149
+ SIGSYS: 31,
150
+ SIGUNUSED: 31
151
+ },
152
+
153
+ // Error codes
154
+ errno: {
155
+ E2BIG: 7,
156
+ EACCES: 13,
157
+ EADDRINUSE: 98,
158
+ EADDRNOTAVAIL: 99,
159
+ EAFNOSUPPORT: 97,
160
+ EAGAIN: 11,
161
+ EALREADY: 114,
162
+ EBADF: 9,
163
+ EBADMSG: 74,
164
+ EBUSY: 16,
165
+ ECANCELED: 125,
166
+ ECHILD: 10,
167
+ ECONNABORTED: 103,
168
+ ECONNREFUSED: 111,
169
+ ECONNRESET: 104,
170
+ EDEADLK: 35,
171
+ EDESTADDRREQ: 89,
172
+ EDOM: 33,
173
+ EDQUOT: 122,
174
+ EEXIST: 17,
175
+ EFAULT: 14,
176
+ EFBIG: 27,
177
+ EHOSTUNREACH: 113,
178
+ EIDRM: 43,
179
+ EILSEQ: 84,
180
+ EINPROGRESS: 115,
181
+ EINTR: 4,
182
+ EINVAL: 22,
183
+ EIO: 5,
184
+ EISCONN: 106,
185
+ EISDIR: 21,
186
+ ELOOP: 40,
187
+ EMFILE: 24,
188
+ EMLINK: 31,
189
+ EMSGSIZE: 90,
190
+ EMULTIHOP: 72,
191
+ ENAMETOOLONG: 36,
192
+ ENETDOWN: 100,
193
+ ENETRESET: 102,
194
+ ENETUNREACH: 101,
195
+ ENFILE: 23,
196
+ ENOBUFS: 105,
197
+ ENODATA: 61,
198
+ ENODEV: 19,
199
+ ENOENT: 2,
200
+ ENOEXEC: 8,
201
+ ENOLCK: 37,
202
+ ENOLINK: 67,
203
+ ENOMEM: 12,
204
+ ENOMSG: 42,
205
+ ENOPROTOOPT: 92,
206
+ ENOSPC: 28,
207
+ ENOSR: 63,
208
+ ENOSTR: 60,
209
+ ENOSYS: 38,
210
+ ENOTCONN: 107,
211
+ ENOTDIR: 20,
212
+ ENOTEMPTY: 39,
213
+ ENOTSOCK: 88,
214
+ ENOTSUP: 95,
215
+ ENOTTY: 25,
216
+ ENXIO: 6,
217
+ EOPNOTSUPP: 95,
218
+ EOVERFLOW: 75,
219
+ EPERM: 1,
220
+ EPIPE: 32,
221
+ EPROTO: 71,
222
+ EPROTONOSUPPORT: 93,
223
+ EPROTOTYPE: 91,
224
+ ERANGE: 34,
225
+ EROFS: 30,
226
+ ESPIPE: 29,
227
+ ESRCH: 3,
228
+ ESTALE: 116,
229
+ ETIME: 62,
230
+ ETIMEDOUT: 110,
231
+ ETXTBSY: 26,
232
+ EWOULDBLOCK: 11,
233
+ EXDEV: 18
234
+ },
235
+
236
+ // Priority levels
237
+ priority: {
238
+ PRIORITY_LOW: 19,
239
+ PRIORITY_BELOW_NORMAL: 10,
240
+ PRIORITY_NORMAL: 0,
241
+ PRIORITY_ABOVE_NORMAL: -7,
242
+ PRIORITY_HIGH: -14,
243
+ PRIORITY_HIGHEST: -20
244
+ }
245
+ },
246
+
247
+ // Process priority (Unix-like systems)
248
+ getPriority: jest.fn((pid = 0) => {
249
+ return 0 // Normal priority
250
+ }),
251
+
252
+ setPriority: jest.fn((pid, priority) => {
253
+ if (typeof pid === 'number' && typeof priority === 'undefined') {
254
+ priority = pid
255
+ pid = 0
256
+ }
257
+
258
+ // Mock implementation - just return success
259
+ return undefined
260
+ }),
261
+
262
+ // Endianness
263
+ endianness: jest.fn(() => 'LE'), // Little Endian
264
+
265
+ // Test helpers
266
+ __setArch: arch => {
267
+ os.arch.mockReturnValue(arch)
268
+ },
269
+
270
+ __setPlatform: platform => {
271
+ os.platform.mockReturnValue(platform)
272
+ },
273
+
274
+ __setHostname: hostname => {
275
+ os.hostname.mockReturnValue(hostname)
276
+ },
277
+
278
+ __setHomedir: homedir => {
279
+ os.homedir.mockReturnValue(homedir)
280
+ },
281
+
282
+ __setTmpdir: tmpdir => {
283
+ os.tmpdir.mockReturnValue(tmpdir)
284
+ },
285
+
286
+ __setMemory: (total, free) => {
287
+ os.totalmem.mockReturnValue(total)
288
+ os.freemem.mockReturnValue(free)
289
+ },
290
+
291
+ __setLoadAvg: loadavg => {
292
+ os.loadavg.mockReturnValue(loadavg)
293
+ },
294
+
295
+ __setUptime: uptime => {
296
+ os.uptime.mockReturnValue(uptime)
297
+ },
298
+
299
+ __setCpus: cpus => {
300
+ os.cpus.mockReturnValue(cpus)
301
+ },
302
+
303
+ __setNetworkInterfaces: interfaces => {
304
+ os.networkInterfaces.mockReturnValue(interfaces)
305
+ },
306
+
307
+ __setUserInfo: userInfo => {
308
+ os.userInfo.mockReturnValue(userInfo)
309
+ },
310
+
311
+ __resetMocks: () => {
312
+ Object.values(os).forEach(fn => {
313
+ if (jest.isMockFunction(fn)) {
314
+ fn.mockClear()
315
+ }
316
+ })
317
+ }
318
+ }
319
+
320
+ module.exports = os