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.
- package/README.md +177 -0
- package/bin/cli.ts +136 -131
- package/bin/lib/commands/add.ts +26 -13
- package/bin/lib/commands/dev.ts +57 -18
- package/bin/lib/commands/doctor.ts +22 -9
- package/bin/lib/commands/init.ts +31 -12
- package/bin/lib/commands/validate.ts +34 -10
- package/bin/lib/config-builder.ts +24 -6
- package/bin/lib/env.ts +10 -2
- package/bin/lib/presets.ts +6 -2
- package/bin/lib/schema.ts +18 -5
- package/bin/lib/templates.ts +26 -17
- package/bin/lib/ui.ts +5 -2
- package/dist/.build-ok +1 -1
- package/dist/bin/lib/commands/add.d.ts +12 -0
- package/dist/bin/lib/commands/dev.d.ts +12 -0
- package/dist/bin/lib/commands/doctor.d.ts +6 -0
- package/dist/bin/lib/config-builder.d.ts +5 -0
- package/dist/client.js +2 -2
- package/dist/dist/index.d.ts +49 -623
- package/dist/fe/components/AbstractAnimatedBackground/index.js +2 -1
- package/dist/index.d.ts +13 -3
- package/dist/index.js +44 -1473
- package/dist/nucleus.config.d.ts +3 -2
- package/dist/server.d.ts +27 -0
- package/dist/server.js +609 -0
- package/dist/src/Client/ApiCaller/deriveAuthEndpoints.d.ts +108 -0
- package/dist/src/Client/ApiCaller/generator.d.ts +32 -1
- package/dist/src/Client/ApiCaller/index.d.ts +1 -1
- package/dist/src/Client/ApiCaller/system-tables.d.ts +5 -5
- package/dist/src/Client/ApiCaller/types.d.ts +158 -115
- package/dist/src/Client/Proxy/httpProxy.js +89 -89
- package/dist/src/Client/Proxy/synthesizedAuth.js +10 -10
- package/dist/src/Client/Proxy/wsProxy.js +41 -41
- package/dist/src/Client/PubSub/usePubSub.js +97 -97
- package/dist/src/Client/PubSub/waitForReturn.js +29 -29
- package/dist/src/Client/Upload/progress.js +31 -31
- package/dist/src/Client/Upload/types.js +7 -7
- package/dist/src/Client/Upload/upload.js +21 -21
- package/dist/src/Managers/Redis/index.d.ts +18 -0
- package/dist/src/Nucleus/index.d.ts +71 -0
- package/dist/src/Nucleus/publicRoutes.d.ts +48 -0
- package/dist/src/Nucleus/routes/auth/admin/changeUserId.d.ts +2 -0
- package/dist/src/Nucleus/routes/auth/admin/createUser.d.ts +8 -0
- package/dist/src/Nucleus/routes/auth/admin/hardDeleteUser.d.ts +2 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/impersonate.d.ts +3 -30
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/passwordAdmin.d.ts +1 -29
- package/dist/src/Nucleus/routes/auth/admin/requireGodmin.d.ts +33 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/roleAssignAuthz.d.ts +1 -3
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/userState.d.ts +1 -29
- package/dist/src/Nucleus/routes/auth/apiKeys/index.d.ts +4 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/captcha/index.d.ts +1 -29
- package/dist/src/Nucleus/routes/auth/check/index.d.ts +8 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/activateUsers.d.ts +2 -3
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/bulkCreate.d.ts +2 -3
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/create.d.ts +2 -3
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/deactivateUsers.d.ts +2 -3
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/deleteUsers.d.ts +2 -3
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/detail.d.ts +2 -3
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/exportUsers.d.ts +2 -3
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/list.d.ts +2 -3
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/remove.d.ts +2 -3
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/handlers/update.d.ts +2 -3
- package/dist/src/Nucleus/routes/auth/cohort/index.d.ts +2 -0
- package/dist/src/Nucleus/routes/auth/cohort/types.d.ts +55 -0
- package/dist/src/Nucleus/routes/auth/cohort/utils.d.ts +43 -0
- package/dist/src/Nucleus/routes/auth/emailVerification/index.d.ts +9 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/index.d.ts +6 -4
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/invite/index.d.ts +1 -29
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/index.d.ts +1 -29
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/logout/index.d.ts +1 -29
- package/dist/src/Nucleus/routes/auth/magicLink/index.d.ts +25 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/me/index.d.ts +1 -29
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/oauth/index.d.ts +1 -29
- package/dist/src/Nucleus/routes/auth/passwordChange/index.d.ts +4 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordReset/index.d.ts +1 -29
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordSet/index.d.ts +1 -29
- package/dist/src/Nucleus/routes/auth/refresh/index.d.ts +11 -0
- package/dist/src/Nucleus/routes/auth/refresh/sessionBinding.d.ts +29 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/register/index.d.ts +3 -31
- package/dist/src/Nucleus/routes/auth/sessions/index.d.ts +4 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/types.d.ts +22 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/webauthn/index.d.ts +3 -31
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/authorization/index.d.ts +1 -29
- package/dist/src/Nucleus/routes/backup/index.d.ts +7 -0
- package/dist/src/Nucleus/routes/backup/types.d.ts +24 -0
- package/dist/src/Nucleus/routes/chat/conversations.routes.d.ts +3 -0
- package/dist/src/Nucleus/routes/chat/index.d.ts +12 -0
- package/dist/src/Nucleus/routes/chat/messages.routes.d.ts +3 -0
- package/dist/src/Nucleus/routes/config/helpers.d.ts +152 -0
- package/dist/src/Nucleus/routes/config/index.d.ts +2 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/config/types.d.ts +12 -4
- package/dist/src/Nucleus/routes/domain/hostnames.d.ts +8 -0
- package/dist/src/Nucleus/routes/domain/index.d.ts +5 -0
- package/dist/src/Nucleus/routes/domain/registrations.d.ts +8 -0
- package/dist/src/Nucleus/routes/domain/resolve.d.ts +7 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/index.d.ts +22 -2
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/utils.d.ts +1 -1
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/integrations/index.d.ts +1 -29
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/integrations/inspectRoutes.d.ts +2 -29
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/monitoring/index.d.ts +1 -29
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/monitoring/live.d.ts +1 -29
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/monitoring/serverLogs.d.ts +1 -29
- package/dist/src/Nucleus/routes/monitoring/sse.d.ts +28 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/notification/index.d.ts +1 -29
- package/dist/src/Nucleus/routes/payment/index.d.ts +4 -0
- package/dist/src/Nucleus/routes/payment/marketplace/index.d.ts +5 -0
- package/dist/src/Nucleus/routes/payment/marketplace/payouts.d.ts +3 -0
- package/dist/src/Nucleus/routes/payment/marketplace/splits.d.ts +3 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/payment/webhook.d.ts +16 -2
- package/dist/src/Nucleus/routes/pubsub/handshakeAuth.d.ts +77 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/pubsub/index.d.ts +16 -29
- package/dist/src/Nucleus/routes/pubsub/refusalReason.d.ts +49 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/pubsub/types.d.ts +7 -1
- package/dist/src/Nucleus/routes/secrets/index.d.ts +11 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/adminGuard.d.ts +14 -7
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/godminGuard.d.ts +1 -1
- package/dist/src/Nucleus/routes/storage/boundedStream.d.ts +28 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/cdn.d.ts +16 -29
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/helpers.d.ts +15 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/index.d.ts +1 -1
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/resumable/index.d.ts +2 -30
- package/dist/src/Nucleus/routes/tenant/check-subdomain.d.ts +6 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/tenant/index.d.ts +3 -2
- package/dist/src/Nucleus/routes/tenant/manage.d.ts +6 -0
- package/dist/src/Nucleus/routes/tenant/provision.d.ts +2 -0
- package/dist/src/Nucleus/routes/tenant/self-signup.d.ts +2 -0
- package/dist/src/{ElysiaPlugin → Nucleus}/routes/verification/index.d.ts +1 -29
- package/dist/src/Server/NucleusServer.d.ts +141 -0
- package/dist/src/Server/createNucleusServer.d.ts +75 -0
- package/dist/src/Server/defineRoute.d.ts +185 -0
- package/dist/src/Server/fileSchema.d.ts +35 -0
- package/dist/src/Server/formats.d.ts +4 -0
- package/dist/src/Server/inboundGuard.d.ts +26 -0
- package/dist/src/Server/internalHeaders.d.ts +26 -0
- package/dist/src/Server/openapi.d.ts +52 -0
- package/dist/src/Server/parseBody.d.ts +39 -0
- package/dist/src/Server/response.d.ts +72 -0
- package/dist/src/Server/routeCollector.d.ts +51 -0
- package/dist/src/Server/routeMount.d.ts +104 -0
- package/dist/src/Server/routeRecording.d.ts +107 -0
- package/dist/src/Server/router.d.ts +140 -0
- package/dist/src/Server/testApp.d.ts +82 -0
- package/dist/src/Server/validate.d.ts +76 -0
- package/dist/src/Server/websocket.d.ts +70 -0
- package/dist/src/Services/Authorization/activeRows.d.ts +33 -0
- package/dist/src/Services/Backup/BackupService.d.ts +22 -0
- package/dist/src/Services/Chat/ChatService.d.ts +3 -1
- package/dist/src/Services/Chat/attachmentAccess.d.ts +28 -0
- package/dist/src/Services/Chat/index.d.ts +1 -0
- package/dist/src/Services/Chat/types.d.ts +13 -0
- package/dist/src/Services/Logger/auditTaxonomy.d.ts +1 -1
- package/dist/src/Services/Logger/index.d.ts +1 -1
- package/dist/src/Services/Notification/index.d.ts +37 -2
- package/dist/src/Services/Notification/types.d.ts +17 -0
- package/dist/src/Services/SchemaTables/resolveEntities.d.ts +1 -1
- package/dist/src/Services/WebAuthn/types.d.ts +15 -0
- package/dist/src/types.d.ts +22 -2
- package/infra/templates/backend/package.json +0 -1
- package/infra/templates/backend/src/index.ts +25 -22
- package/package.json +9 -6
- package/public/components/docs/content/advanced.ts +37 -34
- package/public/components/docs/content/gettingStarted.ts +59 -11
- package/schemas/config.nucleus.json +54 -235
- package/schemas/nucleus.tables.schema.json +1 -3
- package/schemas/table.schema.json +22 -115
- package/scripts/build.ts +21 -4
- package/scripts/generate-schema.ts +739 -739
- package/scripts/importCase.test.ts +174 -0
- package/scripts/packagedScripts.test.ts +4 -1
- package/scripts/scaffoldParity.test.ts +126 -0
- package/scripts/skillCitations.test.ts +106 -0
- package/src/Services/Logger/auditTaxonomy.ts +1 -1
- package/src/Services/SchemaTables/resolveEntities.ts +1 -1
- package/src/system.tables.json +5527 -5527
- package/dist/src/ElysiaPlugin/index.d.ts +0 -23
- package/dist/src/ElysiaPlugin/publicRoutes.d.ts +0 -8
- package/dist/src/ElysiaPlugin/routes/auth/admin/changeUserId.d.ts +0 -30
- package/dist/src/ElysiaPlugin/routes/auth/admin/createUser.d.ts +0 -36
- package/dist/src/ElysiaPlugin/routes/auth/admin/hardDeleteUser.d.ts +0 -30
- package/dist/src/ElysiaPlugin/routes/auth/admin/requireGodmin.d.ts +0 -17
- package/dist/src/ElysiaPlugin/routes/auth/apiKeys/index.d.ts +0 -3
- package/dist/src/ElysiaPlugin/routes/auth/check/index.d.ts +0 -62
- package/dist/src/ElysiaPlugin/routes/auth/cohort/index.d.ts +0 -30
- package/dist/src/ElysiaPlugin/routes/auth/cohort/types.d.ts +0 -26
- package/dist/src/ElysiaPlugin/routes/auth/cohort/utils.d.ts +0 -21
- package/dist/src/ElysiaPlugin/routes/auth/emailVerification/index.d.ts +0 -37
- package/dist/src/ElysiaPlugin/routes/auth/magicLink/index.d.ts +0 -53
- package/dist/src/ElysiaPlugin/routes/auth/passwordChange/index.d.ts +0 -32
- package/dist/src/ElysiaPlugin/routes/auth/refresh/index.d.ts +0 -38
- package/dist/src/ElysiaPlugin/routes/auth/sessions/index.d.ts +0 -32
- package/dist/src/ElysiaPlugin/routes/backup/index.d.ts +0 -35
- package/dist/src/ElysiaPlugin/routes/backup/types.d.ts +0 -14
- package/dist/src/ElysiaPlugin/routes/chat/conversations.routes.d.ts +0 -31
- package/dist/src/ElysiaPlugin/routes/chat/index.d.ts +0 -40
- package/dist/src/ElysiaPlugin/routes/chat/messages.routes.d.ts +0 -31
- package/dist/src/ElysiaPlugin/routes/config/helpers.d.ts +0 -60
- package/dist/src/ElysiaPlugin/routes/config/index.d.ts +0 -30
- package/dist/src/ElysiaPlugin/routes/domain/hostnames.d.ts +0 -36
- package/dist/src/ElysiaPlugin/routes/domain/index.d.ts +0 -4
- package/dist/src/ElysiaPlugin/routes/domain/registrations.d.ts +0 -36
- package/dist/src/ElysiaPlugin/routes/domain/resolve.d.ts +0 -35
- package/dist/src/ElysiaPlugin/routes/payment/index.d.ts +0 -32
- package/dist/src/ElysiaPlugin/routes/payment/marketplace/index.d.ts +0 -4
- package/dist/src/ElysiaPlugin/routes/payment/marketplace/payouts.d.ts +0 -31
- package/dist/src/ElysiaPlugin/routes/payment/marketplace/splits.d.ts +0 -31
- package/dist/src/ElysiaPlugin/routes/pubsub/refusalReason.d.ts +0 -18
- package/dist/src/ElysiaPlugin/routes/secrets/index.d.ts +0 -39
- package/dist/src/ElysiaPlugin/routes/tenant/check-subdomain.d.ts +0 -34
- package/dist/src/ElysiaPlugin/routes/tenant/manage.d.ts +0 -34
- package/dist/src/ElysiaPlugin/routes/tenant/provision.d.ts +0 -30
- package/dist/src/ElysiaPlugin/routes/tenant/self-signup.d.ts +0 -30
- package/dist/src/ElysiaPlugin/swagger.d.ts +0 -27
- /package/dist/src/{ElysiaPlugin → Nucleus}/authRouteClassifier.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/accountState.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/createUserAuthz.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/lockoutState.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/resolveMutationSchema.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/admin/rotationPlan.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/apiKeys/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/assignDefaultRole.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/cohort/schemas.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/emailExempt.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/emailLinks/index.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/fetchUserRolesAndClaims.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/impersonationCookies.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/deviceInfo.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/identifier.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/identifierQuery.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/notifyDecision.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/login/utils.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/logout/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/logout/utils.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/magicLink/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/magicLink/utils.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/oauth/applyProfileSync.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordChange/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordChange/utils.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordReset/outcome.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordReset/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordReset/utils.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/passwordSet/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/refresh/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/refresh/utils.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/register/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/register/utils.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/resolveAuthTables.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/sessions/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/sessions/utils.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/webauthn/cookies.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/auth/webauthn/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/chat/helpers.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/chat/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/domain/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/anonymousCreate.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/createScope.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/relationAuthz.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/entity/userRoleWrite.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/index.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/integrations/inspect.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/integrations/repository.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/integrations/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/payment/marketplace/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/payment/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/payment/validation.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/pubsub/ack-manager.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/pubsub/client-manager.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/pubsub/frame.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/secrets/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/basePathCollision.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/bodyCeiling.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/clientIp.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/csrf.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/redact.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/requestLimits.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/sensitiveColumns.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/sensitiveTables.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/tenantBinding.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/shared/writeLock.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/cpuBudget.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/file-record.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/imageTransform.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/mediaPostProcess.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/pdfTransform.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/resumable/session.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/resumable/store.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/storage/videoTransform.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/routes/tenant/types.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/runtime.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/schemaReconcile.d.ts +0 -0
- /package/dist/src/{ElysiaPlugin → Nucleus}/utils.d.ts +0 -0
- /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 {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { initCommand } from './lib/commands/init'
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
${c.bold('
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
${c.cyan('
|
|
49
|
-
${c.cyan('
|
|
50
|
-
${c.cyan('
|
|
51
|
-
|
|
52
|
-
${c.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
${c.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
${c.dim('
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
case '
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
case '
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
case '
|
|
111
|
-
await
|
|
112
|
-
break
|
|
113
|
-
|
|
114
|
-
case '
|
|
115
|
-
case '-
|
|
116
|
-
|
|
117
|
-
break
|
|
118
|
-
|
|
119
|
-
case '
|
|
120
|
-
case '
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
showHelp(await pkgVersion())
|
|
130
|
-
|
|
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
|
+
}
|
package/bin/lib/commands/add.ts
CHANGED
|
@@ -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
|
-
|
|
13
|
+
|
|
14
14
|
import { spawnSync } from 'node:child_process'
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
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 = {
|
|
81
|
-
|
|
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)
|
|
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))
|
|
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(
|
|
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)
|
|
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(
|
|
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(
|
|
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
|
}
|