alepha 0.15.0 → 0.15.2

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 (551) hide show
  1. package/README.md +43 -98
  2. package/dist/api/audits/index.d.ts +630 -653
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +12 -35
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +365 -358
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +12 -5
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +255 -248
  11. package/dist/api/jobs/index.d.ts.map +1 -1
  12. package/dist/api/jobs/index.js +10 -3
  13. package/dist/api/jobs/index.js.map +1 -1
  14. package/dist/api/keys/index.d.ts +413 -0
  15. package/dist/api/keys/index.d.ts.map +1 -0
  16. package/dist/api/keys/index.js +476 -0
  17. package/dist/api/keys/index.js.map +1 -0
  18. package/dist/api/notifications/index.browser.js +4 -4
  19. package/dist/api/notifications/index.browser.js.map +1 -1
  20. package/dist/api/notifications/index.d.ts +84 -78
  21. package/dist/api/notifications/index.d.ts.map +1 -1
  22. package/dist/api/notifications/index.js +14 -8
  23. package/dist/api/notifications/index.js.map +1 -1
  24. package/dist/api/parameters/index.d.ts +528 -535
  25. package/dist/api/parameters/index.d.ts.map +1 -1
  26. package/dist/api/parameters/index.js +30 -37
  27. package/dist/api/parameters/index.js.map +1 -1
  28. package/dist/api/users/index.d.ts +1221 -910
  29. package/dist/api/users/index.d.ts.map +1 -1
  30. package/dist/api/users/index.js +2556 -248
  31. package/dist/api/users/index.js.map +1 -1
  32. package/dist/api/verifications/index.d.ts +142 -136
  33. package/dist/api/verifications/index.d.ts.map +1 -1
  34. package/dist/api/verifications/index.js +12 -4
  35. package/dist/api/verifications/index.js.map +1 -1
  36. package/dist/batch/index.d.ts +142 -162
  37. package/dist/batch/index.d.ts.map +1 -1
  38. package/dist/batch/index.js +31 -44
  39. package/dist/batch/index.js.map +1 -1
  40. package/dist/bucket/index.d.ts +595 -171
  41. package/dist/bucket/index.d.ts.map +1 -1
  42. package/dist/bucket/index.js +1856 -12
  43. package/dist/bucket/index.js.map +1 -1
  44. package/dist/cache/core/index.d.ts +225 -53
  45. package/dist/cache/core/index.d.ts.map +1 -1
  46. package/dist/cache/core/index.js +213 -7
  47. package/dist/cache/core/index.js.map +1 -1
  48. package/dist/cache/redis/index.d.ts +1 -0
  49. package/dist/cache/redis/index.d.ts.map +1 -1
  50. package/dist/cache/redis/index.js +6 -2
  51. package/dist/cache/redis/index.js.map +1 -1
  52. package/dist/cli/index.d.ts +834 -226
  53. package/dist/cli/index.d.ts.map +1 -1
  54. package/dist/cli/index.js +2872 -417
  55. package/dist/cli/index.js.map +1 -1
  56. package/dist/command/index.d.ts +458 -310
  57. package/dist/command/index.d.ts.map +1 -1
  58. package/dist/command/index.js +2011 -76
  59. package/dist/command/index.js.map +1 -1
  60. package/dist/core/index.browser.js +309 -97
  61. package/dist/core/index.browser.js.map +1 -1
  62. package/dist/core/index.d.ts +796 -701
  63. package/dist/core/index.d.ts.map +1 -1
  64. package/dist/core/index.js +329 -97
  65. package/dist/core/index.js.map +1 -1
  66. package/dist/core/index.native.js +309 -97
  67. package/dist/core/index.native.js.map +1 -1
  68. package/dist/datetime/index.d.ts +59 -44
  69. package/dist/datetime/index.d.ts.map +1 -1
  70. package/dist/datetime/index.js +15 -0
  71. package/dist/datetime/index.js.map +1 -1
  72. package/dist/email/index.d.ts +314 -19
  73. package/dist/email/index.d.ts.map +1 -1
  74. package/dist/email/index.js +1852 -7
  75. package/dist/email/index.js.map +1 -1
  76. package/dist/fake/index.d.ts +5500 -5418
  77. package/dist/fake/index.d.ts.map +1 -1
  78. package/dist/fake/index.js +113 -42
  79. package/dist/fake/index.js.map +1 -1
  80. package/dist/lock/core/index.d.ts +219 -212
  81. package/dist/lock/core/index.d.ts.map +1 -1
  82. package/dist/lock/core/index.js +11 -4
  83. package/dist/lock/core/index.js.map +1 -1
  84. package/dist/lock/redis/index.d.ts.map +1 -1
  85. package/dist/logger/index.d.ts +41 -90
  86. package/dist/logger/index.d.ts.map +1 -1
  87. package/dist/logger/index.js +15 -68
  88. package/dist/logger/index.js.map +1 -1
  89. package/dist/mcp/index.d.ts +228 -230
  90. package/dist/mcp/index.d.ts.map +1 -1
  91. package/dist/mcp/index.js +32 -31
  92. package/dist/mcp/index.js.map +1 -1
  93. package/dist/orm/index.browser.js +12 -12
  94. package/dist/orm/index.browser.js.map +1 -1
  95. package/dist/orm/index.bun.js +90 -80
  96. package/dist/orm/index.bun.js.map +1 -1
  97. package/dist/orm/index.d.ts +1434 -1459
  98. package/dist/orm/index.d.ts.map +1 -1
  99. package/dist/orm/index.js +112 -130
  100. package/dist/orm/index.js.map +1 -1
  101. package/dist/queue/core/index.d.ts +262 -254
  102. package/dist/queue/core/index.d.ts.map +1 -1
  103. package/dist/queue/core/index.js +14 -6
  104. package/dist/queue/core/index.js.map +1 -1
  105. package/dist/queue/redis/index.d.ts.map +1 -1
  106. package/dist/react/auth/index.browser.js +108 -0
  107. package/dist/react/auth/index.browser.js.map +1 -0
  108. package/dist/react/auth/index.d.ts +100 -0
  109. package/dist/react/auth/index.d.ts.map +1 -0
  110. package/dist/react/auth/index.js +145 -0
  111. package/dist/react/auth/index.js.map +1 -0
  112. package/dist/react/core/index.d.ts +469 -0
  113. package/dist/react/core/index.d.ts.map +1 -0
  114. package/dist/react/core/index.js +464 -0
  115. package/dist/react/core/index.js.map +1 -0
  116. package/dist/react/form/index.d.ts +232 -0
  117. package/dist/react/form/index.d.ts.map +1 -0
  118. package/dist/react/form/index.js +432 -0
  119. package/dist/react/form/index.js.map +1 -0
  120. package/dist/react/head/index.browser.js +423 -0
  121. package/dist/react/head/index.browser.js.map +1 -0
  122. package/dist/react/head/index.d.ts +288 -0
  123. package/dist/react/head/index.d.ts.map +1 -0
  124. package/dist/react/head/index.js +465 -0
  125. package/dist/react/head/index.js.map +1 -0
  126. package/dist/react/i18n/index.d.ts +175 -0
  127. package/dist/react/i18n/index.d.ts.map +1 -0
  128. package/dist/react/i18n/index.js +224 -0
  129. package/dist/react/i18n/index.js.map +1 -0
  130. package/dist/react/router/index.browser.js +1980 -0
  131. package/dist/react/router/index.browser.js.map +1 -0
  132. package/dist/react/router/index.d.ts +2068 -0
  133. package/dist/react/router/index.d.ts.map +1 -0
  134. package/dist/react/router/index.js +4932 -0
  135. package/dist/react/router/index.js.map +1 -0
  136. package/dist/react/websocket/index.d.ts +117 -0
  137. package/dist/react/websocket/index.d.ts.map +1 -0
  138. package/dist/react/websocket/index.js +107 -0
  139. package/dist/react/websocket/index.js.map +1 -0
  140. package/dist/redis/index.bun.js +4 -0
  141. package/dist/redis/index.bun.js.map +1 -1
  142. package/dist/redis/index.d.ts +127 -130
  143. package/dist/redis/index.d.ts.map +1 -1
  144. package/dist/redis/index.js +16 -25
  145. package/dist/redis/index.js.map +1 -1
  146. package/dist/retry/index.d.ts +80 -71
  147. package/dist/retry/index.d.ts.map +1 -1
  148. package/dist/retry/index.js +11 -2
  149. package/dist/retry/index.js.map +1 -1
  150. package/dist/router/index.d.ts +6 -6
  151. package/dist/router/index.d.ts.map +1 -1
  152. package/dist/scheduler/index.d.ts +119 -28
  153. package/dist/scheduler/index.d.ts.map +1 -1
  154. package/dist/scheduler/index.js +404 -3
  155. package/dist/scheduler/index.js.map +1 -1
  156. package/dist/security/index.d.ts +642 -228
  157. package/dist/security/index.d.ts.map +1 -1
  158. package/dist/security/index.js +1579 -37
  159. package/dist/security/index.js.map +1 -1
  160. package/dist/server/auth/index.d.ts +1141 -111
  161. package/dist/server/auth/index.d.ts.map +1 -1
  162. package/dist/server/auth/index.js +1261 -25
  163. package/dist/server/auth/index.js.map +1 -1
  164. package/dist/server/cache/index.d.ts +63 -78
  165. package/dist/server/cache/index.d.ts.map +1 -1
  166. package/dist/server/cache/index.js +7 -22
  167. package/dist/server/cache/index.js.map +1 -1
  168. package/dist/server/compress/index.d.ts +13 -5
  169. package/dist/server/compress/index.d.ts.map +1 -1
  170. package/dist/server/compress/index.js +10 -2
  171. package/dist/server/compress/index.js.map +1 -1
  172. package/dist/server/cookies/index.d.ts +46 -22
  173. package/dist/server/cookies/index.d.ts.map +1 -1
  174. package/dist/server/cookies/index.js +7 -5
  175. package/dist/server/cookies/index.js.map +1 -1
  176. package/dist/server/core/index.d.ts +307 -196
  177. package/dist/server/core/index.d.ts.map +1 -1
  178. package/dist/server/core/index.js +271 -38
  179. package/dist/server/core/index.js.map +1 -1
  180. package/dist/server/cors/index.d.ts +24 -34
  181. package/dist/server/cors/index.d.ts.map +1 -1
  182. package/dist/server/cors/index.js +7 -21
  183. package/dist/server/cors/index.js.map +1 -1
  184. package/dist/server/health/index.d.ts +25 -19
  185. package/dist/server/health/index.d.ts.map +1 -1
  186. package/dist/server/health/index.js +8 -2
  187. package/dist/server/health/index.js.map +1 -1
  188. package/dist/server/helmet/index.d.ts +13 -5
  189. package/dist/server/helmet/index.d.ts.map +1 -1
  190. package/dist/server/helmet/index.js +11 -3
  191. package/dist/server/helmet/index.js.map +1 -1
  192. package/dist/server/links/index.browser.js +9 -1
  193. package/dist/server/links/index.browser.js.map +1 -1
  194. package/dist/server/links/index.d.ts +133 -128
  195. package/dist/server/links/index.d.ts.map +1 -1
  196. package/dist/server/links/index.js +24 -11
  197. package/dist/server/links/index.js.map +1 -1
  198. package/dist/server/metrics/index.d.ts +524 -4
  199. package/dist/server/metrics/index.d.ts.map +1 -1
  200. package/dist/server/metrics/index.js +4472 -7
  201. package/dist/server/metrics/index.js.map +1 -1
  202. package/dist/server/multipart/index.d.ts +15 -9
  203. package/dist/server/multipart/index.d.ts.map +1 -1
  204. package/dist/server/multipart/index.js +9 -3
  205. package/dist/server/multipart/index.js.map +1 -1
  206. package/dist/server/proxy/index.d.ts +110 -104
  207. package/dist/server/proxy/index.d.ts.map +1 -1
  208. package/dist/server/proxy/index.js +8 -2
  209. package/dist/server/proxy/index.js.map +1 -1
  210. package/dist/server/rate-limit/index.d.ts +46 -51
  211. package/dist/server/rate-limit/index.d.ts.map +1 -1
  212. package/dist/server/rate-limit/index.js +18 -55
  213. package/dist/server/rate-limit/index.js.map +1 -1
  214. package/dist/server/static/index.d.ts +181 -48
  215. package/dist/server/static/index.d.ts.map +1 -1
  216. package/dist/server/static/index.js +1848 -5
  217. package/dist/server/static/index.js.map +1 -1
  218. package/dist/server/swagger/index.d.ts +348 -53
  219. package/dist/server/swagger/index.d.ts.map +1 -1
  220. package/dist/server/swagger/index.js +1849 -6
  221. package/dist/server/swagger/index.js.map +1 -1
  222. package/dist/sms/index.d.ts +312 -18
  223. package/dist/sms/index.d.ts.map +1 -1
  224. package/dist/sms/index.js +1854 -10
  225. package/dist/sms/index.js.map +1 -1
  226. package/dist/system/index.browser.js +496 -0
  227. package/dist/system/index.browser.js.map +1 -0
  228. package/dist/system/index.d.ts +1158 -0
  229. package/dist/system/index.d.ts.map +1 -0
  230. package/dist/{file → system}/index.js +412 -20
  231. package/dist/system/index.js.map +1 -0
  232. package/dist/thread/index.d.ts +82 -73
  233. package/dist/thread/index.d.ts.map +1 -1
  234. package/dist/thread/index.js +13 -4
  235. package/dist/thread/index.js.map +1 -1
  236. package/dist/topic/core/index.d.ts +330 -323
  237. package/dist/topic/core/index.d.ts.map +1 -1
  238. package/dist/topic/core/index.js +12 -5
  239. package/dist/topic/core/index.js.map +1 -1
  240. package/dist/topic/redis/index.d.ts +6 -6
  241. package/dist/topic/redis/index.d.ts.map +1 -1
  242. package/dist/vite/index.d.ts +163 -5825
  243. package/dist/vite/index.d.ts.map +1 -1
  244. package/dist/vite/index.js +130 -477
  245. package/dist/vite/index.js.map +1 -1
  246. package/dist/websocket/index.browser.js +3 -3
  247. package/dist/websocket/index.browser.js.map +1 -1
  248. package/dist/websocket/index.d.ts +287 -283
  249. package/dist/websocket/index.d.ts.map +1 -1
  250. package/dist/websocket/index.js +15 -11
  251. package/dist/websocket/index.js.map +1 -1
  252. package/package.json +86 -17
  253. package/src/api/audits/index.ts +10 -33
  254. package/src/api/files/__tests__/$bucket.spec.ts +1 -1
  255. package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
  256. package/src/api/files/controllers/FileController.spec.ts +1 -1
  257. package/src/api/files/index.ts +10 -3
  258. package/src/api/files/jobs/FileJobs.spec.ts +1 -1
  259. package/src/api/files/services/FileService.spec.ts +1 -1
  260. package/src/api/jobs/index.ts +10 -3
  261. package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
  262. package/src/api/keys/controllers/ApiKeyController.ts +103 -0
  263. package/src/api/keys/entities/apiKeyEntity.ts +41 -0
  264. package/src/api/keys/index.ts +49 -0
  265. package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
  266. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
  267. package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
  268. package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
  269. package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
  270. package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
  271. package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
  272. package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
  273. package/src/api/keys/services/ApiKeyService.ts +306 -0
  274. package/src/api/logs/TODO.md +52 -0
  275. package/src/api/notifications/index.ts +10 -4
  276. package/src/api/parameters/index.ts +9 -30
  277. package/src/api/parameters/primitives/$config.ts +12 -4
  278. package/src/api/parameters/services/ConfigStore.ts +9 -3
  279. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
  280. package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
  281. package/src/api/users/index.ts +14 -3
  282. package/src/api/users/primitives/$realm.ts +33 -5
  283. package/src/api/users/providers/RealmProvider.ts +1 -12
  284. package/src/api/users/services/SessionService.ts +1 -11
  285. package/src/api/verifications/controllers/VerificationController.ts +2 -0
  286. package/src/api/verifications/index.ts +10 -4
  287. package/src/batch/index.ts +9 -36
  288. package/src/batch/primitives/$batch.ts +0 -8
  289. package/src/batch/providers/BatchProvider.ts +29 -2
  290. package/src/bucket/__tests__/shared.ts +1 -1
  291. package/src/bucket/index.ts +13 -6
  292. package/src/bucket/primitives/$bucket.ts +1 -1
  293. package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
  294. package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
  295. package/src/cache/core/__tests__/shared.ts +30 -0
  296. package/src/cache/core/index.ts +11 -6
  297. package/src/cache/core/primitives/$cache.spec.ts +5 -0
  298. package/src/cache/core/providers/CacheProvider.ts +17 -0
  299. package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
  300. package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
  301. package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
  302. package/src/cli/apps/AlephaCli.ts +3 -16
  303. package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -2
  304. package/src/cli/atoms/appEntryOptions.ts +13 -0
  305. package/src/cli/atoms/buildOptions.ts +1 -1
  306. package/src/cli/atoms/changelogOptions.ts +1 -1
  307. package/src/cli/commands/build.ts +64 -52
  308. package/src/cli/commands/db.ts +17 -11
  309. package/src/cli/commands/deploy.ts +1 -1
  310. package/src/cli/commands/dev.ts +13 -49
  311. package/src/cli/commands/gen/env.ts +6 -3
  312. package/src/cli/commands/gen/openapi.ts +5 -2
  313. package/src/cli/commands/init.spec.ts +544 -0
  314. package/src/cli/commands/init.ts +101 -58
  315. package/src/cli/commands/lint.ts +8 -2
  316. package/src/cli/commands/typecheck.ts +11 -0
  317. package/src/cli/defineConfig.ts +9 -0
  318. package/src/cli/index.ts +2 -1
  319. package/src/cli/providers/AppEntryProvider.ts +131 -0
  320. package/src/cli/providers/ViteBuildProvider.ts +40 -0
  321. package/src/cli/providers/ViteDevServerProvider.ts +378 -0
  322. package/src/cli/services/AlephaCliUtils.ts +39 -93
  323. package/src/cli/services/PackageManagerUtils.ts +140 -17
  324. package/src/cli/services/ProjectScaffolder.ts +169 -101
  325. package/src/cli/services/ViteUtils.ts +82 -0
  326. package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +41 -28
  327. package/src/cli/{assets → templates}/apiHelloControllerTs.ts +2 -1
  328. package/src/cli/{assets → templates}/biomeJson.ts +2 -1
  329. package/src/cli/{assets → templates}/dummySpecTs.ts +2 -1
  330. package/src/cli/{assets → templates}/editorconfig.ts +2 -1
  331. package/src/cli/templates/gitignore.ts +39 -0
  332. package/src/cli/{assets → templates}/mainBrowserTs.ts +2 -1
  333. package/src/cli/templates/mainCss.ts +33 -0
  334. package/src/cli/templates/mainServerTs.ts +33 -0
  335. package/src/cli/{assets → templates}/tsconfigJson.ts +2 -1
  336. package/src/cli/templates/webAppRouterTs.ts +50 -0
  337. package/src/cli/templates/webHelloComponentTsx.ts +20 -0
  338. package/src/command/helpers/Runner.spec.ts +4 -0
  339. package/src/command/helpers/Runner.ts +3 -21
  340. package/src/command/index.ts +12 -4
  341. package/src/command/providers/CliProvider.spec.ts +1067 -0
  342. package/src/command/providers/CliProvider.ts +203 -40
  343. package/src/core/Alepha.ts +3 -9
  344. package/src/core/__tests__/Alepha-start.spec.ts +4 -4
  345. package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
  346. package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
  347. package/src/core/index.shared.ts +1 -0
  348. package/src/core/index.ts +20 -0
  349. package/src/core/primitives/$module.ts +12 -0
  350. package/src/core/providers/EventManager.spec.ts +0 -71
  351. package/src/core/providers/EventManager.ts +3 -15
  352. package/src/core/providers/Json.ts +2 -14
  353. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +257 -0
  354. package/src/core/providers/KeylessJsonSchemaCodec.ts +396 -14
  355. package/src/core/providers/SchemaValidator.spec.ts +236 -0
  356. package/src/datetime/index.ts +15 -0
  357. package/src/email/index.ts +10 -5
  358. package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
  359. package/src/email/providers/LocalEmailProvider.ts +1 -1
  360. package/src/fake/__tests__/keyName.example.ts +1 -1
  361. package/src/fake/__tests__/keyName.spec.ts +5 -5
  362. package/src/fake/index.ts +9 -6
  363. package/src/fake/providers/FakeProvider.spec.ts +258 -40
  364. package/src/fake/providers/FakeProvider.ts +133 -19
  365. package/src/lock/core/index.ts +11 -4
  366. package/src/logger/index.ts +17 -66
  367. package/src/logger/providers/PrettyFormatterProvider.ts +0 -9
  368. package/src/mcp/errors/McpError.ts +30 -0
  369. package/src/mcp/index.ts +13 -27
  370. package/src/mcp/transports/SseMcpTransport.ts +6 -7
  371. package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
  372. package/src/orm/index.browser.ts +2 -2
  373. package/src/orm/index.bun.ts +4 -2
  374. package/src/orm/index.ts +21 -47
  375. package/src/orm/providers/DrizzleKitProvider.ts +3 -5
  376. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -0
  377. package/src/orm/services/Repository.ts +18 -3
  378. package/src/queue/core/index.ts +14 -6
  379. package/src/react/auth/__tests__/$auth.spec.ts +202 -0
  380. package/src/react/auth/hooks/useAuth.ts +32 -0
  381. package/src/react/auth/index.browser.ts +13 -0
  382. package/src/react/auth/index.shared.ts +2 -0
  383. package/src/react/auth/index.ts +48 -0
  384. package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
  385. package/src/react/auth/services/ReactAuth.ts +135 -0
  386. package/src/react/core/__tests__/Router.spec.tsx +169 -0
  387. package/src/react/core/components/ClientOnly.tsx +49 -0
  388. package/src/react/core/components/ErrorBoundary.tsx +73 -0
  389. package/src/react/core/contexts/AlephaContext.ts +7 -0
  390. package/src/react/core/contexts/AlephaProvider.tsx +42 -0
  391. package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
  392. package/src/react/core/hooks/useAction.ts +480 -0
  393. package/src/react/core/hooks/useAlepha.ts +26 -0
  394. package/src/react/core/hooks/useClient.ts +17 -0
  395. package/src/react/core/hooks/useEvents.ts +51 -0
  396. package/src/react/core/hooks/useInject.ts +12 -0
  397. package/src/react/core/hooks/useStore.ts +52 -0
  398. package/src/react/core/index.ts +90 -0
  399. package/src/react/form/components/FormState.tsx +17 -0
  400. package/src/react/form/errors/FormValidationError.ts +18 -0
  401. package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
  402. package/src/react/form/hooks/useForm.ts +47 -0
  403. package/src/react/form/hooks/useFormState.ts +130 -0
  404. package/src/react/form/index.ts +44 -0
  405. package/src/react/form/services/FormModel.ts +614 -0
  406. package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
  407. package/src/react/head/helpers/SeoExpander.ts +142 -0
  408. package/src/react/head/hooks/useHead.spec.tsx +288 -0
  409. package/src/react/head/hooks/useHead.ts +62 -0
  410. package/src/react/head/index.browser.ts +26 -0
  411. package/src/react/head/index.ts +44 -0
  412. package/src/react/head/interfaces/Head.ts +105 -0
  413. package/src/react/head/primitives/$head.ts +25 -0
  414. package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
  415. package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
  416. package/src/react/head/providers/HeadProvider.ts +168 -0
  417. package/src/react/head/providers/ServerHeadProvider.ts +31 -0
  418. package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
  419. package/src/react/i18n/components/Localize.spec.tsx +357 -0
  420. package/src/react/i18n/components/Localize.tsx +35 -0
  421. package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
  422. package/src/react/i18n/hooks/useI18n.ts +18 -0
  423. package/src/react/i18n/index.ts +41 -0
  424. package/src/react/i18n/primitives/$dictionary.ts +69 -0
  425. package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
  426. package/src/react/i18n/providers/I18nProvider.ts +278 -0
  427. package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
  428. package/src/react/router/__tests__/page-head.spec.ts +48 -0
  429. package/src/react/router/__tests__/seo-head.spec.ts +125 -0
  430. package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
  431. package/src/react/router/components/ErrorViewer.tsx +872 -0
  432. package/src/react/router/components/Link.tsx +23 -0
  433. package/src/react/router/components/NestedView.tsx +223 -0
  434. package/src/react/router/components/NotFound.tsx +30 -0
  435. package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
  436. package/src/react/router/contexts/RouterLayerContext.ts +12 -0
  437. package/src/react/router/errors/Redirection.ts +28 -0
  438. package/src/react/router/hooks/useActive.ts +52 -0
  439. package/src/react/router/hooks/useQueryParams.ts +63 -0
  440. package/src/react/router/hooks/useRouter.ts +20 -0
  441. package/src/react/router/hooks/useRouterState.ts +11 -0
  442. package/src/react/router/index.browser.ts +45 -0
  443. package/src/react/router/index.shared.ts +19 -0
  444. package/src/react/router/index.ts +142 -0
  445. package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
  446. package/src/react/router/primitives/$page.spec.tsx +708 -0
  447. package/src/react/router/primitives/$page.ts +497 -0
  448. package/src/react/router/providers/ReactBrowserProvider.ts +309 -0
  449. package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
  450. package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
  451. package/src/react/router/providers/ReactPageProvider.ts +726 -0
  452. package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
  453. package/src/react/router/providers/ReactServerProvider.ts +558 -0
  454. package/src/react/router/providers/ReactServerTemplateProvider.ts +979 -0
  455. package/src/react/router/providers/SSRManifestProvider.ts +334 -0
  456. package/src/react/router/services/ReactPageServerService.ts +48 -0
  457. package/src/react/router/services/ReactPageService.ts +27 -0
  458. package/src/react/router/services/ReactRouter.ts +262 -0
  459. package/src/react/websocket/hooks/useRoom.tsx +242 -0
  460. package/src/react/websocket/index.ts +7 -0
  461. package/src/redis/__tests__/redis.spec.ts +13 -0
  462. package/src/redis/index.ts +9 -25
  463. package/src/redis/providers/BunRedisProvider.ts +9 -0
  464. package/src/redis/providers/NodeRedisProvider.ts +8 -0
  465. package/src/redis/providers/RedisProvider.ts +16 -0
  466. package/src/retry/index.ts +11 -2
  467. package/src/router/index.ts +15 -0
  468. package/src/scheduler/index.ts +11 -2
  469. package/src/security/__tests__/BasicAuth.spec.ts +2 -0
  470. package/src/security/__tests__/ServerSecurityProvider.spec.ts +13 -5
  471. package/src/security/index.ts +15 -10
  472. package/src/security/interfaces/IssuerResolver.ts +27 -0
  473. package/src/security/primitives/$issuer.ts +55 -0
  474. package/src/security/providers/SecurityProvider.ts +179 -0
  475. package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
  476. package/src/security/providers/ServerSecurityProvider.ts +36 -22
  477. package/src/server/auth/index.ts +12 -7
  478. package/src/server/cache/index.ts +7 -22
  479. package/src/server/compress/index.ts +10 -2
  480. package/src/server/cookies/index.ts +7 -5
  481. package/src/server/cookies/primitives/$cookie.ts +33 -11
  482. package/src/server/core/index.ts +17 -7
  483. package/src/server/core/interfaces/ServerRequest.ts +83 -1
  484. package/src/server/core/primitives/$action.spec.ts +1 -1
  485. package/src/server/core/primitives/$action.ts +8 -3
  486. package/src/server/core/providers/BunHttpServerProvider.ts +1 -1
  487. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +125 -0
  488. package/src/server/core/providers/NodeHttpServerProvider.ts +77 -22
  489. package/src/server/core/providers/ServerLoggerProvider.ts +2 -2
  490. package/src/server/core/providers/ServerProvider.ts +9 -12
  491. package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
  492. package/src/server/core/services/ServerRequestParser.ts +306 -13
  493. package/src/server/cors/index.ts +7 -21
  494. package/src/server/cors/primitives/$cors.ts +6 -2
  495. package/src/server/health/index.ts +8 -2
  496. package/src/server/helmet/index.ts +11 -3
  497. package/src/server/links/atoms/apiLinksAtom.ts +7 -0
  498. package/src/server/links/index.browser.ts +2 -0
  499. package/src/server/links/index.ts +13 -6
  500. package/src/server/metrics/index.ts +10 -3
  501. package/src/server/multipart/index.ts +9 -3
  502. package/src/server/proxy/index.ts +8 -2
  503. package/src/server/rate-limit/index.ts +21 -25
  504. package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
  505. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
  506. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
  507. package/src/server/static/index.ts +8 -2
  508. package/src/server/static/providers/ServerStaticProvider.ts +1 -1
  509. package/src/server/swagger/index.ts +9 -4
  510. package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
  511. package/src/sms/index.ts +9 -5
  512. package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
  513. package/src/sms/providers/LocalSmsProvider.ts +1 -1
  514. package/src/system/index.browser.ts +11 -0
  515. package/src/system/index.ts +62 -0
  516. package/src/{file → system}/providers/FileSystemProvider.ts +16 -0
  517. package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
  518. package/src/system/providers/MemoryShellProvider.ts +164 -0
  519. package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
  520. package/src/{file → system}/providers/NodeFileSystemProvider.ts +36 -0
  521. package/src/system/providers/NodeShellProvider.ts +184 -0
  522. package/src/system/providers/ShellProvider.ts +74 -0
  523. package/src/{file → system}/services/FileDetector.spec.ts +2 -2
  524. package/src/thread/index.ts +11 -2
  525. package/src/topic/core/index.ts +12 -5
  526. package/src/vite/index.ts +3 -2
  527. package/src/vite/tasks/buildClient.ts +2 -8
  528. package/src/vite/tasks/buildServer.ts +84 -21
  529. package/src/vite/tasks/copyAssets.ts +5 -4
  530. package/src/vite/tasks/generateSitemap.ts +64 -23
  531. package/src/vite/tasks/index.ts +0 -2
  532. package/src/vite/tasks/prerenderPages.ts +49 -24
  533. package/src/websocket/index.ts +12 -8
  534. package/dist/file/index.d.ts +0 -839
  535. package/dist/file/index.d.ts.map +0 -1
  536. package/dist/file/index.js.map +0 -1
  537. package/src/cli/assets/indexHtml.ts +0 -15
  538. package/src/cli/assets/mainServerTs.ts +0 -24
  539. package/src/cli/assets/webAppRouterTs.ts +0 -15
  540. package/src/cli/assets/webHelloComponentTsx.ts +0 -16
  541. package/src/cli/commands/format.ts +0 -23
  542. package/src/file/index.ts +0 -43
  543. package/src/vite/helpers/boot.ts +0 -117
  544. package/src/vite/plugins/viteAlephaDev.ts +0 -177
  545. package/src/vite/tasks/devServer.ts +0 -71
  546. package/src/vite/tasks/runAlepha.ts +0 -270
  547. /package/dist/orm/{chunk-DtkW-qnP.js → chunk-DH6iiROE.js} +0 -0
  548. /package/src/cli/{assets → templates}/apiIndexTs.ts +0 -0
  549. /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
  550. /package/src/{file → system}/errors/FileError.ts +0 -0
  551. /package/src/{file → system}/services/FileDetector.ts +0 -0
@@ -32,8 +32,11 @@ export interface JsonSchemaObject {
32
32
  minItems?: number;
33
33
  maxItems?: number;
34
34
  uniqueItems?: boolean;
35
- // TypeBox internal markers (pass through)
36
- "~kind"?: string;
35
+ // Alepha text options (trim, lowercase)
36
+ "~options"?: {
37
+ trim?: boolean;
38
+ lowercase?: boolean;
39
+ };
37
40
  // Not supported
38
41
  oneOf?: JsonSchemaObject[];
39
42
  anyOf?: JsonSchemaObject[];
@@ -55,11 +58,13 @@ export interface JsonSchemaObject {
55
58
  * - Nested objects with required/optional properties
56
59
  * - Arrays with item schemas
57
60
  * - Common validation options: minLength, maxLength, minimum, maximum, pattern
61
+ * - anyOf/oneOf/allOf with nullable patterns (e.g., `anyOf: [type, null]` → `t.nullable(type)`)
62
+ * - Alepha ~options (trim, lowercase) pass-through
58
63
  *
59
64
  * **Not supported:**
60
- * - oneOf, anyOf, allOf, not (composition schemas)
61
65
  * - $ref (references)
62
66
  * - additionalProperties, patternProperties
67
+ * - Complex composition schemas (multiple non-null types in anyOf/oneOf/allOf)
63
68
  *
64
69
  * @param schema - JSON Schema object to convert
65
70
  * @returns TypeBox TSchema
@@ -85,12 +90,7 @@ export interface JsonSchemaObject {
85
90
  * // })
86
91
  * ```
87
92
  */
88
- export function jsonSchemaToTypeBox(schema: JsonSchemaObject): TSchema {
89
- // If it already has TypeBox marker, return as-is
90
- if (schema["~kind"]) {
91
- return schema as unknown as TSchema;
92
- }
93
-
93
+ export function jsonSchemaToTypeBox(schema: JsonSchemaObject): any {
94
94
  // Handle const (literal)
95
95
  if (schema.const !== undefined) {
96
96
  return t.const(schema.const as string | number | boolean);
@@ -115,6 +115,53 @@ export function jsonSchemaToTypeBox(schema: JsonSchemaObject): TSchema {
115
115
  );
116
116
  }
117
117
 
118
+ // Handle anyOf (typically used for nullable types: anyOf: [type, null])
119
+ if (schema.anyOf && Array.isArray(schema.anyOf)) {
120
+ const nullSchema = schema.anyOf.find((s) => s.type === "null");
121
+ const nonNullSchemas = schema.anyOf.filter((s) => s.type !== "null");
122
+
123
+ // If anyOf is [someType, null], convert to t.nullable(someType)
124
+ if (nullSchema && nonNullSchemas.length === 1) {
125
+ const converted = jsonSchemaToTypeBox(nonNullSchemas[0]);
126
+ return t.nullable(converted);
127
+ }
128
+
129
+ // For other anyOf cases, create a union
130
+ return t.union(schema.anyOf.map((s) => jsonSchemaToTypeBox(s)));
131
+ }
132
+
133
+ // Handle allOf (merge schemas)
134
+ if (schema.allOf && Array.isArray(schema.allOf)) {
135
+ const nullSchema = schema.allOf.find((s) => s.type === "null");
136
+ const nonNullSchemas = schema.allOf.filter((s) => s.type !== "null");
137
+
138
+ // If allOf includes null, convert to nullable
139
+ if (nullSchema && nonNullSchemas.length === 1) {
140
+ const converted = jsonSchemaToTypeBox(nonNullSchemas[0]);
141
+ return t.nullable(converted);
142
+ }
143
+
144
+ // For other allOf cases, merge the first non-null schema (simplified)
145
+ if (nonNullSchemas.length > 0) {
146
+ return jsonSchemaToTypeBox(nonNullSchemas[0]);
147
+ }
148
+ }
149
+
150
+ // Handle oneOf (similar to anyOf)
151
+ if (schema.oneOf && Array.isArray(schema.oneOf)) {
152
+ const nullSchema = schema.oneOf.find((s) => s.type === "null");
153
+ const nonNullSchemas = schema.oneOf.filter((s) => s.type !== "null");
154
+
155
+ // If oneOf is [someType, null], convert to t.nullable(someType)
156
+ if (nullSchema && nonNullSchemas.length === 1) {
157
+ const converted = jsonSchemaToTypeBox(nonNullSchemas[0]);
158
+ return t.nullable(converted);
159
+ }
160
+
161
+ // For other oneOf cases, create a union
162
+ return t.union(schema.oneOf.map((s) => jsonSchemaToTypeBox(s)));
163
+ }
164
+
118
165
  // Handle type
119
166
  const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
120
167
 
@@ -158,7 +205,7 @@ function filterUndefined<T extends Record<string, unknown>>(
158
205
  * Convert JSON Schema string type to TypeBox.
159
206
  */
160
207
  function convertString(schema: JsonSchemaObject): TSchema {
161
- const options: TStringOptions = filterUndefined({
208
+ const baseOptions: TStringOptions = filterUndefined({
162
209
  title: schema.title,
163
210
  description: schema.description,
164
211
  default: schema.default as string,
@@ -167,6 +214,11 @@ function convertString(schema: JsonSchemaObject): TSchema {
167
214
  pattern: schema.pattern,
168
215
  });
169
216
 
217
+ // Preserve ~options if present (for t.text() compatibility)
218
+ const options: TStringOptions = schema["~options"]
219
+ ? { ...baseOptions, "~options": schema["~options"] }
220
+ : baseOptions;
221
+
170
222
  switch (schema.format) {
171
223
  case "email":
172
224
  return t.email(options);
@@ -27,6 +27,7 @@ export * from "./primitives/$use.ts";
27
27
  export * from "./providers/AlsProvider.ts";
28
28
  export * from "./providers/CodecManager.ts";
29
29
  export * from "./providers/EventManager.ts";
30
+ export * from "./providers/Json.ts";
30
31
  export * from "./providers/JsonSchemaCodec.ts";
31
32
  export * from "./providers/KeylessJsonSchemaCodec.ts";
32
33
  export * from "./providers/SchemaCodec.ts";
package/src/core/index.ts CHANGED
@@ -22,6 +22,26 @@ export * from "./index.shared.ts";
22
22
 
23
23
  // ---------------------------------------------------------------------------------------------------------------------
24
24
 
25
+ /**
26
+ * | type | quality | stability |
27
+ * |------|---------|-----------|
28
+ * | tooling | epic | stable |
29
+ *
30
+ * Foundation of the entire framework with dependency injection and lifecycle management.
31
+ *
32
+ * **Features:**
33
+ * - Dependency injection for services
34
+ * - Service substitution/mocking
35
+ * - Type-safe environment variable loading with TypeBox schemas
36
+ * - Lifecycle hooks (start, stop, log, etc.)
37
+ * - Module definitions and composition
38
+ * - Request-scoped context access via Async Local Storage (ALS)
39
+ * - Reactive state management with atoms
40
+ * - Cluster mode with automatic worker forking
41
+ * - Full TypeScript generics and type inference
42
+ *
43
+ * @module alepha.core
44
+ */
25
45
  export const AlephaCore = $module({
26
46
  name: "alepha.core",
27
47
  services: [
@@ -4,6 +4,7 @@ import { MODULE } from "../constants/MODULE.ts";
4
4
  import { AlephaError } from "../errors/AlephaError.ts";
5
5
  import type { PrimitiveFactoryLike } from "../helpers/primitive.ts";
6
6
  import type { Service } from "../interfaces/Service.ts";
7
+ import type { Atom } from "./$atom.ts";
7
8
 
8
9
  /**
9
10
  * Wrap Services and Primitives into a Module.
@@ -69,6 +70,12 @@ export const $module = <T extends object = {}>(
69
70
  options = options;
70
71
 
71
72
  register(alepha: Alepha): void {
73
+ if (options.atoms) {
74
+ for (const atom of options.atoms) {
75
+ alepha.store.register(atom);
76
+ }
77
+ }
78
+
72
79
  if (typeof options.register === "function") {
73
80
  options.register(alepha);
74
81
  return;
@@ -134,6 +141,11 @@ export interface ModulePrimitiveOptions {
134
141
  * Again, if you declare 'register', you must handle the registration of ALL services manually.
135
142
  */
136
143
  register?: (alepha: Alepha) => void;
144
+
145
+ /**
146
+ * List of atoms to register in the module.
147
+ */
148
+ atoms?: Array<Atom<any>>;
137
149
  }
138
150
 
139
151
  /**
@@ -285,77 +285,6 @@ describe("EventManager", () => {
285
285
  });
286
286
  });
287
287
 
288
- describe("reverse execution order", () => {
289
- it("should execute hooks in reverse order when reverse option is true", async () => {
290
- const eventManager = new EventManager();
291
- const order: number[] = [];
292
-
293
- eventManager.on("echo", async () => {
294
- order.push(1);
295
- });
296
- eventManager.on("echo", async () => {
297
- order.push(2);
298
- });
299
- eventManager.on("echo", async () => {
300
- order.push(3);
301
- });
302
-
303
- await eventManager.emit("echo", {}, { reverse: true });
304
-
305
- expect(order).toEqual([3, 2, 1]);
306
- });
307
-
308
- it("should reverse priorities correctly", async () => {
309
- const eventManager = new EventManager();
310
- const order: string[] = [];
311
-
312
- eventManager.on("echo", {
313
- callback: async () => {
314
- order.push("first");
315
- },
316
- priority: "first",
317
- });
318
- eventManager.on("echo", async () => {
319
- order.push("normal");
320
- });
321
- eventManager.on("echo", {
322
- callback: async () => {
323
- order.push("last");
324
- },
325
- priority: "last",
326
- });
327
-
328
- await eventManager.emit("echo", {}, { reverse: true });
329
-
330
- // Reversed: last -> normal -> first
331
- expect(order).toEqual(["last", "normal", "first"]);
332
- });
333
-
334
- it("should work with stop lifecycle event", async () => {
335
- const alepha = Alepha.create();
336
- const order: string[] = [];
337
-
338
- alepha.events.on("start", async () => {
339
- order.push("start-1");
340
- });
341
- alepha.events.on("start", async () => {
342
- order.push("start-2");
343
- });
344
- alepha.events.on("stop", async () => {
345
- order.push("stop-1");
346
- });
347
- alepha.events.on("stop", async () => {
348
- order.push("stop-2");
349
- });
350
-
351
- await alepha.start();
352
- await alepha.stop();
353
-
354
- // Start should be in order, stop should be reversed
355
- expect(order).toEqual(["start-1", "start-2", "stop-2", "stop-1"]);
356
- });
357
- });
358
-
359
288
  describe("error handling", () => {
360
289
  it("should throw error when callback throws", async () => {
361
290
  const eventManager = new EventManager();
@@ -189,13 +189,6 @@ export class EventManager {
189
189
  func: T,
190
190
  payload: Hooks[T],
191
191
  options: {
192
- /**
193
- * If true, the hooks will be executed in reverse order.
194
- * This is useful for "stop" hooks that should be executed in reverse order.
195
- *
196
- * @default false
197
- */
198
- reverse?: boolean;
199
192
  /**
200
193
  * If true, the hooks will be logged with their execution time.
201
194
  *
@@ -216,8 +209,8 @@ export class EventManager {
216
209
  return;
217
210
  }
218
211
 
219
- // Fast path: single listener, no logging, no reverse
220
- if (events.length === 1 && !options.log && !options.reverse) {
212
+ // Fast path: single listener, no logging
213
+ if (events.length === 1 && !options.log) {
221
214
  const hook = events[0];
222
215
  try {
223
216
  const result = hook.callback(payload);
@@ -244,12 +237,7 @@ export class EventManager {
244
237
  this.log?.trace(`${String(func)} ...`);
245
238
  }
246
239
 
247
- let eventList = events;
248
- if (options.reverse) {
249
- eventList = events.toReversed();
250
- }
251
-
252
- for (const hook of eventList) {
240
+ for (const hook of events) {
253
241
  const name = hook.caller?.name ?? "unknown";
254
242
  if (options.log) {
255
243
  ctx.now2 = performance.now();
@@ -4,18 +4,6 @@
4
4
  * Used across the codebase via dependency injection.
5
5
  */
6
6
  export class Json {
7
- public stringify(
8
- value: any,
9
- replacer?: (this: any, key: string, value: any) => any,
10
- space?: string | number,
11
- ): string {
12
- return JSON.stringify(value, replacer, space);
13
- }
14
-
15
- public parse(
16
- text: string,
17
- reviver?: (this: any, key: string, value: any) => any,
18
- ) {
19
- return JSON.parse(text, reviver);
20
- }
7
+ stringify = JSON.stringify;
8
+ parse = JSON.parse;
21
9
  }
@@ -1,5 +1,6 @@
1
1
  import { Alepha, t } from "alepha";
2
2
  import { describe, test } from "vitest";
3
+ import { KeylessJsonSchemaCodec } from "./KeylessJsonSchemaCodec.ts";
3
4
 
4
5
  describe("KeylessJsonSchemaCodec", () => {
5
6
  describe("Basic types", () => {
@@ -618,4 +619,260 @@ describe("KeylessJsonSchemaCodec", () => {
618
619
  expect(keylessSize).toBeLessThan(jsonSize);
619
620
  });
620
621
  });
622
+
623
+ describe("Safe Mode (Interpreted)", () => {
624
+ test("should work correctly in safe mode", async ({ expect }) => {
625
+ const alepha = Alepha.create();
626
+ const codec = alepha.inject(KeylessJsonSchemaCodec);
627
+
628
+ // Force safe mode (no Function compilation)
629
+ codec.configure({ useFunctionCompilation: false });
630
+
631
+ const schema = t.object({
632
+ name: t.text(),
633
+ age: t.integer(),
634
+ active: t.boolean(),
635
+ });
636
+
637
+ const data = {
638
+ name: "Alice",
639
+ age: 30,
640
+ active: true,
641
+ };
642
+
643
+ const encoded = codec.encodeToString(schema, data);
644
+ expect(encoded).toBe('["Alice",30,true]');
645
+
646
+ const decoded = codec.decode(schema, encoded);
647
+ expect(decoded).toEqual(data);
648
+ });
649
+
650
+ test("should handle nested objects in safe mode", async ({ expect }) => {
651
+ const alepha = Alepha.create();
652
+ const codec = alepha.inject(KeylessJsonSchemaCodec);
653
+
654
+ codec.configure({ useFunctionCompilation: false });
655
+
656
+ const schema = t.object({
657
+ user: t.object({
658
+ name: t.text(),
659
+ profile: t.object({
660
+ bio: t.text(),
661
+ age: t.integer(),
662
+ }),
663
+ }),
664
+ });
665
+
666
+ const data = {
667
+ user: {
668
+ name: "Alice",
669
+ profile: {
670
+ bio: "Developer",
671
+ age: 30,
672
+ },
673
+ },
674
+ };
675
+
676
+ const encoded = codec.encodeToString(schema, data);
677
+ expect(encoded).toBe('[["Alice",["Developer",30]]]');
678
+
679
+ const decoded = codec.decode(schema, encoded);
680
+ expect(decoded).toEqual(data);
681
+ });
682
+
683
+ test("should handle arrays of objects in safe mode", async ({ expect }) => {
684
+ const alepha = Alepha.create();
685
+ const codec = alepha.inject(KeylessJsonSchemaCodec);
686
+
687
+ codec.configure({ useFunctionCompilation: false });
688
+
689
+ const schema = t.object({
690
+ users: t.array(
691
+ t.object({
692
+ name: t.text(),
693
+ age: t.integer(),
694
+ }),
695
+ ),
696
+ });
697
+
698
+ const data = {
699
+ users: [
700
+ { name: "Alice", age: 30 },
701
+ { name: "Bob", age: 25 },
702
+ ],
703
+ };
704
+
705
+ const encoded = codec.encodeToString(schema, data);
706
+ const decoded = codec.decode(schema, encoded);
707
+ expect(decoded).toEqual(data);
708
+ });
709
+
710
+ test("should handle optional fields in safe mode", async ({ expect }) => {
711
+ const alepha = Alepha.create();
712
+ const codec = alepha.inject(KeylessJsonSchemaCodec);
713
+
714
+ codec.configure({ useFunctionCompilation: false });
715
+
716
+ const schema = t.object({
717
+ name: t.text(),
718
+ bio: t.optional(t.text()),
719
+ });
720
+
721
+ // With optional field
722
+ const dataWithBio = { name: "Alice", bio: "Developer" };
723
+ const encodedWith = codec.encodeToString(schema, dataWithBio);
724
+ const decodedWith = codec.decode(schema, encodedWith);
725
+ expect(decodedWith).toEqual(dataWithBio);
726
+
727
+ // Without optional field
728
+ const dataWithoutBio = { name: "Bob" };
729
+ const encodedWithout = codec.encodeToString(schema, dataWithoutBio);
730
+ const decodedWithout = codec.decode<{ name: string; bio?: string }>(
731
+ schema,
732
+ encodedWithout,
733
+ );
734
+ expect(decodedWithout.name).toBe("Bob");
735
+ expect(decodedWithout.bio).toBeUndefined();
736
+ });
737
+
738
+ test("should handle nullable fields in safe mode", async ({ expect }) => {
739
+ const alepha = Alepha.create();
740
+ const codec = alepha.inject(KeylessJsonSchemaCodec);
741
+
742
+ codec.configure({ useFunctionCompilation: false });
743
+
744
+ const schema = t.object({
745
+ name: t.text(),
746
+ deletedAt: t.nullable(t.datetime()),
747
+ });
748
+
749
+ // With null value
750
+ const dataNull = { name: "Alice", deletedAt: null };
751
+ const encodedNull = codec.encodeToString(schema, dataNull);
752
+ const decodedNull = codec.decode<{
753
+ name: string;
754
+ deletedAt: string | null;
755
+ }>(schema, encodedNull);
756
+ expect(decodedNull.deletedAt).toBeNull();
757
+
758
+ // With non-null value
759
+ const dataValue = { name: "Bob", deletedAt: "2024-01-15T10:00:00Z" };
760
+ const encodedValue = codec.encodeToString(schema, dataValue);
761
+ const decodedValue = codec.decode(schema, encodedValue);
762
+ expect(decodedValue).toEqual(dataValue);
763
+ });
764
+ });
765
+
766
+ describe("Compiled Mode (Function)", () => {
767
+ test("should work correctly in compiled mode", async ({ expect }) => {
768
+ const alepha = Alepha.create();
769
+ const codec = alepha.inject(KeylessJsonSchemaCodec);
770
+
771
+ // Force compiled mode
772
+ codec.configure({ useFunctionCompilation: true });
773
+
774
+ const schema = t.object({
775
+ name: t.text(),
776
+ age: t.integer(),
777
+ active: t.boolean(),
778
+ });
779
+
780
+ const data = {
781
+ name: "Alice",
782
+ age: 30,
783
+ active: true,
784
+ };
785
+
786
+ const encoded = codec.encodeToString(schema, data);
787
+ expect(encoded).toBe('["Alice",30,true]');
788
+
789
+ const decoded = codec.decode(schema, encoded);
790
+ expect(decoded).toEqual(data);
791
+ });
792
+
793
+ test("should produce same results as safe mode", async ({ expect }) => {
794
+ const alepha = Alepha.create();
795
+
796
+ const codecSafe = alepha.inject(KeylessJsonSchemaCodec);
797
+ codecSafe.configure({ useFunctionCompilation: false });
798
+
799
+ // Create a second Alepha instance for the compiled codec
800
+ const alepha2 = Alepha.create();
801
+ const codecCompiled = alepha2.inject(KeylessJsonSchemaCodec);
802
+ codecCompiled.configure({ useFunctionCompilation: true });
803
+
804
+ const schema = t.object({
805
+ user: t.object({
806
+ name: t.text(),
807
+ age: t.integer(),
808
+ }),
809
+ tags: t.array(t.text()),
810
+ active: t.boolean(),
811
+ });
812
+
813
+ const data = {
814
+ user: { name: "Alice", age: 30 },
815
+ tags: ["dev", "typescript"],
816
+ active: true,
817
+ };
818
+
819
+ const encodedSafe = codecSafe.encodeToString(schema, data);
820
+ const encodedCompiled = codecCompiled.encodeToString(schema, data);
821
+
822
+ // Both modes should produce the same output
823
+ expect(encodedSafe).toBe(encodedCompiled);
824
+
825
+ const decodedSafe = codecSafe.decode(schema, encodedSafe);
826
+ const decodedCompiled = codecCompiled.decode(schema, encodedCompiled);
827
+
828
+ // Both modes should decode to the same result
829
+ expect(decodedSafe).toEqual(data);
830
+ expect(decodedCompiled).toEqual(data);
831
+ });
832
+ });
833
+
834
+ describe("Configuration", () => {
835
+ test("should allow configuring options", async ({ expect }) => {
836
+ const alepha = Alepha.create();
837
+ const codec = alepha.inject(KeylessJsonSchemaCodec);
838
+
839
+ // Configure all options
840
+ codec.configure({
841
+ useFunctionCompilation: false,
842
+ maxArrayLength: 100,
843
+ maxStringLength: 1000,
844
+ maxDepth: 10,
845
+ });
846
+
847
+ // Test that configuration works by encoding/decoding
848
+ const schema = t.object({ name: t.text() });
849
+ const data = { name: "test" };
850
+
851
+ const encoded = codec.encodeToString(schema, data);
852
+ const decoded = codec.decode(schema, encoded);
853
+
854
+ expect(decoded).toEqual(data);
855
+ });
856
+
857
+ test("should clear cache when compilation mode changes", async ({
858
+ expect,
859
+ }) => {
860
+ const alepha = Alepha.create();
861
+ const codec = alepha.inject(KeylessJsonSchemaCodec);
862
+
863
+ const schema = t.object({ name: t.text() });
864
+ const data = { name: "test" };
865
+
866
+ // Use compiled mode first
867
+ codec.configure({ useFunctionCompilation: true });
868
+ const encoded1 = codec.encodeToString(schema, data);
869
+
870
+ // Switch to safe mode (cache should be cleared)
871
+ codec.configure({ useFunctionCompilation: false });
872
+ const encoded2 = codec.encodeToString(schema, data);
873
+
874
+ // Both should produce the same result
875
+ expect(encoded1).toBe(encoded2);
876
+ });
877
+ });
621
878
  });