nucleus-core-ts 0.9.993 → 0.10.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 (294) hide show
  1. package/README.md +177 -0
  2. package/bin/cli.ts +136 -131
  3. package/bin/lib/commands/add.ts +26 -13
  4. package/bin/lib/commands/dev.ts +57 -18
  5. package/bin/lib/commands/doctor.ts +22 -9
  6. package/bin/lib/commands/init.ts +31 -12
  7. package/bin/lib/commands/validate.ts +34 -10
  8. package/bin/lib/config-builder.ts +24 -6
  9. package/bin/lib/env.ts +10 -2
  10. package/bin/lib/presets.ts +6 -2
  11. package/bin/lib/schema.ts +18 -5
  12. package/bin/lib/templates.ts +26 -17
  13. package/bin/lib/ui.ts +5 -2
  14. package/dist/.build-ok +1 -1
  15. package/dist/bin/lib/commands/add.d.ts +12 -0
  16. package/dist/bin/lib/commands/dev.d.ts +12 -0
  17. package/dist/bin/lib/commands/doctor.d.ts +6 -0
  18. package/dist/bin/lib/config-builder.d.ts +5 -0
  19. package/dist/client.js +2 -2
  20. package/dist/dist/index.d.ts +49 -623
  21. package/dist/fe/components/AbstractAnimatedBackground/index.js +2 -1
  22. package/dist/index.d.ts +13 -3
  23. package/dist/index.js +44 -1473
  24. package/dist/nucleus.config.d.ts +3 -2
  25. package/dist/server.d.ts +27 -0
  26. package/dist/server.js +609 -0
  27. package/dist/src/Client/ApiCaller/deriveAuthEndpoints.d.ts +108 -0
  28. package/dist/src/Client/ApiCaller/generator.d.ts +32 -1
  29. package/dist/src/Client/ApiCaller/index.d.ts +1 -1
  30. package/dist/src/Client/ApiCaller/system-tables.d.ts +5 -5
  31. package/dist/src/Client/ApiCaller/types.d.ts +158 -115
  32. package/dist/src/Client/Proxy/httpProxy.js +89 -89
  33. package/dist/src/Client/Proxy/synthesizedAuth.js +10 -10
  34. package/dist/src/Client/Proxy/wsProxy.js +41 -41
  35. package/dist/src/Client/PubSub/usePubSub.js +97 -97
  36. package/dist/src/Client/PubSub/waitForReturn.js +29 -29
  37. package/dist/src/Client/Upload/progress.js +31 -31
  38. package/dist/src/Client/Upload/types.js +7 -7
  39. package/dist/src/Client/Upload/upload.js +21 -21
  40. package/dist/src/Managers/Redis/index.d.ts +18 -0
  41. package/dist/src/Nucleus/index.d.ts +71 -0
  42. package/dist/src/Nucleus/publicRoutes.d.ts +48 -0
  43. package/dist/src/Nucleus/routes/auth/admin/changeUserId.d.ts +2 -0
  44. package/dist/src/Nucleus/routes/auth/admin/createUser.d.ts +8 -0
  45. package/dist/src/Nucleus/routes/auth/admin/hardDeleteUser.d.ts +2 -0
  46. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/impersonate.d.ts +3 -30
  47. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/passwordAdmin.d.ts +1 -29
  48. package/dist/src/Nucleus/routes/auth/admin/requireGodmin.d.ts +33 -0
  49. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/roleAssignAuthz.d.ts +1 -3
  50. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/userState.d.ts +1 -29
  51. package/dist/src/Nucleus/routes/auth/apiKeys/index.d.ts +4 -0
  52. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/captcha/index.d.ts +1 -29
  53. package/dist/src/Nucleus/routes/auth/check/index.d.ts +8 -0
  54. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/activateUsers.d.ts +2 -3
  55. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/bulkCreate.d.ts +2 -3
  56. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/create.d.ts +2 -3
  57. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/deactivateUsers.d.ts +2 -3
  58. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/deleteUsers.d.ts +2 -3
  59. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/detail.d.ts +2 -3
  60. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/exportUsers.d.ts +2 -3
  61. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/list.d.ts +2 -3
  62. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/remove.d.ts +2 -3
  63. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/update.d.ts +2 -3
  64. package/dist/src/Nucleus/routes/auth/cohort/index.d.ts +2 -0
  65. package/dist/src/Nucleus/routes/auth/cohort/types.d.ts +55 -0
  66. package/dist/src/Nucleus/routes/auth/cohort/utils.d.ts +43 -0
  67. package/dist/src/Nucleus/routes/auth/emailVerification/index.d.ts +9 -0
  68. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/index.d.ts +6 -4
  69. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/invite/index.d.ts +1 -29
  70. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/index.d.ts +1 -29
  71. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/logout/index.d.ts +1 -29
  72. package/dist/src/Nucleus/routes/auth/magicLink/index.d.ts +25 -0
  73. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/me/index.d.ts +1 -29
  74. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/oauth/index.d.ts +1 -29
  75. package/dist/src/Nucleus/routes/auth/passwordChange/index.d.ts +4 -0
  76. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordReset/index.d.ts +1 -29
  77. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordSet/index.d.ts +1 -29
  78. package/dist/src/Nucleus/routes/auth/refresh/index.d.ts +11 -0
  79. package/dist/src/Nucleus/routes/auth/refresh/sessionBinding.d.ts +29 -0
  80. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/register/index.d.ts +3 -31
  81. package/dist/src/Nucleus/routes/auth/sessions/index.d.ts +4 -0
  82. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/types.d.ts +22 -0
  83. package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/webauthn/index.d.ts +3 -31
  84. package/dist/src/{ElysiaPlugin → Nucleus}/routes/authorization/index.d.ts +1 -29
  85. package/dist/src/Nucleus/routes/backup/index.d.ts +7 -0
  86. package/dist/src/Nucleus/routes/backup/types.d.ts +24 -0
  87. package/dist/src/Nucleus/routes/chat/conversations.routes.d.ts +3 -0
  88. package/dist/src/Nucleus/routes/chat/index.d.ts +12 -0
  89. package/dist/src/Nucleus/routes/chat/messages.routes.d.ts +3 -0
  90. package/dist/src/Nucleus/routes/config/helpers.d.ts +152 -0
  91. package/dist/src/Nucleus/routes/config/index.d.ts +2 -0
  92. package/dist/src/{ElysiaPlugin → Nucleus}/routes/config/types.d.ts +12 -4
  93. package/dist/src/Nucleus/routes/domain/hostnames.d.ts +8 -0
  94. package/dist/src/Nucleus/routes/domain/index.d.ts +5 -0
  95. package/dist/src/Nucleus/routes/domain/registrations.d.ts +8 -0
  96. package/dist/src/Nucleus/routes/domain/resolve.d.ts +7 -0
  97. package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/index.d.ts +22 -2
  98. package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/utils.d.ts +1 -1
  99. package/dist/src/{ElysiaPlugin → Nucleus}/routes/integrations/index.d.ts +1 -29
  100. package/dist/src/{ElysiaPlugin → Nucleus}/routes/integrations/inspectRoutes.d.ts +2 -29
  101. package/dist/src/{ElysiaPlugin → Nucleus}/routes/monitoring/index.d.ts +1 -29
  102. package/dist/src/{ElysiaPlugin → Nucleus}/routes/monitoring/live.d.ts +1 -29
  103. package/dist/src/{ElysiaPlugin → Nucleus}/routes/monitoring/serverLogs.d.ts +1 -29
  104. package/dist/src/Nucleus/routes/monitoring/sse.d.ts +28 -0
  105. package/dist/src/{ElysiaPlugin → Nucleus}/routes/notification/index.d.ts +1 -29
  106. package/dist/src/Nucleus/routes/payment/index.d.ts +4 -0
  107. package/dist/src/Nucleus/routes/payment/marketplace/index.d.ts +5 -0
  108. package/dist/src/Nucleus/routes/payment/marketplace/payouts.d.ts +3 -0
  109. package/dist/src/Nucleus/routes/payment/marketplace/splits.d.ts +3 -0
  110. package/dist/src/{ElysiaPlugin → Nucleus}/routes/payment/webhook.d.ts +16 -2
  111. package/dist/src/Nucleus/routes/pubsub/handshakeAuth.d.ts +77 -0
  112. package/dist/src/{ElysiaPlugin → Nucleus}/routes/pubsub/index.d.ts +16 -29
  113. package/dist/src/Nucleus/routes/pubsub/refusalReason.d.ts +49 -0
  114. package/dist/src/{ElysiaPlugin → Nucleus}/routes/pubsub/types.d.ts +7 -1
  115. package/dist/src/Nucleus/routes/secrets/index.d.ts +11 -0
  116. package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/adminGuard.d.ts +14 -7
  117. package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/godminGuard.d.ts +1 -1
  118. package/dist/src/Nucleus/routes/storage/boundedStream.d.ts +28 -0
  119. package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/cdn.d.ts +16 -29
  120. package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/helpers.d.ts +15 -0
  121. package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/index.d.ts +1 -1
  122. package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/resumable/index.d.ts +2 -30
  123. package/dist/src/Nucleus/routes/tenant/check-subdomain.d.ts +6 -0
  124. package/dist/src/{ElysiaPlugin → Nucleus}/routes/tenant/index.d.ts +3 -2
  125. package/dist/src/Nucleus/routes/tenant/manage.d.ts +6 -0
  126. package/dist/src/Nucleus/routes/tenant/provision.d.ts +2 -0
  127. package/dist/src/Nucleus/routes/tenant/self-signup.d.ts +2 -0
  128. package/dist/src/{ElysiaPlugin → Nucleus}/routes/verification/index.d.ts +1 -29
  129. package/dist/src/Server/NucleusServer.d.ts +141 -0
  130. package/dist/src/Server/createNucleusServer.d.ts +75 -0
  131. package/dist/src/Server/defineRoute.d.ts +185 -0
  132. package/dist/src/Server/fileSchema.d.ts +35 -0
  133. package/dist/src/Server/formats.d.ts +4 -0
  134. package/dist/src/Server/inboundGuard.d.ts +26 -0
  135. package/dist/src/Server/internalHeaders.d.ts +26 -0
  136. package/dist/src/Server/openapi.d.ts +52 -0
  137. package/dist/src/Server/parseBody.d.ts +39 -0
  138. package/dist/src/Server/response.d.ts +72 -0
  139. package/dist/src/Server/routeCollector.d.ts +51 -0
  140. package/dist/src/Server/routeMount.d.ts +104 -0
  141. package/dist/src/Server/routeRecording.d.ts +107 -0
  142. package/dist/src/Server/router.d.ts +140 -0
  143. package/dist/src/Server/testApp.d.ts +82 -0
  144. package/dist/src/Server/validate.d.ts +76 -0
  145. package/dist/src/Server/websocket.d.ts +70 -0
  146. package/dist/src/Services/Authorization/activeRows.d.ts +33 -0
  147. package/dist/src/Services/Backup/BackupService.d.ts +22 -0
  148. package/dist/src/Services/Chat/ChatService.d.ts +3 -1
  149. package/dist/src/Services/Chat/attachmentAccess.d.ts +28 -0
  150. package/dist/src/Services/Chat/index.d.ts +1 -0
  151. package/dist/src/Services/Chat/types.d.ts +13 -0
  152. package/dist/src/Services/Logger/auditTaxonomy.d.ts +1 -1
  153. package/dist/src/Services/Logger/index.d.ts +1 -1
  154. package/dist/src/Services/Notification/index.d.ts +37 -2
  155. package/dist/src/Services/Notification/types.d.ts +17 -0
  156. package/dist/src/Services/SchemaTables/resolveEntities.d.ts +1 -1
  157. package/dist/src/Services/WebAuthn/types.d.ts +15 -0
  158. package/dist/src/types.d.ts +22 -2
  159. package/infra/templates/backend/package.json +0 -1
  160. package/infra/templates/backend/src/index.ts +25 -22
  161. package/package.json +9 -6
  162. package/public/components/docs/content/advanced.ts +37 -34
  163. package/public/components/docs/content/gettingStarted.ts +59 -11
  164. package/schemas/config.nucleus.json +54 -235
  165. package/schemas/nucleus.tables.schema.json +1 -3
  166. package/schemas/table.schema.json +22 -115
  167. package/scripts/build.ts +21 -4
  168. package/scripts/generate-schema.ts +739 -739
  169. package/scripts/importCase.test.ts +174 -0
  170. package/scripts/packagedScripts.test.ts +4 -1
  171. package/scripts/scaffoldParity.test.ts +126 -0
  172. package/scripts/skillCitations.test.ts +106 -0
  173. package/src/Services/Logger/auditTaxonomy.ts +1 -1
  174. package/src/Services/SchemaTables/resolveEntities.ts +1 -1
  175. package/src/system.tables.json +5527 -5527
  176. package/dist/src/ElysiaPlugin/index.d.ts +0 -23
  177. package/dist/src/ElysiaPlugin/publicRoutes.d.ts +0 -8
  178. package/dist/src/ElysiaPlugin/routes/auth/admin/changeUserId.d.ts +0 -30
  179. package/dist/src/ElysiaPlugin/routes/auth/admin/createUser.d.ts +0 -36
  180. package/dist/src/ElysiaPlugin/routes/auth/admin/hardDeleteUser.d.ts +0 -30
  181. package/dist/src/ElysiaPlugin/routes/auth/admin/requireGodmin.d.ts +0 -17
  182. package/dist/src/ElysiaPlugin/routes/auth/apiKeys/index.d.ts +0 -3
  183. package/dist/src/ElysiaPlugin/routes/auth/check/index.d.ts +0 -62
  184. package/dist/src/ElysiaPlugin/routes/auth/cohort/index.d.ts +0 -30
  185. package/dist/src/ElysiaPlugin/routes/auth/cohort/types.d.ts +0 -26
  186. package/dist/src/ElysiaPlugin/routes/auth/cohort/utils.d.ts +0 -21
  187. package/dist/src/ElysiaPlugin/routes/auth/emailVerification/index.d.ts +0 -37
  188. package/dist/src/ElysiaPlugin/routes/auth/magicLink/index.d.ts +0 -53
  189. package/dist/src/ElysiaPlugin/routes/auth/passwordChange/index.d.ts +0 -32
  190. package/dist/src/ElysiaPlugin/routes/auth/refresh/index.d.ts +0 -38
  191. package/dist/src/ElysiaPlugin/routes/auth/sessions/index.d.ts +0 -32
  192. package/dist/src/ElysiaPlugin/routes/backup/index.d.ts +0 -35
  193. package/dist/src/ElysiaPlugin/routes/backup/types.d.ts +0 -14
  194. package/dist/src/ElysiaPlugin/routes/chat/conversations.routes.d.ts +0 -31
  195. package/dist/src/ElysiaPlugin/routes/chat/index.d.ts +0 -40
  196. package/dist/src/ElysiaPlugin/routes/chat/messages.routes.d.ts +0 -31
  197. package/dist/src/ElysiaPlugin/routes/config/helpers.d.ts +0 -60
  198. package/dist/src/ElysiaPlugin/routes/config/index.d.ts +0 -30
  199. package/dist/src/ElysiaPlugin/routes/domain/hostnames.d.ts +0 -36
  200. package/dist/src/ElysiaPlugin/routes/domain/index.d.ts +0 -4
  201. package/dist/src/ElysiaPlugin/routes/domain/registrations.d.ts +0 -36
  202. package/dist/src/ElysiaPlugin/routes/domain/resolve.d.ts +0 -35
  203. package/dist/src/ElysiaPlugin/routes/payment/index.d.ts +0 -32
  204. package/dist/src/ElysiaPlugin/routes/payment/marketplace/index.d.ts +0 -4
  205. package/dist/src/ElysiaPlugin/routes/payment/marketplace/payouts.d.ts +0 -31
  206. package/dist/src/ElysiaPlugin/routes/payment/marketplace/splits.d.ts +0 -31
  207. package/dist/src/ElysiaPlugin/routes/pubsub/refusalReason.d.ts +0 -18
  208. package/dist/src/ElysiaPlugin/routes/secrets/index.d.ts +0 -39
  209. package/dist/src/ElysiaPlugin/routes/tenant/check-subdomain.d.ts +0 -34
  210. package/dist/src/ElysiaPlugin/routes/tenant/manage.d.ts +0 -34
  211. package/dist/src/ElysiaPlugin/routes/tenant/provision.d.ts +0 -30
  212. package/dist/src/ElysiaPlugin/routes/tenant/self-signup.d.ts +0 -30
  213. package/dist/src/ElysiaPlugin/swagger.d.ts +0 -27
  214. /package/dist/src/{ElysiaPlugin → Nucleus}/authRouteClassifier.d.ts +0 -0
  215. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/accountState.d.ts +0 -0
  216. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/createUserAuthz.d.ts +0 -0
  217. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/lockoutState.d.ts +0 -0
  218. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/resolveMutationSchema.d.ts +0 -0
  219. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/rotationPlan.d.ts +0 -0
  220. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/apiKeys/types.d.ts +0 -0
  221. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/assignDefaultRole.d.ts +0 -0
  222. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/schemas.d.ts +0 -0
  223. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/emailExempt.d.ts +0 -0
  224. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/emailLinks/index.d.ts +0 -0
  225. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/fetchUserRolesAndClaims.d.ts +0 -0
  226. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/impersonationCookies.d.ts +0 -0
  227. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/deviceInfo.d.ts +0 -0
  228. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/identifier.d.ts +0 -0
  229. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/identifierQuery.d.ts +0 -0
  230. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/notifyDecision.d.ts +0 -0
  231. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/types.d.ts +0 -0
  232. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/utils.d.ts +0 -0
  233. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/logout/types.d.ts +0 -0
  234. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/logout/utils.d.ts +0 -0
  235. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/magicLink/types.d.ts +0 -0
  236. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/magicLink/utils.d.ts +0 -0
  237. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/oauth/applyProfileSync.d.ts +0 -0
  238. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordChange/types.d.ts +0 -0
  239. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordChange/utils.d.ts +0 -0
  240. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordReset/outcome.d.ts +0 -0
  241. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordReset/types.d.ts +0 -0
  242. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordReset/utils.d.ts +0 -0
  243. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordSet/types.d.ts +0 -0
  244. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/refresh/types.d.ts +0 -0
  245. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/refresh/utils.d.ts +0 -0
  246. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/register/types.d.ts +0 -0
  247. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/register/utils.d.ts +0 -0
  248. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/resolveAuthTables.d.ts +0 -0
  249. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/sessions/types.d.ts +0 -0
  250. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/sessions/utils.d.ts +0 -0
  251. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/webauthn/cookies.d.ts +0 -0
  252. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/webauthn/types.d.ts +0 -0
  253. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/chat/helpers.d.ts +0 -0
  254. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/chat/types.d.ts +0 -0
  255. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/domain/types.d.ts +0 -0
  256. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/anonymousCreate.d.ts +0 -0
  257. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/createScope.d.ts +0 -0
  258. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/relationAuthz.d.ts +0 -0
  259. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/types.d.ts +0 -0
  260. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/userRoleWrite.d.ts +0 -0
  261. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/index.d.ts +0 -0
  262. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/integrations/inspect.d.ts +0 -0
  263. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/integrations/repository.d.ts +0 -0
  264. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/integrations/types.d.ts +0 -0
  265. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/payment/marketplace/types.d.ts +0 -0
  266. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/payment/types.d.ts +0 -0
  267. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/payment/validation.d.ts +0 -0
  268. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/pubsub/ack-manager.d.ts +0 -0
  269. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/pubsub/client-manager.d.ts +0 -0
  270. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/pubsub/frame.d.ts +0 -0
  271. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/secrets/types.d.ts +0 -0
  272. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/basePathCollision.d.ts +0 -0
  273. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/bodyCeiling.d.ts +0 -0
  274. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/clientIp.d.ts +0 -0
  275. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/csrf.d.ts +0 -0
  276. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/redact.d.ts +0 -0
  277. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/requestLimits.d.ts +0 -0
  278. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/sensitiveColumns.d.ts +0 -0
  279. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/sensitiveTables.d.ts +0 -0
  280. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/tenantBinding.d.ts +0 -0
  281. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/writeLock.d.ts +0 -0
  282. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/cpuBudget.d.ts +0 -0
  283. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/file-record.d.ts +0 -0
  284. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/imageTransform.d.ts +0 -0
  285. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/mediaPostProcess.d.ts +0 -0
  286. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/pdfTransform.d.ts +0 -0
  287. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/resumable/session.d.ts +0 -0
  288. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/resumable/store.d.ts +0 -0
  289. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/videoTransform.d.ts +0 -0
  290. /package/dist/src/{ElysiaPlugin → Nucleus}/routes/tenant/types.d.ts +0 -0
  291. /package/dist/src/{ElysiaPlugin → Nucleus}/runtime.d.ts +0 -0
  292. /package/dist/src/{ElysiaPlugin → Nucleus}/schemaReconcile.d.ts +0 -0
  293. /package/dist/src/{ElysiaPlugin → Nucleus}/utils.d.ts +0 -0
  294. /package/dist/src/{ElysiaPlugin → Nucleus}/validationError.d.ts +0 -0
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # nucleus-core-ts
2
+
3
+ A TypeScript framework for multi-tenant APIs on Bun: authentication and
4
+ authorization, entity CRUD generated from a config file, storage, payments,
5
+ chat, pub/sub, monitoring — and a typed client generated from the same
6
+ declarations the server serves.
7
+
8
+ ```bash
9
+ bunx nucleus-core-ts init
10
+ ```
11
+
12
+ ## Where the documentation is
13
+
14
+ This file is an index, not a manual. The maintained documentation is:
15
+
16
+ - **`.claude/skills/`** — 21 skills, one per subsystem (`nucleus-authentication`,
17
+ `nucleus-entities`, `nucleus-payment`, …). These are the reference.
18
+ - **`public/`** — the docs site shipped in the package.
19
+ - **`src/types.ts`** — the configuration surface, and the last word when a
20
+ document and the code disagree.
21
+
22
+ Other `.md` files in the repo are working notes or historical audit records.
23
+ `docs/` in particular is an archive: it records what was true when it was
24
+ written and is not updated.
25
+
26
+ ## Entry points
27
+
28
+ | import | what |
29
+ |---|---|
30
+ | `nucleus-core-ts` | the server plugin and the services it lends a host app |
31
+ | `nucleus-core-ts/client` | the generated, typed API client |
32
+ | `nucleus-core-ts/fe` | React components (auth pages, admin panels) |
33
+ | `nucleus-core-ts/proxy` | server-side proxy client |
34
+
35
+ `client`, `fe` and `proxy` are independent of the HTTP layer below.
36
+
37
+ ## The HTTP layer is ours
38
+
39
+ The server half used to run on [Elysia](https://elysiajs.com). It does not any
40
+ more, and not partially: there is no adapter, no swagger plugin, no static
41
+ plugin, no peer dependency, no import anywhere in the source, and nothing in
42
+ `node_modules`. The reason was never performance — nucleus-core is a product of
43
+ its own, and a product's HTTP layer, type system and public API shape should not
44
+ belong to a third project we do not control.
45
+
46
+ **What that means, concretely:**
47
+
48
+ - **One entry point.** `createNucleusServer({ config, port })` serves the whole
49
+ product on `Bun.serve`. `NucleusElysiaPlugin` is gone; a consumer that used it
50
+ changes its boot line and its route modules and keeps everything else.
51
+
52
+ - **A host brings its own routes.** This is what took longest and it is what
53
+ every consumer was blocked on:
54
+
55
+ ```ts
56
+ await createNucleusServer({
57
+ config: { options, schema, relations },
58
+ port: 3000,
59
+ routes: [{ prefix: '/reports', routes: [defineRoute({ … })] }],
60
+ onRequest: (ctx) => Response | undefined, // BEFORE the inbound guard and auth
61
+ socket: defineWebSocketRoute({ … }),
62
+ onStop: [async () => { /* close your pool */ }],
63
+ })
64
+ ```
65
+
66
+ A group's routes sit behind nucleus's auth, exactly as they did when mounted on
67
+ an Elysia carrying the plugin — that is the inherited contract. Something that
68
+ must answer without authentication goes in `onRequest`, which runs first: a
69
+ public webhook that needs a verbatim body, an anonymous share link.
70
+
71
+ - **"No Elysia" is measured, not asserted.** `noFrameworkGraph.test.ts` checks it
72
+ two ways that miss different things: every entry point is bundled with packages
73
+ left external and must contain no `from "elysia"`, and every source file plus
74
+ the manifest is scanned, because a dynamic import never reaches a bundle.
75
+
76
+ - **The suites that compared two servers now state one.** With no second arm to
77
+ agree with, "the two answer alike" became "this is the answer" — and the claims
78
+ got stronger doing it, from 53 tests and 189 assertions to 74 and 422. Parity
79
+ passed whenever both arms were wrong in the same way; an absolute cannot.
80
+
81
+ - `src/Server/` holds the replacement — response semantics, `defineRoute`, the
82
+ router, the WebSocket upgrade — and every route in the repo declares against
83
+ it. See the `nucleus-routing` skill for how to declare one.
84
+
85
+ - The work, its measurements and its open questions live in
86
+ [`ELYSIA_MIGRATION.md`](./ELYSIA_MIGRATION.md). Read that before touching the
87
+ server's HTTP edge.
88
+
89
+ **What the migration found.** Twenty defects that existed in the shipped product
90
+ and that no test caught. Seventeen came from making the two paths answer the same
91
+ question; the last three came from removing Elysia from the TESTS, which moved
92
+ ~58 suites off Elysia's routing and validation and onto the router that actually
93
+ serves them. The ones worth naming:
94
+
95
+ | | |
96
+ |---|---|
97
+ | login sent ONE cookie | `access_token` and `refresh_token` never reached the browser |
98
+ | the 3-D Secure callback was dead | `Body already used` since the bridge landed |
99
+ | a resumable upload wrote nothing | `application/octet-stream` bodies arrived as `undefined`, so the chunk was appended as nothing and the request answered success |
100
+ | auth ran AFTER validation | an unauthenticated caller was handed the schema of a protected endpoint — property names, types, and the sample the validator builds |
101
+ | a thrown handler *or guard* leaked | Bun's `DevErrorPage` carried the raw error text where the product answers a JSON envelope whose whole job is withholding it |
102
+ | 422s and 404s shipped bare | no `nosniff`, no HSTS, no `x-frame-options`, no request id — on 151 routes |
103
+ | `stop()` leaked and killed | the DB pool, Redis and a live interval survived every restart, and in-flight requests were cut where Elysia drains them |
104
+ | monitoring was blind | the request log, the collector and the live store recorded nothing on the Bun path |
105
+ | form bodies were not parsed | `application/x-www-form-urlencoded` fell through every branch |
106
+ | schema `default:` never applied | a defaulted field left out became a 422; so did an extra property, an absent optional body, and a malformed one |
107
+ | nested form keys stayed flat | `a.b=1` arrived as a key called `a.b`, so `body.a.b` found nothing |
108
+ | a WebSocket upgrade skipped the guards | no rate limit, no tenant resolution, no header strip |
109
+
110
+ Two of those were the OTHER way round, with the SHIPPED path broken and the
111
+ replacement correct: multipart uploads never worked on Elysia at all, and a
112
+ failed insert came back from it as `500 text/plain` carrying the schema name,
113
+ the table name and every column, because Elysia discarded the `Response` the
114
+ product's error responder returned. Both are gone with the path that had them.
115
+
116
+ **And three found by taking Elysia out of the tests** — all of them live on the
117
+ only path that remains, all now fixed:
118
+
119
+ | | |
120
+ |---|---|
121
+ | the 422 handed the caller their own submitted values | `POST /login` with a bad email answered `"password": "hunter2-the-real-one"` — into the response, and into any log that records one. Every value in a refusal is its TYPE now. The parity walk could not see it: it sends an empty body, so `found` was always `{}` |
122
+ | a malformed body on a route with NO body schema | reached the handler as `undefined` and 500'd where the handler dereferenced it. 69 of 134 write declarations carry no body schema and 36 read the body anyway — a client error was becoming a server error. Now a 400 |
123
+ | a JSON body claimed to be `text/plain` | seventeen returned-`Error` sites, including the whole authentication middleware. Copied from Elysia so the two arms agreed byte for byte; with Elysia gone the only argument for it went too |
124
+
125
+ `ELYSIA_MIGRATION.md` §11 has the rest, including the four audit claims that did
126
+ NOT reproduce when measured, and one regression this work introduced and then
127
+ removed.
128
+
129
+ Breaking changes will be announced here first. There is no 1.0 date; the 0.9.x
130
+ line continues.
131
+
132
+ ## Gates
133
+
134
+ Every push runs, and all of these block:
135
+
136
+ ```bash
137
+ bun test src scripts fe # unit tests
138
+ bunx tsc --noEmit -p tsconfig.check.json # the core library must type-check clean
139
+ ```
140
+
141
+ **The lint gate is currently not one of them.** CI runs `bunx biome check .`,
142
+ and `biome` on npm is not Biome — it is an unrelated 0.3.3 package for managing
143
+ environment variables. `@biomejs/biome` is the real one and is not declared as a
144
+ dependency, so the step resolves the wrong package, prints no findings and exits
145
+ 0. It passes on every commit and checks nothing. Locally it works only for
146
+ whoever has Biome installed globally.
147
+
148
+ Repairing it means declaring `@biomejs/biome`, pointing CI at it, and then
149
+ making the repo clean under the real tool — which is a repo-wide change, so it
150
+ is written down here rather than done quietly. See `ELYSIA_MIGRATION.md` §7.
151
+
152
+ **What that costs, measured** (`bunx @biomejs/biome check .`, 1144 files):
153
+
154
+ | | count |
155
+ |---|---|
156
+ | errors today | 234 |
157
+ | fixed by `--write` | 90, touching 83 files |
158
+ | left needing a judgement call | 144 errors + 29 warnings + 9 infos |
159
+
160
+ The biggest groups are `assist/source/organizeImports` (33) and
161
+ `lint/suspicious/noThenProperty` (12 — mostly chainable drizzle stubs in tests,
162
+ where a `then` property is the point). So the repair is two commits, not one: a
163
+ mechanical `--write` pass, then a smaller pass that decides what to keep.
164
+
165
+ CI additionally runs every `*.integration.test.ts` against a real Postgres and
166
+ Redis (`RUN_INTEGRATION=1`); they self-skip otherwise, because the races they
167
+ catch — over-commit, non-atomic payout
168
+ bookkeeping — cannot be reproduced against a fake backend.
169
+
170
+ `tsconfig.check.json` covers `src` only — `fe/` imports from the package root,
171
+ which only exists after a build, so it cannot be type-checked on a fresh
172
+ checkout. The build emits its declarations best-effort.
173
+
174
+ A local green is not a CI green. Path separators, case sensitivity, musl memory
175
+ behaviour and `/proc` fixtures all differ between a developer machine and the
176
+ Alpine image that runs in production; `ELYSIA_MIGRATION.md` §6 has the matrix
177
+ and the container command that reproduces it.
package/bin/cli.ts CHANGED
@@ -1,131 +1,136 @@
1
- #!/usr/bin/env bun
2
-
3
- /**
4
- * Nucleus CLI — the single front door to nucleus-core-ts.
5
- *
6
- * nucleus init scaffold a new project (interactive)
7
- * nucleus dev … run locally (up | down | run)
8
- * nucleus add … extend an existing project (entity | feature | oauth)
9
- * nucleus validate validate config.json against the schema
10
- * nucleus doctor check the local environment (bun, postgres, redis, …)
11
- * nucleus generate generate the Drizzle schema from config.json
12
- */
13
-
14
- import { spawn } from 'node:child_process'
15
- import { dirname, join } from 'node:path'
16
- import { fileURLToPath } from 'node:url'
17
- import { banner, c, log } from './lib/ui'
18
- import { doctorCommand } from './lib/commands/doctor'
19
- import { validateCommand } from './lib/commands/validate'
20
- import { initCommand } from './lib/commands/init'
21
- import { devCommand } from './lib/commands/dev'
22
- import { addCommand } from './lib/commands/add'
23
-
24
- const here = dirname(fileURLToPath(import.meta.url))
25
- const rootDir = join(here, '..')
26
-
27
- const argv = process.argv.slice(2)
28
- const firstArg = argv[0] ?? ''
29
- const looksLikeFile = firstArg.endsWith('.json') || firstArg.startsWith('./') || firstArg.startsWith('/')
30
- const command = looksLikeFile ? 'generate' : firstArg
31
-
32
- async function pkgVersion(): Promise<string> {
33
- try {
34
- return (JSON.parse(await Bun.file(join(rootDir, 'package.json')).text()) as { version: string }).version
35
- } catch {
36
- return '?'
37
- }
38
- }
39
-
40
- function showHelp(version: string) {
41
- banner(`Nucleus CLI v${version}`, 'nucleus-core-ts — config-driven backend framework')
42
- log(`
43
- ${c.bold('Usage')} ${c.cyan('nucleus')} ${c.dim('<command> [options]')}
44
-
45
- ${c.bold('Create & evolve')}
46
- ${c.cyan('init')} ${c.dim('[--preset <p>] [-o <dir>] [-y]')} build a config + scaffold a runnable backend (zero-to-running)
47
- ${c.cyan('add')} ${c.dim('entity | feature <n> | oauth <p>')} extend this project's config in place (+ regenerate)
48
- ${c.cyan('scaffold')} full-project scaffold (backend+frontend+k8s+pipelines) from a config.json
49
- ${c.cyan('generate')} ${c.dim('<config.json> <outDir>')} generate the Drizzle schema + relations from config
50
- ${c.cyan('validate')} ${c.dim('[config.json]')} validate a config against the JSON-Schema + cross-field rules
51
-
52
- ${c.bold('Local dev')}
53
- ${c.cyan('dev')} ${c.dim('[up | down]')} run the app; ${c.dim('up')} starts Postgres+Redis, ${c.dim('down')} stops them
54
- ${c.cyan('doctor')} check the local environment can run a Nucleus project
55
-
56
- ${c.bold('Maintenance')}
57
- ${c.cyan('audit:purge-noise')} ${c.dim('[--execute]')} delete historical low-signal audit_logs rows (dry-run by default)
58
- ${c.cyan('help')}${c.dim(', ')}${c.cyan('--version')} this help / the installed version
59
-
60
- ${c.dim('init = preset → runnable backend · scaffold (= new) = full project · Aliases: generate = gen, validate = check')}
61
- `)
62
- }
63
-
64
- function runScript(scriptRelPath: string, args: string[]): Promise<never> {
65
- return new Promise<never>(() => {
66
- const proc = spawn('bun', ['run', join(rootDir, scriptRelPath), ...args], { cwd: process.cwd(), stdio: 'inherit' })
67
- proc.on('close', (code) => process.exit(code ?? 1))
68
- })
69
- }
70
-
71
- switch (command) {
72
- case 'init':
73
- process.exit(await initCommand(argv.slice(1)))
74
- break
75
-
76
- case 'dev':
77
- process.exit(await devCommand(argv.slice(1)))
78
- break
79
-
80
- case 'add':
81
- process.exit(await addCommand(argv.slice(1)))
82
- break
83
-
84
- case 'scaffold':
85
- case 'new': {
86
- // Full-project scaffold (backend + frontend + k8s + pipelines) from an
87
- // existing config.json. `init` is the leaner, config-building local-dev path.
88
- const { scaffold } = await import(join(rootDir, 'infra', 'scripts', 'generate-project.ts'))
89
- await scaffold(join(rootDir, 'infra'))
90
- break
91
- }
92
-
93
- case 'generate':
94
- case 'gen': {
95
- const genArgs = looksLikeFile ? argv : argv.slice(1)
96
- await runScript(join('scripts', 'generate-schema.ts'), genArgs)
97
- break
98
- }
99
-
100
- case 'validate':
101
- case 'check':
102
- process.exit(await validateCommand(argv.slice(1)))
103
- break
104
-
105
- case 'doctor':
106
- process.exit(await doctorCommand())
107
- break
108
-
109
- case 'audit:purge-noise':
110
- case 'audit-purge-noise':
111
- await runScript(join('scripts', 'audit-purge-noise.ts'), argv.slice(1))
112
- break
113
-
114
- case '--version':
115
- case '-v':
116
- log(await pkgVersion())
117
- break
118
-
119
- case 'help':
120
- case '--help':
121
- case '-h':
122
- case '':
123
- case undefined:
124
- showHelp(await pkgVersion())
125
- break
126
-
127
- default:
128
- log(`${c.red('Unknown command:')} ${command}\n`)
129
- showHelp(await pkgVersion())
130
- process.exit(1)
131
- }
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * Nucleus CLI — the single front door to nucleus-core-ts.
5
+ *
6
+ * nucleus init scaffold a new project (interactive)
7
+ * nucleus dev … run locally (up | down | run)
8
+ * nucleus add … extend an existing project (entity | feature | oauth)
9
+ * nucleus validate validate config.json against the schema
10
+ * nucleus doctor check the local environment (bun, postgres, redis, …)
11
+ * nucleus generate generate the Drizzle schema from config.json
12
+ */
13
+
14
+ import { spawn } from 'node:child_process'
15
+ import { dirname, join } from 'node:path'
16
+ import { fileURLToPath } from 'node:url'
17
+ import { addCommand } from './lib/commands/add'
18
+ import { devCommand } from './lib/commands/dev'
19
+ import { doctorCommand } from './lib/commands/doctor'
20
+ import { initCommand } from './lib/commands/init'
21
+ import { validateCommand } from './lib/commands/validate'
22
+ import { banner, c, log } from './lib/ui'
23
+
24
+ const here = dirname(fileURLToPath(import.meta.url))
25
+ const rootDir = join(here, '..')
26
+
27
+ const argv = process.argv.slice(2)
28
+ const firstArg = argv[0] ?? ''
29
+ const looksLikeFile =
30
+ firstArg.endsWith('.json') || firstArg.startsWith('./') || firstArg.startsWith('/')
31
+ const command = looksLikeFile ? 'generate' : firstArg
32
+
33
+ async function pkgVersion(): Promise<string> {
34
+ try {
35
+ return (JSON.parse(await Bun.file(join(rootDir, 'package.json')).text()) as { version: string })
36
+ .version
37
+ } catch {
38
+ return '?'
39
+ }
40
+ }
41
+
42
+ function showHelp(version: string) {
43
+ banner(`Nucleus CLI v${version}`, 'nucleus-core-ts — config-driven backend framework')
44
+ log(`
45
+ ${c.bold('Usage')} ${c.cyan('nucleus')} ${c.dim('<command> [options]')}
46
+
47
+ ${c.bold('Create & evolve')}
48
+ ${c.cyan('init')} ${c.dim('[--preset <p>] [-o <dir>] [-y]')} build a config + scaffold a runnable backend (zero-to-running)
49
+ ${c.cyan('add')} ${c.dim('entity | feature <n> | oauth <p>')} extend this project's config in place (+ regenerate)
50
+ ${c.cyan('scaffold')} full-project scaffold (backend+frontend+k8s+pipelines) from a config.json
51
+ ${c.cyan('generate')} ${c.dim('<config.json> <outDir>')} generate the Drizzle schema + relations from config
52
+ ${c.cyan('validate')} ${c.dim('[config.json]')} validate a config against the JSON-Schema + cross-field rules
53
+
54
+ ${c.bold('Local dev')}
55
+ ${c.cyan('dev')} ${c.dim('[up | down]')} run the app; ${c.dim('up')} starts Postgres+Redis, ${c.dim('down')} stops them
56
+ ${c.cyan('doctor')} check the local environment can run a Nucleus project
57
+
58
+ ${c.bold('Maintenance')}
59
+ ${c.cyan('audit:purge-noise')} ${c.dim('[--execute]')} delete historical low-signal audit_logs rows (dry-run by default)
60
+ ${c.cyan('help')}${c.dim(', ')}${c.cyan('--version')} this help / the installed version
61
+
62
+ ${c.dim('init = preset → runnable backend · scaffold (= new) = full project · Aliases: generate = gen, validate = check')}
63
+ `)
64
+ }
65
+
66
+ function runScript(scriptRelPath: string, args: string[]): Promise<never> {
67
+ return new Promise<never>(() => {
68
+ const proc = spawn('bun', ['run', join(rootDir, scriptRelPath), ...args], {
69
+ cwd: process.cwd(),
70
+ stdio: 'inherit',
71
+ })
72
+ proc.on('close', (code) => process.exit(code ?? 1))
73
+ })
74
+ }
75
+
76
+ switch (command) {
77
+ case 'init':
78
+ process.exit(await initCommand(argv.slice(1)))
79
+ break
80
+
81
+ case 'dev':
82
+ process.exit(await devCommand(argv.slice(1)))
83
+ break
84
+
85
+ case 'add':
86
+ process.exit(await addCommand(argv.slice(1)))
87
+ break
88
+
89
+ case 'scaffold':
90
+ case 'new': {
91
+ // Full-project scaffold (backend + frontend + k8s + pipelines) from an
92
+ // existing config.json. `init` is the leaner, config-building local-dev path.
93
+ const { scaffold } = await import(join(rootDir, 'infra', 'scripts', 'generate-project.ts'))
94
+ await scaffold(join(rootDir, 'infra'))
95
+ break
96
+ }
97
+
98
+ case 'generate':
99
+ case 'gen': {
100
+ const genArgs = looksLikeFile ? argv : argv.slice(1)
101
+ await runScript(join('scripts', 'generate-schema.ts'), genArgs)
102
+ break
103
+ }
104
+
105
+ case 'validate':
106
+ case 'check':
107
+ process.exit(await validateCommand(argv.slice(1)))
108
+ break
109
+
110
+ case 'doctor':
111
+ process.exit(await doctorCommand())
112
+ break
113
+
114
+ case 'audit:purge-noise':
115
+ case 'audit-purge-noise':
116
+ await runScript(join('scripts', 'audit-purge-noise.ts'), argv.slice(1))
117
+ break
118
+
119
+ case '--version':
120
+ case '-v':
121
+ log(await pkgVersion())
122
+ break
123
+
124
+ case 'help':
125
+ case '--help':
126
+ case '-h':
127
+ case '':
128
+ case undefined:
129
+ showHelp(await pkgVersion())
130
+ break
131
+
132
+ default:
133
+ log(`${c.red('Unknown command:')} ${command}\n`)
134
+ showHelp(await pkgVersion())
135
+ process.exit(1)
136
+ }
@@ -10,13 +10,13 @@
10
10
  * After editing, it re-validates and (for schema-affecting changes) regenerates
11
11
  * the Drizzle schema so `nucleus dev` picks the change up.
12
12
  */
13
- import { dirname, join, relative } from 'node:path'
13
+
14
14
  import { spawnSync } from 'node:child_process'
15
- import { c, fail, info, log, ok, step, warn } from '../ui'
16
- import { prompts } from '../ui'
17
- import { buildEntity, slug } from '../config-builder'
18
- import { findConfigPath, crossFieldChecks } from './validate'
15
+ import { dirname, join, relative } from 'node:path'
16
+ import { buildEntity } from '../config-builder'
19
17
  import { loadConfigSchema, validateAgainstSchema } from '../schema'
18
+ import { c, fail, info, log, ok, prompts, step, warn } from '../ui'
19
+ import { crossFieldChecks, findConfigPath } from './validate'
20
20
 
21
21
  type Cfg = Record<string, unknown>
22
22
 
@@ -77,8 +77,13 @@ const FEATURES: Record<string, { summary: string; apply: (cfg: Cfg) => void | Pr
77
77
  const provider = await p.choose(' Provider', ['iyzico', 'stripe'], 0)
78
78
  const block: Cfg = { enabled: true, provider }
79
79
  if (provider === 'iyzico')
80
- block.iyzico = { apiKey: 'IYZICO_API_KEY', secretKey: 'IYZICO_SECRET_KEY', baseUrl: 'IYZICO_BASE_URL' }
81
- else block.stripe = { secretKey: 'STRIPE_SECRET_KEY', webhookSecret: 'STRIPE_WEBHOOK_SECRET' }
80
+ block.iyzico = {
81
+ apiKey: 'IYZICO_API_KEY',
82
+ secretKey: 'IYZICO_SECRET_KEY',
83
+ baseUrl: 'IYZICO_BASE_URL',
84
+ }
85
+ else
86
+ block.stripe = { secretKey: 'STRIPE_SECRET_KEY', webhookSecret: 'STRIPE_WEBHOOK_SECRET' }
82
87
  cfg.payment = block
83
88
  } finally {
84
89
  p.close()
@@ -113,7 +118,7 @@ async function persist(path: string, cfg: Cfg, regen: boolean): Promise<number>
113
118
  fail('Change would make the config invalid — nothing written')
114
119
  return 1
115
120
  }
116
- await Bun.write(path, JSON.stringify(cfg, null, 2) + '\n')
121
+ await Bun.write(path, `${JSON.stringify(cfg, null, 2)}\n`)
117
122
  ok(`Updated ${c.cyan(relative(process.cwd(), path))}`)
118
123
 
119
124
  if (regen) {
@@ -168,7 +173,8 @@ async function addFeature(name?: string): Promise<number> {
168
173
  if (!key || !FEATURES[key]) {
169
174
  fail(`Unknown feature "${name ?? ''}"`)
170
175
  log(` Available features:`)
171
- for (const [k, v] of Object.entries(FEATURES)) log(` ${c.cyan(k.padEnd(14))} ${c.dim(v.summary)}`)
176
+ for (const [k, v] of Object.entries(FEATURES))
177
+ log(` ${c.cyan(k.padEnd(14))} ${c.dim(v.summary)}`)
172
178
  return 1
173
179
  }
174
180
  const loaded = await readConfig()
@@ -188,7 +194,9 @@ async function addFeature(name?: string): Promise<number> {
188
194
  async function addOauth(provider?: string): Promise<number> {
189
195
  const prov = (provider || '').toLowerCase()
190
196
  if (!prov || !OAUTH_PROVIDERS.includes(prov)) {
191
- fail(`Unknown OAuth provider "${provider ?? ''}" — expected one of ${OAUTH_PROVIDERS.join(', ')}`)
197
+ fail(
198
+ `Unknown OAuth provider "${provider ?? ''}" — expected one of ${OAUTH_PROVIDERS.join(', ')}`
199
+ )
192
200
  return 1
193
201
  }
194
202
  const loaded = await readConfig()
@@ -210,7 +218,8 @@ async function addOauth(provider?: string): Promise<number> {
210
218
  cfg.authentication = auth
211
219
  step(`Adding OAuth provider: ${c.cyan(prov)}`)
212
220
  const rc = await persist(path, cfg, false)
213
- if (rc === 0) info(`Set ${up}_CLIENT_ID and ${up}_CLIENT_SECRET in .env, plus the provider redirect URI.`)
221
+ if (rc === 0)
222
+ info(`Set ${up}_CLIENT_ID and ${up}_CLIENT_SECRET in .env, plus the provider redirect URI.`)
214
223
  return rc
215
224
  }
216
225
 
@@ -227,9 +236,13 @@ export async function addCommand(args: string[]): Promise<number> {
227
236
  default:
228
237
  fail(`Unknown: nucleus add ${thing ?? ''}`)
229
238
  log(` Usage:`)
230
- log(` ${c.cyan('nucleus add entity')} ${c.dim('add one or more entities (interactive)')}`)
239
+ log(
240
+ ` ${c.cyan('nucleus add entity')} ${c.dim('add one or more entities (interactive)')}`
241
+ )
231
242
  log(` ${c.cyan('nucleus add feature <name>')} ${c.dim('enable a feature block')}`)
232
- log(` ${c.cyan('nucleus add oauth <provider>')} ${c.dim(`add OAuth (${OAUTH_PROVIDERS.join('|')})`)}`)
243
+ log(
244
+ ` ${c.cyan('nucleus add oauth <provider>')} ${c.dim(`add OAuth (${OAUTH_PROVIDERS.join('|')})`)}`
245
+ )
233
246
  return 1
234
247
  }
235
248
  }