@trokky/trokky 2.0.3
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/dist/adapters/filesystem/filesystem-adapter.d.ts +80 -0
- package/dist/adapters/filesystem/filesystem-adapter.d.ts.map +1 -0
- package/dist/adapters/filesystem/filesystem-adapter.js +1370 -0
- package/dist/adapters/filesystem/filesystem-adapter.js.map +1 -0
- package/dist/adapters/filesystem/index.d.ts +29 -0
- package/dist/adapters/filesystem/index.d.ts.map +1 -0
- package/dist/adapters/filesystem/index.js +31 -0
- package/dist/adapters/filesystem/index.js.map +1 -0
- package/dist/adapters/filesystem/types.d.ts +111 -0
- package/dist/adapters/filesystem/types.d.ts.map +1 -0
- package/dist/adapters/filesystem/types.js +2 -0
- package/dist/adapters/filesystem/types.js.map +1 -0
- package/dist/adapters/filesystem-data/filesystem-data-adapter.d.ts +111 -0
- package/dist/adapters/filesystem-data/filesystem-data-adapter.d.ts.map +1 -0
- package/dist/adapters/filesystem-data/filesystem-data-adapter.js +1363 -0
- package/dist/adapters/filesystem-data/filesystem-data-adapter.js.map +1 -0
- package/dist/adapters/filesystem-data/index.d.ts +3 -0
- package/dist/adapters/filesystem-data/index.d.ts.map +1 -0
- package/dist/adapters/filesystem-data/index.js +13 -0
- package/dist/adapters/filesystem-data/index.js.map +1 -0
- package/dist/adapters/filesystem-data/types.d.ts +147 -0
- package/dist/adapters/filesystem-data/types.d.ts.map +1 -0
- package/dist/adapters/filesystem-data/types.js +2 -0
- package/dist/adapters/filesystem-data/types.js.map +1 -0
- package/dist/adapters/filesystem-media/filesystem-media-adapter.d.ts +32 -0
- package/dist/adapters/filesystem-media/filesystem-media-adapter.d.ts.map +1 -0
- package/dist/adapters/filesystem-media/filesystem-media-adapter.js +639 -0
- package/dist/adapters/filesystem-media/filesystem-media-adapter.js.map +1 -0
- package/dist/adapters/filesystem-media/index.d.ts +3 -0
- package/dist/adapters/filesystem-media/index.d.ts.map +1 -0
- package/dist/adapters/filesystem-media/index.js +13 -0
- package/dist/adapters/filesystem-media/index.js.map +1 -0
- package/dist/adapters/filesystem-media/types.d.ts +76 -0
- package/dist/adapters/filesystem-media/types.d.ts.map +1 -0
- package/dist/adapters/filesystem-media/types.js +2 -0
- package/dist/adapters/filesystem-media/types.js.map +1 -0
- package/dist/adapters/postgres-data/index.d.ts +3 -0
- package/dist/adapters/postgres-data/index.d.ts.map +1 -0
- package/dist/adapters/postgres-data/index.js +13 -0
- package/dist/adapters/postgres-data/index.js.map +1 -0
- package/dist/adapters/postgres-data/postgres-data-adapter.d.ts +154 -0
- package/dist/adapters/postgres-data/postgres-data-adapter.d.ts.map +1 -0
- package/dist/adapters/postgres-data/postgres-data-adapter.js +1432 -0
- package/dist/adapters/postgres-data/postgres-data-adapter.js.map +1 -0
- package/dist/adapters/postgres-data/types.d.ts +139 -0
- package/dist/adapters/postgres-data/types.d.ts.map +1 -0
- package/dist/adapters/postgres-data/types.js +2 -0
- package/dist/adapters/postgres-data/types.js.map +1 -0
- package/dist/core/adapters/registry.d.ts +79 -0
- package/dist/core/adapters/registry.d.ts.map +1 -0
- package/dist/core/adapters/registry.js +149 -0
- package/dist/core/adapters/registry.js.map +1 -0
- package/dist/core/core/engine.d.ts +551 -0
- package/dist/core/core/engine.d.ts.map +1 -0
- package/dist/core/core/engine.js +1074 -0
- package/dist/core/core/engine.js.map +1 -0
- package/dist/core/crypto/adapter.d.ts +63 -0
- package/dist/core/crypto/adapter.d.ts.map +1 -0
- package/dist/core/crypto/adapter.js +63 -0
- package/dist/core/crypto/adapter.js.map +1 -0
- package/dist/core/crypto/fallback-adapter.d.ts +23 -0
- package/dist/core/crypto/fallback-adapter.d.ts.map +1 -0
- package/dist/core/crypto/fallback-adapter.js +195 -0
- package/dist/core/crypto/fallback-adapter.js.map +1 -0
- package/dist/core/crypto/node-adapter.d.ts +20 -0
- package/dist/core/crypto/node-adapter.d.ts.map +1 -0
- package/dist/core/crypto/node-adapter.js +85 -0
- package/dist/core/crypto/node-adapter.js.map +1 -0
- package/dist/core/crypto/password-hash.d.ts +73 -0
- package/dist/core/crypto/password-hash.d.ts.map +1 -0
- package/dist/core/crypto/password-hash.js +244 -0
- package/dist/core/crypto/password-hash.js.map +1 -0
- package/dist/core/crypto/webcrypto-adapter.d.ts +24 -0
- package/dist/core/crypto/webcrypto-adapter.d.ts.map +1 -0
- package/dist/core/crypto/webcrypto-adapter.js +158 -0
- package/dist/core/crypto/webcrypto-adapter.js.map +1 -0
- package/dist/core/errors/index.d.ts +30 -0
- package/dist/core/errors/index.d.ts.map +1 -0
- package/dist/core/errors/index.js +61 -0
- package/dist/core/errors/index.js.map +1 -0
- package/dist/core/events/event-bus.d.ts +121 -0
- package/dist/core/events/event-bus.d.ts.map +1 -0
- package/dist/core/events/event-bus.js +631 -0
- package/dist/core/events/event-bus.js.map +1 -0
- package/dist/core/events/index.d.ts +17 -0
- package/dist/core/events/index.d.ts.map +1 -0
- package/dist/core/events/index.js +22 -0
- package/dist/core/events/index.js.map +1 -0
- package/dist/core/events/memory-storage.d.ts +57 -0
- package/dist/core/events/memory-storage.d.ts.map +1 -0
- package/dist/core/events/memory-storage.js +175 -0
- package/dist/core/events/memory-storage.js.map +1 -0
- package/dist/core/events/types.d.ts +434 -0
- package/dist/core/events/types.d.ts.map +1 -0
- package/dist/core/events/types.js +9 -0
- package/dist/core/events/types.js.map +1 -0
- package/dist/core/events/utils.d.ts +134 -0
- package/dist/core/events/utils.d.ts.map +1 -0
- package/dist/core/events/utils.js +333 -0
- package/dist/core/events/utils.js.map +1 -0
- package/dist/core/fields/conditional.d.ts +115 -0
- package/dist/core/fields/conditional.d.ts.map +1 -0
- package/dist/core/fields/conditional.js +296 -0
- package/dist/core/fields/conditional.js.map +1 -0
- package/dist/core/fields/field-type.d.ts +218 -0
- package/dist/core/fields/field-type.d.ts.map +1 -0
- package/dist/core/fields/field-type.js +17 -0
- package/dist/core/fields/field-type.js.map +1 -0
- package/dist/core/fields/helpers.d.ts +86 -0
- package/dist/core/fields/helpers.d.ts.map +1 -0
- package/dist/core/fields/helpers.js +260 -0
- package/dist/core/fields/helpers.js.map +1 -0
- package/dist/core/fields/index.d.ts +5 -0
- package/dist/core/fields/index.d.ts.map +1 -0
- package/dist/core/fields/index.js +6 -0
- package/dist/core/fields/index.js.map +1 -0
- package/dist/core/fields/registry.d.ts +78 -0
- package/dist/core/fields/registry.d.ts.map +1 -0
- package/dist/core/fields/registry.js +185 -0
- package/dist/core/fields/registry.js.map +1 -0
- package/dist/core/index.d.ts +39 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +57 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/media/image-processor.d.ts +24 -0
- package/dist/core/media/image-processor.d.ts.map +1 -0
- package/dist/core/media/image-processor.js +69 -0
- package/dist/core/media/image-processor.js.map +1 -0
- package/dist/core/media/processors/cloudflare-images.d.ts +83 -0
- package/dist/core/media/processors/cloudflare-images.d.ts.map +1 -0
- package/dist/core/media/processors/cloudflare-images.js +241 -0
- package/dist/core/media/processors/cloudflare-images.js.map +1 -0
- package/dist/core/media/processors/cloudflare-transform-store.d.ts +127 -0
- package/dist/core/media/processors/cloudflare-transform-store.d.ts.map +1 -0
- package/dist/core/media/processors/cloudflare-transform-store.js +237 -0
- package/dist/core/media/processors/cloudflare-transform-store.js.map +1 -0
- package/dist/core/media/processors/cloudflare-transformations.d.ts +81 -0
- package/dist/core/media/processors/cloudflare-transformations.d.ts.map +1 -0
- package/dist/core/media/processors/cloudflare-transformations.js +144 -0
- package/dist/core/media/processors/cloudflare-transformations.js.map +1 -0
- package/dist/core/media/processors/index.d.ts +9 -0
- package/dist/core/media/processors/index.d.ts.map +1 -0
- package/dist/core/media/processors/index.js +13 -0
- package/dist/core/media/processors/index.js.map +1 -0
- package/dist/core/media/processors/noop.d.ts +22 -0
- package/dist/core/media/processors/noop.d.ts.map +1 -0
- package/dist/core/media/processors/noop.js +38 -0
- package/dist/core/media/processors/noop.js.map +1 -0
- package/dist/core/media/processors/sharp.d.ts +30 -0
- package/dist/core/media/processors/sharp.d.ts.map +1 -0
- package/dist/core/media/processors/sharp.js +126 -0
- package/dist/core/media/processors/sharp.js.map +1 -0
- package/dist/core/media/processors/types.d.ts +67 -0
- package/dist/core/media/processors/types.d.ts.map +1 -0
- package/dist/core/media/processors/types.js +42 -0
- package/dist/core/media/processors/types.js.map +1 -0
- package/dist/core/media/processors/workers-images.d.ts +112 -0
- package/dist/core/media/processors/workers-images.d.ts.map +1 -0
- package/dist/core/media/processors/workers-images.js +257 -0
- package/dist/core/media/processors/workers-images.js.map +1 -0
- package/dist/core/schema/registry.d.ts +41 -0
- package/dist/core/schema/registry.d.ts.map +1 -0
- package/dist/core/schema/registry.js +248 -0
- package/dist/core/schema/registry.js.map +1 -0
- package/dist/core/schema/singleton.d.ts +107 -0
- package/dist/core/schema/singleton.d.ts.map +1 -0
- package/dist/core/schema/singleton.js +180 -0
- package/dist/core/schema/singleton.js.map +1 -0
- package/dist/core/security/auth.d.ts +120 -0
- package/dist/core/security/auth.d.ts.map +1 -0
- package/dist/core/security/auth.js +274 -0
- package/dist/core/security/auth.js.map +1 -0
- package/dist/core/security/captcha/index.d.ts +21 -0
- package/dist/core/security/captcha/index.d.ts.map +1 -0
- package/dist/core/security/captcha/index.js +34 -0
- package/dist/core/security/captcha/index.js.map +1 -0
- package/dist/core/security/captcha/recaptcha.d.ts +41 -0
- package/dist/core/security/captcha/recaptcha.d.ts.map +1 -0
- package/dist/core/security/captcha/recaptcha.js +89 -0
- package/dist/core/security/captcha/recaptcha.js.map +1 -0
- package/dist/core/security/captcha/turnstile.d.ts +41 -0
- package/dist/core/security/captcha/turnstile.d.ts.map +1 -0
- package/dist/core/security/captcha/turnstile.js +90 -0
- package/dist/core/security/captcha/turnstile.js.map +1 -0
- package/dist/core/security/captcha/types.d.ts +66 -0
- package/dist/core/security/captcha/types.d.ts.map +1 -0
- package/dist/core/security/captcha/types.js +7 -0
- package/dist/core/security/captcha/types.js.map +1 -0
- package/dist/core/security/mfa/email-otp.d.ts +91 -0
- package/dist/core/security/mfa/email-otp.d.ts.map +1 -0
- package/dist/core/security/mfa/email-otp.js +264 -0
- package/dist/core/security/mfa/email-otp.js.map +1 -0
- package/dist/core/security/mfa/index.d.ts +8 -0
- package/dist/core/security/mfa/index.d.ts.map +1 -0
- package/dist/core/security/mfa/index.js +8 -0
- package/dist/core/security/mfa/index.js.map +1 -0
- package/dist/core/security/mfa/totp.d.ts +87 -0
- package/dist/core/security/mfa/totp.d.ts.map +1 -0
- package/dist/core/security/mfa/totp.js +293 -0
- package/dist/core/security/mfa/totp.js.map +1 -0
- package/dist/core/security/middleware.d.ts +102 -0
- package/dist/core/security/middleware.d.ts.map +1 -0
- package/dist/core/security/middleware.js +261 -0
- package/dist/core/security/middleware.js.map +1 -0
- package/dist/core/security/oauth/google.d.ts +76 -0
- package/dist/core/security/oauth/google.d.ts.map +1 -0
- package/dist/core/security/oauth/google.js +154 -0
- package/dist/core/security/oauth/google.js.map +1 -0
- package/dist/core/security/oauth/index.d.ts +8 -0
- package/dist/core/security/oauth/index.d.ts.map +1 -0
- package/dist/core/security/oauth/index.js +7 -0
- package/dist/core/security/oauth/index.js.map +1 -0
- package/dist/core/security/oauth2/authorization-server.d.ts +195 -0
- package/dist/core/security/oauth2/authorization-server.d.ts.map +1 -0
- package/dist/core/security/oauth2/authorization-server.js +569 -0
- package/dist/core/security/oauth2/authorization-server.js.map +1 -0
- package/dist/core/security/oauth2/index.d.ts +9 -0
- package/dist/core/security/oauth2/index.d.ts.map +1 -0
- package/dist/core/security/oauth2/index.js +9 -0
- package/dist/core/security/oauth2/index.js.map +1 -0
- package/dist/core/security/rate-limiter.d.ts +15 -0
- package/dist/core/security/rate-limiter.d.ts.map +1 -0
- package/dist/core/security/rate-limiter.js +48 -0
- package/dist/core/security/rate-limiter.js.map +1 -0
- package/dist/core/security/validation.d.ts +20 -0
- package/dist/core/security/validation.d.ts.map +1 -0
- package/dist/core/security/validation.js +273 -0
- package/dist/core/security/validation.js.map +1 -0
- package/dist/core/services/auth-service.d.ts +128 -0
- package/dist/core/services/auth-service.d.ts.map +1 -0
- package/dist/core/services/auth-service.js +530 -0
- package/dist/core/services/auth-service.js.map +1 -0
- package/dist/core/services/captcha-service.d.ts +44 -0
- package/dist/core/services/captcha-service.d.ts.map +1 -0
- package/dist/core/services/captcha-service.js +82 -0
- package/dist/core/services/captcha-service.js.map +1 -0
- package/dist/core/services/document-service.d.ts +59 -0
- package/dist/core/services/document-service.d.ts.map +1 -0
- package/dist/core/services/document-service.js +269 -0
- package/dist/core/services/document-service.js.map +1 -0
- package/dist/core/services/media-service.d.ts +40 -0
- package/dist/core/services/media-service.d.ts.map +1 -0
- package/dist/core/services/media-service.js +396 -0
- package/dist/core/services/media-service.js.map +1 -0
- package/dist/core/services/mfa-service.d.ts +123 -0
- package/dist/core/services/mfa-service.d.ts.map +1 -0
- package/dist/core/services/mfa-service.js +606 -0
- package/dist/core/services/mfa-service.js.map +1 -0
- package/dist/core/services/oauth-service.d.ts +58 -0
- package/dist/core/services/oauth-service.d.ts.map +1 -0
- package/dist/core/services/oauth-service.js +253 -0
- package/dist/core/services/oauth-service.js.map +1 -0
- package/dist/core/services/oauth2-server-service.d.ts +61 -0
- package/dist/core/services/oauth2-server-service.d.ts.map +1 -0
- package/dist/core/services/oauth2-server-service.js +259 -0
- package/dist/core/services/oauth2-server-service.js.map +1 -0
- package/dist/core/services/passkey-service.d.ts +59 -0
- package/dist/core/services/passkey-service.d.ts.map +1 -0
- package/dist/core/services/passkey-service.js +238 -0
- package/dist/core/services/passkey-service.js.map +1 -0
- package/dist/core/services/token-service.d.ts +31 -0
- package/dist/core/services/token-service.d.ts.map +1 -0
- package/dist/core/services/token-service.js +132 -0
- package/dist/core/services/token-service.js.map +1 -0
- package/dist/core/services/trusted-device-service.d.ts +39 -0
- package/dist/core/services/trusted-device-service.d.ts.map +1 -0
- package/dist/core/services/trusted-device-service.js +123 -0
- package/dist/core/services/trusted-device-service.js.map +1 -0
- package/dist/core/services/user-service.d.ts +38 -0
- package/dist/core/services/user-service.d.ts.map +1 -0
- package/dist/core/services/user-service.js +265 -0
- package/dist/core/services/user-service.js.map +1 -0
- package/dist/core/studio/integration.d.ts +54 -0
- package/dist/core/studio/integration.d.ts.map +1 -0
- package/dist/core/studio/integration.js +326 -0
- package/dist/core/studio/integration.js.map +1 -0
- package/dist/core/types/index.d.ts +282 -0
- package/dist/core/types/index.d.ts.map +1 -0
- package/dist/core/types/index.js +83 -0
- package/dist/core/types/index.js.map +1 -0
- package/dist/core/types/mail.d.ts +90 -0
- package/dist/core/types/mail.d.ts.map +1 -0
- package/dist/core/types/mail.js +7 -0
- package/dist/core/types/mail.js.map +1 -0
- package/dist/core/types/oauth2.d.ts +9 -0
- package/dist/core/types/oauth2.d.ts.map +1 -0
- package/dist/core/types/oauth2.js +7 -0
- package/dist/core/types/oauth2.js.map +1 -0
- package/dist/core/types/storage-adapters.d.ts +611 -0
- package/dist/core/types/storage-adapters.d.ts.map +1 -0
- package/dist/core/types/storage-adapters.js +14 -0
- package/dist/core/types/storage-adapters.js.map +1 -0
- package/dist/core/types/user.d.ts +10 -0
- package/dist/core/types/user.d.ts.map +1 -0
- package/dist/core/types/user.js +45 -0
- package/dist/core/types/user.js.map +1 -0
- package/dist/core/utils/id-generator.d.ts +16 -0
- package/dist/core/utils/id-generator.d.ts.map +1 -0
- package/dist/core/utils/id-generator.js +61 -0
- package/dist/core/utils/id-generator.js.map +1 -0
- package/dist/core/utils/logger.d.ts +100 -0
- package/dist/core/utils/logger.d.ts.map +1 -0
- package/dist/core/utils/logger.js +212 -0
- package/dist/core/utils/logger.js.map +1 -0
- package/dist/core/utils/reference-expander.d.ts +57 -0
- package/dist/core/utils/reference-expander.d.ts.map +1 -0
- package/dist/core/utils/reference-expander.js +192 -0
- package/dist/core/utils/reference-expander.js.map +1 -0
- package/dist/core/utils/universal-crypto.d.ts +46 -0
- package/dist/core/utils/universal-crypto.d.ts.map +1 -0
- package/dist/core/utils/universal-crypto.js +171 -0
- package/dist/core/utils/universal-crypto.js.map +1 -0
- package/dist/core/validation/validator.d.ts +11 -0
- package/dist/core/validation/validator.d.ts.map +1 -0
- package/dist/core/validation/validator.js +164 -0
- package/dist/core/validation/validator.js.map +1 -0
- package/dist/i18n/config.d.ts +4077 -0
- package/dist/i18n/config.d.ts.map +1 -0
- package/dist/i18n/config.js +116 -0
- package/dist/i18n/config.js.map +1 -0
- package/dist/i18n/hooks.d.ts +86 -0
- package/dist/i18n/hooks.d.ts.map +1 -0
- package/dist/i18n/hooks.js +122 -0
- package/dist/i18n/hooks.js.map +1 -0
- package/dist/i18n/index.d.ts +39 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +40 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/locales/en/auth.json +108 -0
- package/dist/i18n/locales/en/common.json +100 -0
- package/dist/i18n/locales/en/errors.json +55 -0
- package/dist/i18n/locales/en/fields.json +456 -0
- package/dist/i18n/locales/en/studio.json +1329 -0
- package/dist/i18n/locales/fr/auth.json +108 -0
- package/dist/i18n/locales/fr/common.json +100 -0
- package/dist/i18n/locales/fr/errors.json +55 -0
- package/dist/i18n/locales/fr/fields.json +456 -0
- package/dist/i18n/locales/fr/studio.json +1274 -0
- package/dist/i18n/provider.d.ts +45 -0
- package/dist/i18n/provider.d.ts.map +1 -0
- package/dist/i18n/provider.js +49 -0
- package/dist/i18n/provider.js.map +1 -0
- package/dist/i18n/types.d.ts +8 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +7 -0
- package/dist/i18n/types.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/express/adapter.d.ts +33 -0
- package/dist/integrations/express/adapter.d.ts.map +1 -0
- package/dist/integrations/express/adapter.js +203 -0
- package/dist/integrations/express/adapter.js.map +1 -0
- package/dist/integrations/express/config.d.ts +599 -0
- package/dist/integrations/express/config.d.ts.map +1 -0
- package/dist/integrations/express/config.js +166 -0
- package/dist/integrations/express/config.js.map +1 -0
- package/dist/integrations/express/index.d.ts +10 -0
- package/dist/integrations/express/index.d.ts.map +1 -0
- package/dist/integrations/express/index.js +9 -0
- package/dist/integrations/express/index.js.map +1 -0
- package/dist/integrations/express/integration.d.ts +111 -0
- package/dist/integrations/express/integration.d.ts.map +1 -0
- package/dist/integrations/express/integration.js +730 -0
- package/dist/integrations/express/integration.js.map +1 -0
- package/dist/integrations/express/media-rewrite-middleware.d.ts +78 -0
- package/dist/integrations/express/media-rewrite-middleware.d.ts.map +1 -0
- package/dist/integrations/express/media-rewrite-middleware.js +211 -0
- package/dist/integrations/express/media-rewrite-middleware.js.map +1 -0
- package/dist/integrations/express/media-url-generator.d.ts +52 -0
- package/dist/integrations/express/media-url-generator.d.ts.map +1 -0
- package/dist/integrations/express/media-url-generator.js +107 -0
- package/dist/integrations/express/media-url-generator.js.map +1 -0
- package/dist/integrations/express/middleware.d.ts +25 -0
- package/dist/integrations/express/middleware.d.ts.map +1 -0
- package/dist/integrations/express/middleware.js +130 -0
- package/dist/integrations/express/middleware.js.map +1 -0
- package/dist/integrations/express/server.d.ts +99 -0
- package/dist/integrations/express/server.d.ts.map +1 -0
- package/dist/integrations/express/server.js +597 -0
- package/dist/integrations/express/server.js.map +1 -0
- package/dist/integrations/express/types.d.ts +106 -0
- package/dist/integrations/express/types.d.ts.map +1 -0
- package/dist/integrations/express/types.js +2 -0
- package/dist/integrations/express/types.js.map +1 -0
- package/dist/mail/adapters/console.d.ts +30 -0
- package/dist/mail/adapters/console.d.ts.map +1 -0
- package/dist/mail/adapters/console.js +169 -0
- package/dist/mail/adapters/console.js.map +1 -0
- package/dist/mail/adapters/resend.d.ts +18 -0
- package/dist/mail/adapters/resend.d.ts.map +1 -0
- package/dist/mail/adapters/resend.js +148 -0
- package/dist/mail/adapters/resend.js.map +1 -0
- package/dist/mail/adapters/smtp.d.ts +22 -0
- package/dist/mail/adapters/smtp.d.ts.map +1 -0
- package/dist/mail/adapters/smtp.js +180 -0
- package/dist/mail/adapters/smtp.js.map +1 -0
- package/dist/mail/index.d.ts +15 -0
- package/dist/mail/index.d.ts.map +1 -0
- package/dist/mail/index.js +13 -0
- package/dist/mail/index.js.map +1 -0
- package/dist/mail/mail-service.d.ts +180 -0
- package/dist/mail/mail-service.d.ts.map +1 -0
- package/dist/mail/mail-service.js +370 -0
- package/dist/mail/mail-service.js.map +1 -0
- package/dist/mail/notification-service.d.ts +82 -0
- package/dist/mail/notification-service.d.ts.map +1 -0
- package/dist/mail/notification-service.js +262 -0
- package/dist/mail/notification-service.js.map +1 -0
- package/dist/mail/templates/built-in-templates.d.ts +47 -0
- package/dist/mail/templates/built-in-templates.d.ts.map +1 -0
- package/dist/mail/templates/built-in-templates.js +416 -0
- package/dist/mail/templates/built-in-templates.js.map +1 -0
- package/dist/mail/templates/custom-template-renderer.d.ts +115 -0
- package/dist/mail/templates/custom-template-renderer.d.ts.map +1 -0
- package/dist/mail/templates/custom-template-renderer.js +225 -0
- package/dist/mail/templates/custom-template-renderer.js.map +1 -0
- package/dist/mail/types.d.ts +7 -0
- package/dist/mail/types.d.ts.map +1 -0
- package/dist/mail/types.js +7 -0
- package/dist/mail/types.js.map +1 -0
- package/dist/routes/auth/captcha.d.ts +33 -0
- package/dist/routes/auth/captcha.d.ts.map +1 -0
- package/dist/routes/auth/captcha.js +102 -0
- package/dist/routes/auth/captcha.js.map +1 -0
- package/dist/routes/auth/change-password.d.ts +17 -0
- package/dist/routes/auth/change-password.d.ts.map +1 -0
- package/dist/routes/auth/change-password.js +121 -0
- package/dist/routes/auth/change-password.js.map +1 -0
- package/dist/routes/auth/index.d.ts +13 -0
- package/dist/routes/auth/index.d.ts.map +1 -0
- package/dist/routes/auth/index.js +35 -0
- package/dist/routes/auth/index.js.map +1 -0
- package/dist/routes/auth/mfa.d.ts +121 -0
- package/dist/routes/auth/mfa.d.ts.map +1 -0
- package/dist/routes/auth/mfa.js +1143 -0
- package/dist/routes/auth/mfa.js.map +1 -0
- package/dist/routes/auth/oauth.d.ts +37 -0
- package/dist/routes/auth/oauth.d.ts.map +1 -0
- package/dist/routes/auth/oauth.js +420 -0
- package/dist/routes/auth/oauth.js.map +1 -0
- package/dist/routes/auth/oauth2-server.d.ts +70 -0
- package/dist/routes/auth/oauth2-server.d.ts.map +1 -0
- package/dist/routes/auth/oauth2-server.js +775 -0
- package/dist/routes/auth/oauth2-server.js.map +1 -0
- package/dist/routes/auth/passkey.d.ts +65 -0
- package/dist/routes/auth/passkey.d.ts.map +1 -0
- package/dist/routes/auth/passkey.js +910 -0
- package/dist/routes/auth/passkey.js.map +1 -0
- package/dist/routes/auth/password-reset.d.ts +23 -0
- package/dist/routes/auth/password-reset.d.ts.map +1 -0
- package/dist/routes/auth/password-reset.js +336 -0
- package/dist/routes/auth/password-reset.js.map +1 -0
- package/dist/routes/handlers/audit.d.ts +21 -0
- package/dist/routes/handlers/audit.d.ts.map +1 -0
- package/dist/routes/handlers/audit.js +124 -0
- package/dist/routes/handlers/audit.js.map +1 -0
- package/dist/routes/handlers/auth.d.ts +150 -0
- package/dist/routes/handlers/auth.d.ts.map +1 -0
- package/dist/routes/handlers/auth.js +512 -0
- package/dist/routes/handlers/auth.js.map +1 -0
- package/dist/routes/handlers/base.d.ts +34 -0
- package/dist/routes/handlers/base.d.ts.map +1 -0
- package/dist/routes/handlers/base.js +366 -0
- package/dist/routes/handlers/base.js.map +1 -0
- package/dist/routes/handlers/config.d.ts +31 -0
- package/dist/routes/handlers/config.d.ts.map +1 -0
- package/dist/routes/handlers/config.js +483 -0
- package/dist/routes/handlers/config.js.map +1 -0
- package/dist/routes/handlers/documents.d.ts +50 -0
- package/dist/routes/handlers/documents.d.ts.map +1 -0
- package/dist/routes/handlers/documents.js +708 -0
- package/dist/routes/handlers/documents.js.map +1 -0
- package/dist/routes/handlers/index.d.ts +12 -0
- package/dist/routes/handlers/index.d.ts.map +1 -0
- package/dist/routes/handlers/index.js +11 -0
- package/dist/routes/handlers/index.js.map +1 -0
- package/dist/routes/handlers/media.d.ts +24 -0
- package/dist/routes/handlers/media.d.ts.map +1 -0
- package/dist/routes/handlers/media.js +432 -0
- package/dist/routes/handlers/media.js.map +1 -0
- package/dist/routes/handlers/search.d.ts +10 -0
- package/dist/routes/handlers/search.d.ts.map +1 -0
- package/dist/routes/handlers/search.js +153 -0
- package/dist/routes/handlers/search.js.map +1 -0
- package/dist/routes/handlers/tokens.d.ts +14 -0
- package/dist/routes/handlers/tokens.d.ts.map +1 -0
- package/dist/routes/handlers/tokens.js +109 -0
- package/dist/routes/handlers/tokens.js.map +1 -0
- package/dist/routes/handlers/types.d.ts +13 -0
- package/dist/routes/handlers/types.d.ts.map +1 -0
- package/dist/routes/handlers/types.js +5 -0
- package/dist/routes/handlers/types.js.map +1 -0
- package/dist/routes/handlers/users.d.ts +16 -0
- package/dist/routes/handlers/users.d.ts.map +1 -0
- package/dist/routes/handlers/users.js +198 -0
- package/dist/routes/handlers/users.js.map +1 -0
- package/dist/routes/handlers/webhooks.d.ts +37 -0
- package/dist/routes/handlers/webhooks.d.ts.map +1 -0
- package/dist/routes/handlers/webhooks.js +343 -0
- package/dist/routes/handlers/webhooks.js.map +1 -0
- package/dist/routes/index.d.ts +5 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +5 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/routes.d.ts +29 -0
- package/dist/routes/routes.d.ts.map +1 -0
- package/dist/routes/routes.js +531 -0
- package/dist/routes/routes.js.map +1 -0
- package/dist/routes/slug-processor.d.ts +32 -0
- package/dist/routes/slug-processor.d.ts.map +1 -0
- package/dist/routes/slug-processor.js +328 -0
- package/dist/routes/slug-processor.js.map +1 -0
- package/dist/routes/types.d.ts +31 -0
- package/dist/routes/types.d.ts.map +1 -0
- package/dist/routes/types.js +7 -0
- package/dist/routes/types.js.map +1 -0
- package/dist/routes/users/index.d.ts +7 -0
- package/dist/routes/users/index.d.ts.map +1 -0
- package/dist/routes/users/index.js +7 -0
- package/dist/routes/users/index.js.map +1 -0
- package/dist/structure/builder/StructureBuilder.d.ts +209 -0
- package/dist/structure/builder/StructureBuilder.d.ts.map +1 -0
- package/dist/structure/builder/StructureBuilder.js +425 -0
- package/dist/structure/builder/StructureBuilder.js.map +1 -0
- package/dist/structure/builder/index.d.ts +8 -0
- package/dist/structure/builder/index.d.ts.map +1 -0
- package/dist/structure/builder/index.js +6 -0
- package/dist/structure/builder/index.js.map +1 -0
- package/dist/structure/builder/navigation-tree-builder.d.ts +33 -0
- package/dist/structure/builder/navigation-tree-builder.d.ts.map +1 -0
- package/dist/structure/builder/navigation-tree-builder.js +284 -0
- package/dist/structure/builder/navigation-tree-builder.js.map +1 -0
- package/dist/structure/errors/index.d.ts +72 -0
- package/dist/structure/errors/index.d.ts.map +1 -0
- package/dist/structure/errors/index.js +136 -0
- package/dist/structure/errors/index.js.map +1 -0
- package/dist/structure/index.d.ts +14 -0
- package/dist/structure/index.d.ts.map +1 -0
- package/dist/structure/index.js +16 -0
- package/dist/structure/index.js.map +1 -0
- package/dist/structure/types/filters.d.ts +167 -0
- package/dist/structure/types/filters.d.ts.map +1 -0
- package/dist/structure/types/filters.js +38 -0
- package/dist/structure/types/filters.js.map +1 -0
- package/dist/structure/types/index.d.ts +11 -0
- package/dist/structure/types/index.d.ts.map +1 -0
- package/dist/structure/types/index.js +7 -0
- package/dist/structure/types/index.js.map +1 -0
- package/dist/structure/types/permissions.d.ts +159 -0
- package/dist/structure/types/permissions.d.ts.map +1 -0
- package/dist/structure/types/permissions.js +49 -0
- package/dist/structure/types/permissions.js.map +1 -0
- package/dist/structure/types/structure.d.ts +342 -0
- package/dist/structure/types/structure.d.ts.map +1 -0
- package/dist/structure/types/structure.js +6 -0
- package/dist/structure/types/structure.js.map +1 -0
- package/dist/structure/types/views.d.ts +278 -0
- package/dist/structure/types/views.d.ts.map +1 -0
- package/dist/structure/types/views.js +6 -0
- package/dist/structure/types/views.js.map +1 -0
- package/dist/structure/utils/hash.d.ts +61 -0
- package/dist/structure/utils/hash.d.ts.map +1 -0
- package/dist/structure/utils/hash.js +118 -0
- package/dist/structure/utils/hash.js.map +1 -0
- package/dist/structure/utils/index.d.ts +10 -0
- package/dist/structure/utils/index.d.ts.map +1 -0
- package/dist/structure/utils/index.js +7 -0
- package/dist/structure/utils/index.js.map +1 -0
- package/dist/structure/utils/permission-checker.d.ts +57 -0
- package/dist/structure/utils/permission-checker.d.ts.map +1 -0
- package/dist/structure/utils/permission-checker.js +286 -0
- package/dist/structure/utils/permission-checker.js.map +1 -0
- package/dist/structure/utils/query-builder.d.ts +82 -0
- package/dist/structure/utils/query-builder.d.ts.map +1 -0
- package/dist/structure/utils/query-builder.js +489 -0
- package/dist/structure/utils/query-builder.js.map +1 -0
- package/dist/structure/utils/structure-merger.d.ts +91 -0
- package/dist/structure/utils/structure-merger.d.ts.map +1 -0
- package/dist/structure/utils/structure-merger.js +445 -0
- package/dist/structure/utils/structure-merger.js.map +1 -0
- package/dist/structure/validation/schemas.d.ts +3107 -0
- package/dist/structure/validation/schemas.d.ts.map +1 -0
- package/dist/structure/validation/schemas.js +436 -0
- package/dist/structure/validation/schemas.js.map +1 -0
- package/dist/types/api-requests.d.ts +334 -0
- package/dist/types/api-requests.d.ts.map +1 -0
- package/dist/types/api-requests.js +8 -0
- package/dist/types/api-requests.js.map +1 -0
- package/dist/types/auth.d.ts +394 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +8 -0
- package/dist/types/auth.js.map +1 -0
- package/dist/types/document.d.ts +49 -0
- package/dist/types/document.d.ts.map +1 -0
- package/dist/types/document.js +6 -0
- package/dist/types/document.js.map +1 -0
- package/dist/types/field-system.d.ts +197 -0
- package/dist/types/field-system.d.ts.map +1 -0
- package/dist/types/field-system.js +8 -0
- package/dist/types/field-system.js.map +1 -0
- package/dist/types/fields.d.ts +17 -0
- package/dist/types/fields.d.ts.map +1 -0
- package/dist/types/fields.js +21 -0
- package/dist/types/fields.js.map +1 -0
- package/dist/types/http.d.ts +162 -0
- package/dist/types/http.d.ts.map +1 -0
- package/dist/types/http.js +8 -0
- package/dist/types/http.js.map +1 -0
- package/dist/types/i18n.d.ts +56 -0
- package/dist/types/i18n.d.ts.map +1 -0
- package/dist/types/i18n.js +25 -0
- package/dist/types/i18n.js.map +1 -0
- package/dist/types/index.d.ts +22 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mail.d.ts +224 -0
- package/dist/types/mail.d.ts.map +1 -0
- package/dist/types/mail.js +8 -0
- package/dist/types/mail.js.map +1 -0
- package/dist/types/media.d.ts +56 -0
- package/dist/types/media.d.ts.map +1 -0
- package/dist/types/media.js +6 -0
- package/dist/types/media.js.map +1 -0
- package/dist/types/oauth2.d.ts +287 -0
- package/dist/types/oauth2.d.ts.map +1 -0
- package/dist/types/oauth2.js +43 -0
- package/dist/types/oauth2.js.map +1 -0
- package/dist/types/passkey.d.ts +217 -0
- package/dist/types/passkey.d.ts.map +1 -0
- package/dist/types/passkey.js +8 -0
- package/dist/types/passkey.js.map +1 -0
- package/dist/types/slug.d.ts +99 -0
- package/dist/types/slug.d.ts.map +1 -0
- package/dist/types/slug.js +8 -0
- package/dist/types/slug.js.map +1 -0
- package/package.json +183 -0
|
@@ -0,0 +1,1074 @@
|
|
|
1
|
+
import { detectCryptoAdapter } from '../crypto/adapter.js';
|
|
2
|
+
import { SecurityValidator } from '../security/validation.js';
|
|
3
|
+
import { SchemaRegistry } from '../schema/registry.js';
|
|
4
|
+
import { DocumentValidator } from '../validation/validator.js';
|
|
5
|
+
import { RateLimiter } from '../security/rate-limiter.js';
|
|
6
|
+
import { IdGenerator } from '../utils/id-generator.js';
|
|
7
|
+
import { createLogger } from '../utils/logger.js';
|
|
8
|
+
import { createImageProcessor } from '../media/image-processor.js';
|
|
9
|
+
import { TrokkyEventBus, MemoryEventStorage } from '../events/index.js';
|
|
10
|
+
import { systemStartup } from '../events/index.js';
|
|
11
|
+
import { OAuth2AuthorizationServer } from '../security/oauth2/index.js';
|
|
12
|
+
import { AuthService } from '../services/auth-service.js';
|
|
13
|
+
import { MFAService, generateSecureSecret } from '../services/mfa-service.js';
|
|
14
|
+
import { TrustedDeviceService } from '../services/trusted-device-service.js';
|
|
15
|
+
import { OAuthService } from '../services/oauth-service.js';
|
|
16
|
+
import { PasskeyService } from '../services/passkey-service.js';
|
|
17
|
+
import { UserService } from '../services/user-service.js';
|
|
18
|
+
import { TokenService } from '../services/token-service.js';
|
|
19
|
+
import { DocumentService } from '../services/document-service.js';
|
|
20
|
+
import { MediaService } from '../services/media-service.js';
|
|
21
|
+
import { CaptchaService } from '../services/captcha-service.js';
|
|
22
|
+
import { OAuth2ServerService } from '../services/oauth2-server-service.js';
|
|
23
|
+
export class TrokkyCore {
|
|
24
|
+
// Split storage adapters (new architecture)
|
|
25
|
+
dataStorage;
|
|
26
|
+
mediaStorage;
|
|
27
|
+
// Legacy unified storage adapter (for backward compatibility)
|
|
28
|
+
storage;
|
|
29
|
+
schemas;
|
|
30
|
+
validator;
|
|
31
|
+
idGenerator;
|
|
32
|
+
rateLimiter;
|
|
33
|
+
securityEnabled;
|
|
34
|
+
options;
|
|
35
|
+
jwtSecret;
|
|
36
|
+
config;
|
|
37
|
+
auditLogger;
|
|
38
|
+
cryptoAdapter;
|
|
39
|
+
imageProcessor; // Initialized in init() method
|
|
40
|
+
imageProcessorConfig;
|
|
41
|
+
logger = createLogger('core', 'TrokkyCore');
|
|
42
|
+
auditLog = createLogger('core', 'Audit');
|
|
43
|
+
// Event system
|
|
44
|
+
eventBus;
|
|
45
|
+
eventsEnabled;
|
|
46
|
+
// OAuth2 Authorization Server (enables CLI login and external SSO)
|
|
47
|
+
oauth2Server = null;
|
|
48
|
+
// Secure callbacks for sensitive operations (not logged in events)
|
|
49
|
+
userCreatedWithPasswordCallback;
|
|
50
|
+
// Extracted domain services (authentication, MFA, trusted devices, OAuth, passkeys)
|
|
51
|
+
authService;
|
|
52
|
+
mfaService;
|
|
53
|
+
trustedDeviceService;
|
|
54
|
+
oauthService;
|
|
55
|
+
passkeyService;
|
|
56
|
+
userService;
|
|
57
|
+
tokenService;
|
|
58
|
+
documentService;
|
|
59
|
+
mediaService;
|
|
60
|
+
captchaService;
|
|
61
|
+
oauth2ServerService;
|
|
62
|
+
constructor(config, storageAdapterOrAdapters, options = {}) {
|
|
63
|
+
// Determine if we're using unified or split adapters
|
|
64
|
+
if (this.isTrokkyStorageAdapters(storageAdapterOrAdapters)) {
|
|
65
|
+
// Split adapters (new architecture)
|
|
66
|
+
this.dataStorage = storageAdapterOrAdapters.data;
|
|
67
|
+
this.mediaStorage = storageAdapterOrAdapters.media;
|
|
68
|
+
this.storage = undefined;
|
|
69
|
+
this.logger.info('TrokkyCore initialized with split storage adapters', {
|
|
70
|
+
dataAdapter: this.dataStorage.constructor?.name || 'DataStorageAdapter',
|
|
71
|
+
mediaAdapter: this.mediaStorage.constructor?.name || 'MediaStorageAdapter'
|
|
72
|
+
});
|
|
73
|
+
// Validate split adapters have required methods
|
|
74
|
+
this.validateStorageAdapters();
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// Unified adapter (legacy support)
|
|
78
|
+
this.storage = storageAdapterOrAdapters;
|
|
79
|
+
// Create adapter wrappers for backward compatibility
|
|
80
|
+
this.dataStorage = this.createDataAdapterWrapper(storageAdapterOrAdapters);
|
|
81
|
+
this.mediaStorage = this.createMediaAdapterWrapper(storageAdapterOrAdapters);
|
|
82
|
+
this.logger.warn('TrokkyCore using legacy unified storage adapter - consider migrating to split adapters', {
|
|
83
|
+
adapter: storageAdapterOrAdapters.constructor?.name || 'StorageAdapter'
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
this.options = options;
|
|
87
|
+
this.config = config;
|
|
88
|
+
this.schemas = options.schemaRegistry || new SchemaRegistry(config.schemas, config.features);
|
|
89
|
+
this.validator = options.validator || new DocumentValidator(this.schemas);
|
|
90
|
+
this.idGenerator = options.idGenerator || new IdGenerator();
|
|
91
|
+
this.securityEnabled = options.enableSecurity ?? config.security?.validateInput ?? true;
|
|
92
|
+
// Initialize JWT secret (use provided secret, environment variable if available, or generate one)
|
|
93
|
+
const envJwt = (typeof process !== 'undefined' && process.env?.TROKKY_JWT_SECRET)
|
|
94
|
+
? process.env.TROKKY_JWT_SECRET
|
|
95
|
+
: undefined;
|
|
96
|
+
this.jwtSecret = options.jwtSecret || envJwt || this.generateSecureSecret();
|
|
97
|
+
// Initialize audit logger
|
|
98
|
+
this.auditLogger = options.auditLogger;
|
|
99
|
+
// Initialize crypto adapter
|
|
100
|
+
this.cryptoAdapter = options.cryptoAdapter || detectCryptoAdapter({
|
|
101
|
+
...options.cryptoOptions,
|
|
102
|
+
adapterType: options.cryptoOptions?.adapterType || 'auto'
|
|
103
|
+
});
|
|
104
|
+
// Image processor will be initialized in init() method
|
|
105
|
+
// Store config for async initialization
|
|
106
|
+
this.imageProcessorConfig = options.imageProcessorConfig || {
|
|
107
|
+
type: config.media?.imageProcessor || 'none',
|
|
108
|
+
variants: config.media?.imageVariants || [],
|
|
109
|
+
options: config.media?.imageProcessorOptions || {}
|
|
110
|
+
};
|
|
111
|
+
if (config.security?.rateLimitEnabled || config.api?.rateLimit) {
|
|
112
|
+
const rateLimitConfig = {
|
|
113
|
+
windowMs: config.api?.rateLimit?.windowMs || 60 * 1000,
|
|
114
|
+
maxRequests: config.api?.rateLimit?.maxRequests || 1000
|
|
115
|
+
};
|
|
116
|
+
this.rateLimiter = options.rateLimiter || new RateLimiter(rateLimitConfig);
|
|
117
|
+
}
|
|
118
|
+
// Initialize event system
|
|
119
|
+
this.eventsEnabled = options.enableEvents ?? true;
|
|
120
|
+
if (options.eventBus) {
|
|
121
|
+
this.eventBus = options.eventBus;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Create default event bus with memory storage
|
|
125
|
+
const eventStorage = new MemoryEventStorage({
|
|
126
|
+
maxEvents: 1000,
|
|
127
|
+
autoCleanup: true
|
|
128
|
+
});
|
|
129
|
+
const eventBusConfig = {
|
|
130
|
+
maxHistorySize: 1000,
|
|
131
|
+
enablePersistence: true,
|
|
132
|
+
storage: eventStorage,
|
|
133
|
+
enableWebhooks: true,
|
|
134
|
+
maxConcurrentWebhooks: 5,
|
|
135
|
+
dataStorage: this.dataStorage?.saveWebhook && this.dataStorage?.listWebhooks && this.dataStorage?.deleteWebhook
|
|
136
|
+
? this.dataStorage
|
|
137
|
+
: undefined,
|
|
138
|
+
...options.eventBusConfig
|
|
139
|
+
};
|
|
140
|
+
this.eventBus = new TrokkyEventBus(eventBusConfig);
|
|
141
|
+
}
|
|
142
|
+
// Initialize extracted domain services
|
|
143
|
+
this.authService = new AuthService({
|
|
144
|
+
cryptoAdapter: this.cryptoAdapter,
|
|
145
|
+
jwtSecret: this.jwtSecret,
|
|
146
|
+
config: this.config,
|
|
147
|
+
logger: this.logger,
|
|
148
|
+
getUser: (id) => this.getUser(id),
|
|
149
|
+
getUserByUsername: (username) => this.getUserByUsername(username),
|
|
150
|
+
updateUser: (id, userData) => this.updateUser(id, userData),
|
|
151
|
+
// Adapters that support a conditional write set updatedAt themselves
|
|
152
|
+
updateUserIf: this.dataStorage.saveUserIf
|
|
153
|
+
? async (id, userData, condition) => {
|
|
154
|
+
// Same guards as updateUser(); only the write itself is conditional.
|
|
155
|
+
if (this.rateLimiter) {
|
|
156
|
+
await this.rateLimiter.checkRateLimit('updateUser');
|
|
157
|
+
}
|
|
158
|
+
if (this.securityEnabled) {
|
|
159
|
+
SecurityValidator.validateDocumentId(id);
|
|
160
|
+
}
|
|
161
|
+
return this.dataStorage.saveUserIf(id, userData, condition);
|
|
162
|
+
}
|
|
163
|
+
: undefined,
|
|
164
|
+
validateAppToken: (token) => this.validateAppToken(token),
|
|
165
|
+
logAuditEvent: (event) => this.logAuditEvent(event),
|
|
166
|
+
checkMFARequired: (userId) => this.mfaService.checkMFARequired(userId),
|
|
167
|
+
isDeviceTrusted: (userId, deviceId) => this.trustedDeviceService.isDeviceTrusted(userId, deviceId),
|
|
168
|
+
trustDevice: (userId, deviceId, deviceName, deviceOptions) => this.trustedDeviceService.trustDevice(userId, deviceId, deviceName, deviceOptions),
|
|
169
|
+
getTOTPService: (issuer) => this.mfaService.getTOTPService(issuer)
|
|
170
|
+
});
|
|
171
|
+
this.mfaService = new MFAService({
|
|
172
|
+
logger: this.logger,
|
|
173
|
+
eventBus: this.eventBus,
|
|
174
|
+
eventsEnabled: this.eventsEnabled,
|
|
175
|
+
getUser: (id) => this.getUser(id),
|
|
176
|
+
updateUser: (id, userData) => this.updateUser(id, userData),
|
|
177
|
+
getSettings: () => this.getSettings(),
|
|
178
|
+
verifyPassword: (plainPassword, hashedPassword) => this.authService.verifyPassword(plainPassword, hashedPassword),
|
|
179
|
+
logAuditEvent: (event) => this.logAuditEvent(event)
|
|
180
|
+
});
|
|
181
|
+
this.trustedDeviceService = new TrustedDeviceService({
|
|
182
|
+
logger: this.logger,
|
|
183
|
+
getUser: (id) => this.getUser(id),
|
|
184
|
+
updateUser: (id, userData) => this.updateUser(id, userData),
|
|
185
|
+
getSettings: () => this.getSettings()
|
|
186
|
+
});
|
|
187
|
+
this.oauthService = new OAuthService({
|
|
188
|
+
config: this.config,
|
|
189
|
+
logger: this.logger,
|
|
190
|
+
dataStorage: this.dataStorage,
|
|
191
|
+
getUser: (id) => this.getUser(id),
|
|
192
|
+
updateUser: (id, userData) => this.updateUser(id, userData),
|
|
193
|
+
listUsers: (listOptions) => this.listUsers(listOptions),
|
|
194
|
+
logAuditEvent: (event) => this.logAuditEvent(event),
|
|
195
|
+
checkMFARequired: (userId) => this.mfaService.checkMFARequired(userId),
|
|
196
|
+
isDeviceTrusted: (userId, deviceId) => this.trustedDeviceService.isDeviceTrusted(userId, deviceId),
|
|
197
|
+
issueFullTokens: (user, tokenOptions) => this.authService.issueFullTokens(user, tokenOptions),
|
|
198
|
+
generateMFAPendingToken: (user, methods) => this.authService.generateMFAPendingToken(user, methods),
|
|
199
|
+
generateMFASetupToken: (user, allowedMethods) => this.authService.generateMFASetupToken(user, allowedMethods),
|
|
200
|
+
generateAuthToken: (user, expiresIn, rememberMe) => this.authService.generateAuthToken(user, expiresIn, rememberMe),
|
|
201
|
+
verifyAuthToken: (token) => this.authService.verifyAuthToken(token)
|
|
202
|
+
});
|
|
203
|
+
this.passkeyService = new PasskeyService({
|
|
204
|
+
config: this.config,
|
|
205
|
+
logger: this.logger,
|
|
206
|
+
dataStorage: this.dataStorage,
|
|
207
|
+
getUser: (id) => this.getUser(id),
|
|
208
|
+
updateUser: (id, userData) => this.updateUser(id, userData),
|
|
209
|
+
listUsers: (listOptions) => this.listUsers(listOptions),
|
|
210
|
+
logAuditEvent: (event) => this.logAuditEvent(event),
|
|
211
|
+
checkMFARequired: (userId) => this.mfaService.checkMFARequired(userId),
|
|
212
|
+
isDeviceTrusted: (userId, deviceId) => this.trustedDeviceService.isDeviceTrusted(userId, deviceId),
|
|
213
|
+
issueFullTokens: (user, tokenOptions) => this.authService.issueFullTokens(user, tokenOptions),
|
|
214
|
+
generateMFAPendingToken: (user, methods) => this.authService.generateMFAPendingToken(user, methods),
|
|
215
|
+
generateMFASetupToken: (user, allowedMethods) => this.authService.generateMFASetupToken(user, allowedMethods)
|
|
216
|
+
});
|
|
217
|
+
this.userService = new UserService({
|
|
218
|
+
logger: this.logger,
|
|
219
|
+
dataStorage: this.dataStorage,
|
|
220
|
+
idGenerator: this.idGenerator,
|
|
221
|
+
rateLimiter: this.rateLimiter,
|
|
222
|
+
securityEnabled: this.securityEnabled,
|
|
223
|
+
eventBus: this.eventBus,
|
|
224
|
+
hashPassword: (password) => this.hashPassword(password),
|
|
225
|
+
checkWeakPassword: (password) => this.checkWeakPassword(password),
|
|
226
|
+
logAuditEvent: (event) => this.logAuditEvent(event),
|
|
227
|
+
getUserCreatedWithPasswordCallback: () => this.userCreatedWithPasswordCallback
|
|
228
|
+
});
|
|
229
|
+
this.tokenService = new TokenService({
|
|
230
|
+
dataStorage: this.dataStorage,
|
|
231
|
+
idGenerator: this.idGenerator,
|
|
232
|
+
cryptoAdapter: this.cryptoAdapter,
|
|
233
|
+
rateLimiter: this.rateLimiter,
|
|
234
|
+
securityEnabled: this.securityEnabled,
|
|
235
|
+
logAuditEvent: (event) => this.logAuditEvent(event)
|
|
236
|
+
});
|
|
237
|
+
this.documentService = new DocumentService({
|
|
238
|
+
logger: this.logger,
|
|
239
|
+
auditLog: this.auditLog,
|
|
240
|
+
dataStorage: this.dataStorage,
|
|
241
|
+
schemas: this.schemas,
|
|
242
|
+
idGenerator: this.idGenerator,
|
|
243
|
+
rateLimiter: this.rateLimiter,
|
|
244
|
+
securityEnabled: this.securityEnabled,
|
|
245
|
+
eventBus: this.eventBus,
|
|
246
|
+
eventsEnabled: this.eventsEnabled,
|
|
247
|
+
validateDocument: (collection, data) => this.validateDocument(collection, data)
|
|
248
|
+
});
|
|
249
|
+
this.mediaService = new MediaService({
|
|
250
|
+
config: this.config,
|
|
251
|
+
logger: this.logger,
|
|
252
|
+
mediaStorage: this.mediaStorage,
|
|
253
|
+
idGenerator: this.idGenerator,
|
|
254
|
+
rateLimiter: this.rateLimiter,
|
|
255
|
+
securityEnabled: this.securityEnabled,
|
|
256
|
+
eventBus: this.eventBus,
|
|
257
|
+
eventsEnabled: this.eventsEnabled,
|
|
258
|
+
getImageProcessor: () => this.imageProcessor
|
|
259
|
+
});
|
|
260
|
+
this.captchaService = new CaptchaService({
|
|
261
|
+
config: this.config,
|
|
262
|
+
logger: this.logger
|
|
263
|
+
});
|
|
264
|
+
this.oauth2ServerService = new OAuth2ServerService({
|
|
265
|
+
logger: this.logger,
|
|
266
|
+
cryptoAdapter: this.cryptoAdapter,
|
|
267
|
+
jwtSecret: this.jwtSecret,
|
|
268
|
+
getOAuth2Server: () => this.oauth2Server,
|
|
269
|
+
getOAuth2Options: () => this.options.oauth2,
|
|
270
|
+
getUser: (id) => this.getUser(id),
|
|
271
|
+
updateUser: (id, userData) => this.updateUser(id, userData)
|
|
272
|
+
});
|
|
273
|
+
// Emit system startup event
|
|
274
|
+
if (this.eventsEnabled) {
|
|
275
|
+
this.eventBus.emitEvent(systemStartup('TrokkyCore')).catch(error => {
|
|
276
|
+
this.logger.warn('Failed to emit system startup event', error);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Public getters for external access
|
|
281
|
+
/**
|
|
282
|
+
* Get the event bus instance for emitting custom events
|
|
283
|
+
*/
|
|
284
|
+
get events() {
|
|
285
|
+
return this.eventBus;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Get the configuration
|
|
289
|
+
*/
|
|
290
|
+
get configuration() {
|
|
291
|
+
return this.config;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Register a secure callback for when users are created with temporary passwords
|
|
295
|
+
* This callback is NOT part of the event system and does not get logged
|
|
296
|
+
* Used by mail services to send welcome emails with credentials
|
|
297
|
+
*/
|
|
298
|
+
onUserCreatedWithPassword(callback) {
|
|
299
|
+
this.userCreatedWithPasswordCallback = callback;
|
|
300
|
+
this.logger.debug('Registered secure callback for user creation with password');
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Check rate limit for a specific operation
|
|
304
|
+
* Allows routes and external code to use the rate limiter
|
|
305
|
+
*/
|
|
306
|
+
async checkRateLimit(operation, context) {
|
|
307
|
+
if (this.rateLimiter) {
|
|
308
|
+
await this.rateLimiter.checkRateLimit(operation, context);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// Helper methods for adapter management
|
|
312
|
+
isTrokkyStorageAdapters(adapter) {
|
|
313
|
+
return adapter &&
|
|
314
|
+
typeof adapter === 'object' &&
|
|
315
|
+
'data' in adapter &&
|
|
316
|
+
'media' in adapter &&
|
|
317
|
+
typeof adapter.data === 'object' &&
|
|
318
|
+
typeof adapter.media === 'object';
|
|
319
|
+
}
|
|
320
|
+
createDataAdapterWrapper(storage) {
|
|
321
|
+
return {
|
|
322
|
+
// Document operations
|
|
323
|
+
getDocument: storage.getDocument.bind(storage),
|
|
324
|
+
saveDocument: storage.saveDocument.bind(storage),
|
|
325
|
+
listDocuments: storage.listDocuments.bind(storage),
|
|
326
|
+
deleteDocument: storage.deleteDocument.bind(storage),
|
|
327
|
+
// User operations (with fallback if not implemented)
|
|
328
|
+
getUser: storage.getUser?.bind(storage) || (() => { throw new Error('User operations not supported by unified adapter'); }),
|
|
329
|
+
saveUser: storage.saveUser?.bind(storage) || (() => { throw new Error('User operations not supported by unified adapter'); }),
|
|
330
|
+
saveUserIf: storage.saveUserIf?.bind(storage),
|
|
331
|
+
listUsers: storage.listUsers?.bind(storage) || (() => { throw new Error('User operations not supported by unified adapter'); }),
|
|
332
|
+
deleteUser: storage.deleteUser?.bind(storage) || (() => { throw new Error('User operations not supported by unified adapter'); }),
|
|
333
|
+
getUserByUsername: storage.getUserByUsername?.bind(storage) || (() => { throw new Error('User operations not supported by unified adapter'); }),
|
|
334
|
+
getUserByEmail: storage.getUserByEmail?.bind(storage) || (() => { throw new Error('User operations not supported by unified adapter'); }),
|
|
335
|
+
// App token operations (with fallback if not implemented)
|
|
336
|
+
getAppToken: storage.getAppToken?.bind(storage) || (() => { throw new Error('App token operations not supported by unified adapter'); }),
|
|
337
|
+
saveAppToken: storage.saveAppToken?.bind(storage) || (() => { throw new Error('App token operations not supported by unified adapter'); }),
|
|
338
|
+
listAppTokens: storage.listAppTokens?.bind(storage) || (() => { throw new Error('App token operations not supported by unified adapter'); }),
|
|
339
|
+
deleteAppToken: storage.deleteAppToken?.bind(storage) || (() => { throw new Error('App token operations not supported by unified adapter'); }),
|
|
340
|
+
getAppTokenByHash: storage.getAppTokenByHash?.bind(storage) || (() => { throw new Error('App token operations not supported by unified adapter'); }),
|
|
341
|
+
// Utility operations
|
|
342
|
+
healthCheck: storage.healthCheck.bind(storage),
|
|
343
|
+
migrate: storage.migrate?.bind(storage)
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
createMediaAdapterWrapper(storage) {
|
|
347
|
+
return {
|
|
348
|
+
// File operations
|
|
349
|
+
uploadFile: storage.uploadFile.bind(storage),
|
|
350
|
+
getFile: storage.getFile.bind(storage),
|
|
351
|
+
updateFile: storage.updateFile?.bind(storage) || (() => { throw new Error('File update not supported by unified adapter'); }),
|
|
352
|
+
getFileContent: storage.getFileContent.bind(storage),
|
|
353
|
+
listMedia: storage.listMedia?.bind(storage) || (() => { throw new Error('Media listing not supported by unified adapter'); }),
|
|
354
|
+
deleteFile: storage.deleteFile.bind(storage),
|
|
355
|
+
// Variant operations (with fallback if not implemented)
|
|
356
|
+
saveVariantFile: storage.saveVariantFile?.bind(storage) || (() => { throw new Error('Variant operations not supported by unified adapter'); }),
|
|
357
|
+
getVariantContent: storage.getVariantContent?.bind(storage) || (() => { throw new Error('Variant operations not supported by unified adapter'); }),
|
|
358
|
+
deleteVariantFiles: storage.deleteVariantFiles?.bind(storage) || (() => { throw new Error('Variant operations not supported by unified adapter'); }),
|
|
359
|
+
// Utility operations
|
|
360
|
+
healthCheck: storage.healthCheck.bind(storage)
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
// Adapter validation
|
|
364
|
+
validateStorageAdapters() {
|
|
365
|
+
// Validate DataStorageAdapter has required methods
|
|
366
|
+
const requiredDataMethods = [
|
|
367
|
+
'getDocument', 'saveDocument', 'listDocuments', 'deleteDocument',
|
|
368
|
+
'getUser', 'saveUser', 'listUsers', 'deleteUser', 'getUserByUsername', 'getUserByEmail',
|
|
369
|
+
'getAppToken', 'saveAppToken', 'listAppTokens', 'deleteAppToken', 'getAppTokenByHash',
|
|
370
|
+
'healthCheck'
|
|
371
|
+
];
|
|
372
|
+
for (const method of requiredDataMethods) {
|
|
373
|
+
if (typeof this.dataStorage[method] !== 'function') {
|
|
374
|
+
throw new Error(`DataStorageAdapter missing required method: ${method}`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
// Validate MediaStorageAdapter has required methods
|
|
378
|
+
const requiredMediaMethods = [
|
|
379
|
+
'uploadFile', 'getFile', 'getFileContent', 'deleteFile', 'healthCheck'
|
|
380
|
+
];
|
|
381
|
+
for (const method of requiredMediaMethods) {
|
|
382
|
+
if (typeof this.mediaStorage[method] !== 'function') {
|
|
383
|
+
throw new Error(`MediaStorageAdapter missing required method: ${method}`);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
this.logger.debug('Storage adapters validation passed', {
|
|
387
|
+
dataMethodCount: requiredDataMethods.length,
|
|
388
|
+
mediaMethodCount: requiredMediaMethods.length
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
// Public getters
|
|
392
|
+
getEventBus() {
|
|
393
|
+
return this.eventBus;
|
|
394
|
+
}
|
|
395
|
+
// Initialization
|
|
396
|
+
async init() {
|
|
397
|
+
// Initialize image processor asynchronously
|
|
398
|
+
if (!this.options.imageProcessor) {
|
|
399
|
+
this.imageProcessor = await createImageProcessor(this.imageProcessorConfig);
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
this.imageProcessor = this.options.imageProcessor;
|
|
403
|
+
}
|
|
404
|
+
// Initialize OAuth2 Authorization Server if enabled
|
|
405
|
+
if (this.options.oauth2?.enabled) {
|
|
406
|
+
const oauth2Config = this.options.oauth2;
|
|
407
|
+
if (!oauth2Config.issuer) {
|
|
408
|
+
this.logger.warn('OAuth2 enabled but no issuer configured - using default localhost');
|
|
409
|
+
}
|
|
410
|
+
this.oauth2Server = new OAuth2AuthorizationServer({
|
|
411
|
+
issuer: oauth2Config.issuer || 'http://localhost:3000',
|
|
412
|
+
jwtSecret: this.jwtSecret,
|
|
413
|
+
accessTokenTtl: oauth2Config.accessTokenTtl,
|
|
414
|
+
refreshTokenTtl: oauth2Config.refreshTokenTtl,
|
|
415
|
+
deviceCodeTtl: oauth2Config.deviceCodeTtl,
|
|
416
|
+
authCodeTtl: oauth2Config.authCodeTtl,
|
|
417
|
+
pollingInterval: oauth2Config.pollingInterval,
|
|
418
|
+
clients: oauth2Config.clients
|
|
419
|
+
});
|
|
420
|
+
this.logger.info('OAuth2 Authorization Server initialized', {
|
|
421
|
+
issuer: oauth2Config.issuer || 'http://localhost:3000',
|
|
422
|
+
clients: oauth2Config.clients?.length || 0
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
// Setup admin user from environment variables if configured
|
|
426
|
+
if (this.options.setupAdminFromEnv) {
|
|
427
|
+
await this.setupAdminFromEnv();
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
// Document operations
|
|
431
|
+
async getDocument(collection, id) {
|
|
432
|
+
return this.documentService.getDocument(collection, id);
|
|
433
|
+
}
|
|
434
|
+
async saveDocument(collection, data, auditContext) {
|
|
435
|
+
return this.documentService.saveDocument(collection, data, auditContext);
|
|
436
|
+
}
|
|
437
|
+
async listDocuments(collection, options) {
|
|
438
|
+
return this.documentService.listDocuments(collection, options);
|
|
439
|
+
}
|
|
440
|
+
async countDocuments(collection, filter) {
|
|
441
|
+
return this.documentService.countDocuments(collection, filter);
|
|
442
|
+
}
|
|
443
|
+
async deleteDocument(collection, id, auditContext) {
|
|
444
|
+
return this.documentService.deleteDocument(collection, id, auditContext);
|
|
445
|
+
}
|
|
446
|
+
// ==========================================================================
|
|
447
|
+
// AUDIT LOG OPERATIONS
|
|
448
|
+
// ==========================================================================
|
|
449
|
+
/**
|
|
450
|
+
* Get audit logs for a specific document
|
|
451
|
+
*/
|
|
452
|
+
async getDocumentAuditLogs(documentId, options) {
|
|
453
|
+
return this.documentService.getDocumentAuditLogs(documentId, options);
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Get audit logs for a collection
|
|
457
|
+
*/
|
|
458
|
+
async getCollectionAuditLogs(collection, options) {
|
|
459
|
+
return this.documentService.getCollectionAuditLogs(collection, options);
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Get audit logs for a specific actor
|
|
463
|
+
*/
|
|
464
|
+
async getActorAuditLogs(actorId, options) {
|
|
465
|
+
return this.documentService.getActorAuditLogs(actorId, options);
|
|
466
|
+
}
|
|
467
|
+
// Media operations
|
|
468
|
+
async uploadMedia(file) {
|
|
469
|
+
return this.mediaService.uploadMedia(file);
|
|
470
|
+
}
|
|
471
|
+
async getMedia(id) {
|
|
472
|
+
return this.mediaService.getMedia(id);
|
|
473
|
+
}
|
|
474
|
+
async updateMedia(id, metadata) {
|
|
475
|
+
return this.mediaService.updateMedia(id, metadata);
|
|
476
|
+
}
|
|
477
|
+
async getMediaContent(id) {
|
|
478
|
+
return this.mediaService.getMediaContent(id);
|
|
479
|
+
}
|
|
480
|
+
async listMedia(options) {
|
|
481
|
+
return this.mediaService.listMedia(options);
|
|
482
|
+
}
|
|
483
|
+
async deleteMedia(id) {
|
|
484
|
+
return this.mediaService.deleteMedia(id);
|
|
485
|
+
}
|
|
486
|
+
async regenerateMediaVariants(id) {
|
|
487
|
+
return this.mediaService.regenerateMediaVariants(id);
|
|
488
|
+
}
|
|
489
|
+
// Schema operations
|
|
490
|
+
getSchema(name) {
|
|
491
|
+
return this.schemas.getSchema(name);
|
|
492
|
+
}
|
|
493
|
+
getAllSchemas() {
|
|
494
|
+
return this.schemas.getAllSchemas();
|
|
495
|
+
}
|
|
496
|
+
validateDocument(collection, data) {
|
|
497
|
+
return this.validator.validateDocument(collection, data);
|
|
498
|
+
}
|
|
499
|
+
// Image processing operations
|
|
500
|
+
getImageUrl(imageId, variantName) {
|
|
501
|
+
return this.mediaService.getImageUrl(imageId, variantName);
|
|
502
|
+
}
|
|
503
|
+
async getImageProcessor() {
|
|
504
|
+
return this.mediaService.getImageProcessor();
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Get storage adapter (legacy unified adapter)
|
|
508
|
+
* @deprecated Use getDataStorageAdapter() and getMediaStorageAdapter() instead
|
|
509
|
+
*/
|
|
510
|
+
getStorageAdapter() {
|
|
511
|
+
return this.storage || null;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Get data storage adapter
|
|
515
|
+
*/
|
|
516
|
+
getDataStorageAdapter() {
|
|
517
|
+
return this.dataStorage;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Get media storage adapter
|
|
521
|
+
*/
|
|
522
|
+
getMediaStorageAdapter() {
|
|
523
|
+
return this.mediaStorage;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Get both storage adapters
|
|
527
|
+
*/
|
|
528
|
+
getStorageAdapters() {
|
|
529
|
+
return {
|
|
530
|
+
data: this.dataStorage,
|
|
531
|
+
media: this.mediaStorage
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
// Health check
|
|
535
|
+
async healthCheck() {
|
|
536
|
+
try {
|
|
537
|
+
// Check health of both storage adapters
|
|
538
|
+
const dataStorageHealthy = await this.dataStorage.healthCheck();
|
|
539
|
+
const mediaStorageHealthy = await this.mediaStorage.healthCheck();
|
|
540
|
+
const storageHealthy = dataStorageHealthy && mediaStorageHealthy;
|
|
541
|
+
const schemasLoaded = this.schemas.getAllSchemas().length > 0;
|
|
542
|
+
const imageProcessorHealthy = await this.imageProcessor.healthCheck();
|
|
543
|
+
return storageHealthy && schemasLoaded && imageProcessorHealthy;
|
|
544
|
+
}
|
|
545
|
+
catch {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
// Utility methods
|
|
550
|
+
validateAndSanitizeMediaFile(file) {
|
|
551
|
+
return this.mediaService.validateAndSanitizeMediaFile(file);
|
|
552
|
+
}
|
|
553
|
+
sanitizeFilename(filename) {
|
|
554
|
+
return this.mediaService.sanitizeFilename(filename);
|
|
555
|
+
}
|
|
556
|
+
getFileExtension(filename) {
|
|
557
|
+
return this.mediaService.getFileExtension(filename);
|
|
558
|
+
}
|
|
559
|
+
// User management operations (system entities)
|
|
560
|
+
async createUser(userData) {
|
|
561
|
+
return this.userService.createUser(userData);
|
|
562
|
+
}
|
|
563
|
+
async getUser(id) {
|
|
564
|
+
return this.userService.getUser(id);
|
|
565
|
+
}
|
|
566
|
+
async getUserByUsername(username) {
|
|
567
|
+
return this.userService.getUserByUsername(username);
|
|
568
|
+
}
|
|
569
|
+
async getUserByEmail(email) {
|
|
570
|
+
return this.userService.getUserByEmail(email);
|
|
571
|
+
}
|
|
572
|
+
async updateUser(id, userData) {
|
|
573
|
+
return this.userService.updateUser(id, userData);
|
|
574
|
+
}
|
|
575
|
+
async listUsers(options) {
|
|
576
|
+
return this.userService.listUsers(options);
|
|
577
|
+
}
|
|
578
|
+
async deleteUser(id) {
|
|
579
|
+
return this.userService.deleteUser(id);
|
|
580
|
+
}
|
|
581
|
+
// App Token management operations
|
|
582
|
+
async listAppTokens(options) {
|
|
583
|
+
return this.tokenService.listAppTokens(options);
|
|
584
|
+
}
|
|
585
|
+
async createAppToken(tokenData, createdBy) {
|
|
586
|
+
return this.tokenService.createAppToken(tokenData, createdBy);
|
|
587
|
+
}
|
|
588
|
+
async getAppToken(id) {
|
|
589
|
+
return this.tokenService.getAppToken(id);
|
|
590
|
+
}
|
|
591
|
+
async validateAppToken(token) {
|
|
592
|
+
return this.tokenService.validateAppToken(token);
|
|
593
|
+
}
|
|
594
|
+
async deleteAppToken(id) {
|
|
595
|
+
return this.tokenService.deleteAppToken(id);
|
|
596
|
+
}
|
|
597
|
+
// Authentication utilities
|
|
598
|
+
async verifyPassword(plainPassword, hashedPassword) {
|
|
599
|
+
return this.authService.verifyPassword(plainPassword, hashedPassword);
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Hash a password using the configured crypto adapter
|
|
603
|
+
* Exposed publicly to ensure consistent hashing across all password operations
|
|
604
|
+
*/
|
|
605
|
+
async hashPassword(password) {
|
|
606
|
+
return this.authService.hashPassword(password);
|
|
607
|
+
}
|
|
608
|
+
getDefaultPermissions(role) {
|
|
609
|
+
return this.userService.getDefaultPermissions(role);
|
|
610
|
+
}
|
|
611
|
+
checkWeakPassword(password) {
|
|
612
|
+
return this.authService.checkWeakPassword(password);
|
|
613
|
+
}
|
|
614
|
+
// JWT Token Management
|
|
615
|
+
async generateAuthToken(user, expiresIn = '24h', rememberMe) {
|
|
616
|
+
return this.authService.generateAuthToken(user, expiresIn, rememberMe);
|
|
617
|
+
}
|
|
618
|
+
async verifyAuthToken(token) {
|
|
619
|
+
return this.authService.verifyAuthToken(token);
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Unified token validation that handles both JWT and API tokens
|
|
623
|
+
* Returns a consistent UserSession interface for both token types
|
|
624
|
+
*/
|
|
625
|
+
async verifyAnyToken(token) {
|
|
626
|
+
return this.authService.verifyAnyToken(token);
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Authentication result types for MFA support
|
|
630
|
+
*/
|
|
631
|
+
async authenticateUser(username, password, options = {}) {
|
|
632
|
+
return this.authService.authenticateUser(username, password, options);
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Issue full authentication tokens after successful login (including MFA if required)
|
|
636
|
+
*/
|
|
637
|
+
async issueFullTokens(user, options = {}) {
|
|
638
|
+
return this.authService.issueFullTokens(user, options);
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Generate MFA pending token (used when MFA verification is needed)
|
|
642
|
+
*/
|
|
643
|
+
async generateMFAPendingToken(user, methods) {
|
|
644
|
+
return this.authService.generateMFAPendingToken(user, methods);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Generate MFA setup token (used when org requires MFA but user hasn't set it up)
|
|
648
|
+
*/
|
|
649
|
+
async generateMFASetupToken(user, allowedMethods) {
|
|
650
|
+
return this.authService.generateMFASetupToken(user, allowedMethods);
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Complete MFA verification and issue full tokens
|
|
654
|
+
* Call this after verifyMFACode returns true
|
|
655
|
+
*/
|
|
656
|
+
async completeMFAAuthentication(mfaToken, options = {}) {
|
|
657
|
+
return this.authService.completeMFAAuthentication(mfaToken, options);
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Verify MFA setup token and return user info
|
|
661
|
+
*/
|
|
662
|
+
async verifyMFASetupToken(setupToken) {
|
|
663
|
+
return this.authService.verifyMFASetupToken(setupToken);
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Verify any MFA token (pending or setup) and return payload
|
|
667
|
+
*/
|
|
668
|
+
async verifyMFAToken(token) {
|
|
669
|
+
return this.authService.verifyMFAToken(token);
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Complete MFA setup and issue full authentication tokens
|
|
673
|
+
* Used when a user sets up MFA during the login flow (when org requires MFA)
|
|
674
|
+
*/
|
|
675
|
+
async completeMFASetupAndLogin(setupToken, options = {}) {
|
|
676
|
+
return this.authService.completeMFASetupAndLogin(setupToken, options);
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Verify a backup code for a user
|
|
680
|
+
* Returns result with remaining codes if valid
|
|
681
|
+
*/
|
|
682
|
+
async verifyBackupCode(userId, code) {
|
|
683
|
+
return this.authService.verifyBackupCode(userId, code);
|
|
684
|
+
}
|
|
685
|
+
async refreshAuthToken(refreshToken) {
|
|
686
|
+
return this.authService.refreshAuthToken(refreshToken);
|
|
687
|
+
}
|
|
688
|
+
// ==========================================================================
|
|
689
|
+
// OAuth Methods
|
|
690
|
+
// ==========================================================================
|
|
691
|
+
/**
|
|
692
|
+
* Link an OAuth provider to an existing user
|
|
693
|
+
*/
|
|
694
|
+
async linkOAuthProvider(userId, provider) {
|
|
695
|
+
return this.oauthService.linkOAuthProvider(userId, provider);
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Unlink an OAuth provider from a user
|
|
699
|
+
*/
|
|
700
|
+
async unlinkOAuthProvider(userId, providerName) {
|
|
701
|
+
return this.oauthService.unlinkOAuthProvider(userId, providerName);
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Authenticate a user via OAuth provider
|
|
705
|
+
* Returns null if no user is linked to this provider
|
|
706
|
+
* Returns AuthenticationResult which may require MFA verification or setup
|
|
707
|
+
*/
|
|
708
|
+
async authenticateWithOAuth(providerName, providerId, options) {
|
|
709
|
+
return this.oauthService.authenticateWithOAuth(providerName, providerId, options);
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Find a user by OAuth provider
|
|
713
|
+
*/
|
|
714
|
+
async getUserByOAuthProvider(providerName, providerId) {
|
|
715
|
+
return this.oauthService.getUserByOAuthProvider(providerName, providerId);
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Check if OAuth is configured for a provider
|
|
719
|
+
*/
|
|
720
|
+
isOAuthConfigured(providerName) {
|
|
721
|
+
return this.oauthService.isOAuthConfigured(providerName);
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Get OAuth configuration for a provider
|
|
725
|
+
*/
|
|
726
|
+
getOAuthConfig(providerName) {
|
|
727
|
+
return this.oauthService.getOAuthConfig(providerName);
|
|
728
|
+
}
|
|
729
|
+
// ==========================================================================
|
|
730
|
+
// Passkey/WebAuthn Methods
|
|
731
|
+
// ==========================================================================
|
|
732
|
+
/**
|
|
733
|
+
* Check if passkey authentication is configured
|
|
734
|
+
*/
|
|
735
|
+
isPasskeyConfigured() {
|
|
736
|
+
return this.passkeyService.isPasskeyConfigured();
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Get passkey configuration
|
|
740
|
+
*/
|
|
741
|
+
getPasskeyConfig() {
|
|
742
|
+
return this.passkeyService.getPasskeyConfig();
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Find a user by passkey credential ID
|
|
746
|
+
*/
|
|
747
|
+
async getUserByPasskeyCredentialId(credentialId) {
|
|
748
|
+
return this.passkeyService.getUserByPasskeyCredentialId(credentialId);
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Add a passkey credential to a user
|
|
752
|
+
*/
|
|
753
|
+
async addPasskeyToUser(userId, credential) {
|
|
754
|
+
return this.passkeyService.addPasskeyToUser(userId, credential);
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Remove a passkey credential from a user
|
|
758
|
+
*/
|
|
759
|
+
async removePasskeyFromUser(userId, credentialId) {
|
|
760
|
+
return this.passkeyService.removePasskeyFromUser(userId, credentialId);
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Update a passkey credential (counter, lastUsedAt, friendlyName)
|
|
764
|
+
*/
|
|
765
|
+
async updateUserPasskey(userId, credentialId, updates) {
|
|
766
|
+
return this.passkeyService.updateUserPasskey(userId, credentialId, updates);
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Authenticate with passkey (after WebAuthn verification)
|
|
770
|
+
* Similar to authenticateWithOAuth but for passkeys
|
|
771
|
+
*/
|
|
772
|
+
async authenticateWithPasskey(userId, credentialId, options) {
|
|
773
|
+
return this.passkeyService.authenticateWithPasskey(userId, credentialId, options);
|
|
774
|
+
}
|
|
775
|
+
// ==========================================================================
|
|
776
|
+
// CAPTCHA Methods
|
|
777
|
+
// ==========================================================================
|
|
778
|
+
/**
|
|
779
|
+
* Get or create the CAPTCHA provider instance
|
|
780
|
+
* @private
|
|
781
|
+
*/
|
|
782
|
+
getCaptchaProvider() {
|
|
783
|
+
return this.captchaService.getCaptchaProvider();
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Check if CAPTCHA is configured
|
|
787
|
+
*/
|
|
788
|
+
isCaptchaConfigured() {
|
|
789
|
+
return this.captchaService.isCaptchaConfigured();
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Check if CAPTCHA is required for a specific endpoint
|
|
793
|
+
* @param endpoint - The endpoint to check ('login', 'passwordResetRequest', 'passwordResetVerify')
|
|
794
|
+
*/
|
|
795
|
+
isCaptchaRequiredFor(endpoint) {
|
|
796
|
+
return this.captchaService.isCaptchaRequiredFor(endpoint);
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Get CAPTCHA configuration for frontend use
|
|
800
|
+
* Returns public config (site key, provider, options) - never the secret key
|
|
801
|
+
*/
|
|
802
|
+
getCaptchaConfig() {
|
|
803
|
+
return this.captchaService.getCaptchaConfig();
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Verify a CAPTCHA token
|
|
807
|
+
* @param token - The CAPTCHA token from the frontend widget
|
|
808
|
+
* @param remoteIp - Optional client IP address for verification
|
|
809
|
+
*/
|
|
810
|
+
async verifyCaptcha(token, remoteIp) {
|
|
811
|
+
return this.captchaService.verifyCaptcha(token, remoteIp);
|
|
812
|
+
}
|
|
813
|
+
// ==========================================================================
|
|
814
|
+
// MFA (Multi-Factor Authentication) Methods
|
|
815
|
+
// ==========================================================================
|
|
816
|
+
/**
|
|
817
|
+
* Get the TOTP service instance
|
|
818
|
+
* Creates one with a default issuer (can be overridden via settings)
|
|
819
|
+
*/
|
|
820
|
+
getTOTPService(issuer) {
|
|
821
|
+
return this.mfaService.getTOTPService(issuer);
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Get the Email OTP service instance
|
|
825
|
+
*/
|
|
826
|
+
getEmailOTPService() {
|
|
827
|
+
return this.mfaService.getEmailOTPService();
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Check if MFA is required for a user
|
|
831
|
+
* Returns whether MFA is required and available methods
|
|
832
|
+
*/
|
|
833
|
+
async checkMFARequired(userId) {
|
|
834
|
+
return this.mfaService.checkMFARequired(userId);
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Get project settings
|
|
838
|
+
*/
|
|
839
|
+
async getSettings() {
|
|
840
|
+
if (!this.dataStorage.getSettings) {
|
|
841
|
+
return null;
|
|
842
|
+
}
|
|
843
|
+
return this.dataStorage.getSettings();
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Initialize TOTP setup for a user
|
|
847
|
+
* Returns QR code and secret for authenticator app
|
|
848
|
+
*/
|
|
849
|
+
async initializeTOTPSetup(userId) {
|
|
850
|
+
return this.mfaService.initializeTOTPSetup(userId);
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Verify and enable TOTP for a user
|
|
854
|
+
* Must be called after initializeTOTPSetup with a valid code from authenticator
|
|
855
|
+
*/
|
|
856
|
+
async verifyAndEnableTOTP(userId, code) {
|
|
857
|
+
return this.mfaService.verifyAndEnableTOTP(userId, code);
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Initialize Email OTP setup for a user
|
|
861
|
+
* Sends verification code to user's email
|
|
862
|
+
*/
|
|
863
|
+
async initializeEmailOTPSetup(userId) {
|
|
864
|
+
return this.mfaService.initializeEmailOTPSetup(userId);
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Verify and enable Email OTP for a user
|
|
868
|
+
*/
|
|
869
|
+
async verifyAndEnableEmailOTP(userId, code) {
|
|
870
|
+
return this.mfaService.verifyAndEnableEmailOTP(userId, code);
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Verify MFA code during login
|
|
874
|
+
* Supports TOTP, email, and backup codes
|
|
875
|
+
*/
|
|
876
|
+
async verifyMFACode(userId, code, method) {
|
|
877
|
+
return this.mfaService.verifyMFACode(userId, code, method);
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Send Email OTP for MFA verification during login
|
|
881
|
+
*/
|
|
882
|
+
async sendMFAEmailOTP(userId) {
|
|
883
|
+
return this.mfaService.sendMFAEmailOTP(userId);
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Disable MFA method for a user
|
|
887
|
+
* Requires password verification
|
|
888
|
+
*/
|
|
889
|
+
async disableMFAMethod(userId, method, password) {
|
|
890
|
+
return this.mfaService.disableMFAMethod(userId, method, password);
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Disable all MFA for a user (removes all methods and backup codes)
|
|
894
|
+
* Requires password verification
|
|
895
|
+
*/
|
|
896
|
+
async disableAllMFA(userId, password) {
|
|
897
|
+
return this.mfaService.disableAllMFA(userId, password);
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* Regenerate backup codes for a user
|
|
901
|
+
* Requires password verification
|
|
902
|
+
*/
|
|
903
|
+
async regenerateBackupCodes(userId, password) {
|
|
904
|
+
return this.mfaService.regenerateBackupCodes(userId, password);
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Trust a device to skip MFA
|
|
908
|
+
*/
|
|
909
|
+
async trustDevice(userId, deviceId, deviceName, options) {
|
|
910
|
+
return this.trustedDeviceService.trustDevice(userId, deviceId, deviceName, options);
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Check if a device is trusted for MFA bypass
|
|
914
|
+
*/
|
|
915
|
+
async isDeviceTrusted(userId, deviceId) {
|
|
916
|
+
return this.trustedDeviceService.isDeviceTrusted(userId, deviceId);
|
|
917
|
+
}
|
|
918
|
+
/**
|
|
919
|
+
* Revoke trust for a specific device
|
|
920
|
+
*/
|
|
921
|
+
async revokeTrustedDevice(userId, deviceId) {
|
|
922
|
+
return this.trustedDeviceService.revokeTrustedDevice(userId, deviceId);
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Revoke trust for all devices
|
|
926
|
+
*/
|
|
927
|
+
async revokeAllTrustedDevices(userId) {
|
|
928
|
+
return this.trustedDeviceService.revokeAllTrustedDevices(userId);
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Get list of trusted devices for a user
|
|
932
|
+
*/
|
|
933
|
+
async getTrustedDevices(userId) {
|
|
934
|
+
return this.trustedDeviceService.getTrustedDevices(userId);
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Admin: Reset MFA for a user (emergency recovery)
|
|
938
|
+
* Removes all MFA configuration
|
|
939
|
+
*/
|
|
940
|
+
async adminResetUserMFA(adminUserId, targetUserId) {
|
|
941
|
+
return this.mfaService.adminResetUserMFA(adminUserId, targetUserId);
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* Get MFA status for a user
|
|
945
|
+
*/
|
|
946
|
+
async getMFAStatus(userId) {
|
|
947
|
+
return this.mfaService.getMFAStatus(userId);
|
|
948
|
+
}
|
|
949
|
+
generateSecureSecret() {
|
|
950
|
+
return generateSecureSecret();
|
|
951
|
+
}
|
|
952
|
+
logAuditEvent(event) {
|
|
953
|
+
// Always call custom audit logger if provided
|
|
954
|
+
if (this.auditLogger) {
|
|
955
|
+
this.auditLogger(event);
|
|
956
|
+
}
|
|
957
|
+
// Log through our structured logger system
|
|
958
|
+
const logData = {
|
|
959
|
+
type: event.type,
|
|
960
|
+
action: event.action,
|
|
961
|
+
user: event.username,
|
|
962
|
+
target: event.targetUserId,
|
|
963
|
+
timestamp: event.timestamp,
|
|
964
|
+
...event.details
|
|
965
|
+
};
|
|
966
|
+
if (event.success) {
|
|
967
|
+
this.auditLog.info(`${event.type}: ${event.action}`, logData);
|
|
968
|
+
}
|
|
969
|
+
else {
|
|
970
|
+
this.auditLog.warn(`${event.type}: ${event.action} - FAILED`, logData);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
// Development utility: Setup admin user from environment variables
|
|
974
|
+
async setupAdminFromEnv() {
|
|
975
|
+
return this.userService.setupAdminFromEnv();
|
|
976
|
+
}
|
|
977
|
+
// ============================================
|
|
978
|
+
// OAuth2 Authorization Server Methods
|
|
979
|
+
// ============================================
|
|
980
|
+
/**
|
|
981
|
+
* Get the OAuth2 Authorization Server instance
|
|
982
|
+
* Returns null if OAuth2 is not enabled
|
|
983
|
+
*/
|
|
984
|
+
getOAuth2Server() {
|
|
985
|
+
return this.oauth2ServerService.getOAuth2Server();
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* Generate OAuth2 tokens for a user
|
|
989
|
+
* Used by the OAuth2 routes to create access and refresh tokens
|
|
990
|
+
*/
|
|
991
|
+
async generateOAuth2Tokens(user, scopes, clientId) {
|
|
992
|
+
return this.oauth2ServerService.generateOAuth2Tokens(user, scopes, clientId);
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* Refresh an OAuth2 access token using a refresh token
|
|
996
|
+
* Returns new tokens if the refresh token is valid
|
|
997
|
+
*/
|
|
998
|
+
async refreshOAuth2Token(refreshToken, clientId, requestedScope) {
|
|
999
|
+
return this.oauth2ServerService.refreshOAuth2Token(refreshToken, clientId, requestedScope);
|
|
1000
|
+
}
|
|
1001
|
+
// ============================================
|
|
1002
|
+
// OAuth2 Consent Management
|
|
1003
|
+
// ============================================
|
|
1004
|
+
/**
|
|
1005
|
+
* Check if a user has an existing consent for a client with the given scopes
|
|
1006
|
+
* Returns the consent if all requested scopes are already consented, null otherwise
|
|
1007
|
+
*/
|
|
1008
|
+
async getUserConsent(userId, clientId, requestedScopes) {
|
|
1009
|
+
return this.oauth2ServerService.getUserConsent(userId, clientId, requestedScopes);
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Save user consent for a client
|
|
1013
|
+
* Stores in user preferences for persistence
|
|
1014
|
+
*/
|
|
1015
|
+
async saveUserConsent(userId, clientId, scopes, expiresInDays) {
|
|
1016
|
+
return this.oauth2ServerService.saveUserConsent(userId, clientId, scopes, expiresInDays);
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Revoke user consent for a client
|
|
1020
|
+
*/
|
|
1021
|
+
async revokeUserConsent(userId, clientId) {
|
|
1022
|
+
return this.oauth2ServerService.revokeUserConsent(userId, clientId);
|
|
1023
|
+
}
|
|
1024
|
+
// Rate limiter cleanup (call periodically)
|
|
1025
|
+
cleanup() {
|
|
1026
|
+
if (this.rateLimiter) {
|
|
1027
|
+
this.rateLimiter.cleanup();
|
|
1028
|
+
}
|
|
1029
|
+
// Stop OAuth2 server cleanup interval
|
|
1030
|
+
if (this.oauth2Server) {
|
|
1031
|
+
this.oauth2Server.stopCleanup();
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Full teardown: everything `cleanup()` does, plus releasing whatever the storage adapters
|
|
1036
|
+
* and the event storage are holding open.
|
|
1037
|
+
*
|
|
1038
|
+
* This is a separate method rather than an async `cleanup()` because `cleanup()` is called
|
|
1039
|
+
* synchronously and unawaited by existing hosts (see the express integration's boot-time
|
|
1040
|
+
* consistency check); turning it async would silently give those callers a floating promise
|
|
1041
|
+
* and change nothing for them. So `cleanup()` keeps its exact current behaviour and this
|
|
1042
|
+
* builds on top.
|
|
1043
|
+
*
|
|
1044
|
+
* Every close is awaited independently: an adapter that fails to close must not strand the
|
|
1045
|
+
* handles held by the others, which is the whole reason the process could not exit.
|
|
1046
|
+
*/
|
|
1047
|
+
async shutdown() {
|
|
1048
|
+
this.cleanup();
|
|
1049
|
+
const closers = [];
|
|
1050
|
+
const seen = new Set();
|
|
1051
|
+
// The legacy unified adapter is wrapped into both `dataStorage` and `mediaStorage`, and a
|
|
1052
|
+
// split deployment may still point both at one instance, so dedupe by identity: closing
|
|
1053
|
+
// the same pool twice is at best noise and at worst an error.
|
|
1054
|
+
const addCloser = (name, target) => {
|
|
1055
|
+
if (!target || seen.has(target) || typeof target.close !== 'function')
|
|
1056
|
+
return;
|
|
1057
|
+
seen.add(target);
|
|
1058
|
+
closers.push({ name, close: () => target.close() });
|
|
1059
|
+
};
|
|
1060
|
+
// With a legacy unified adapter the two wrappers delegate to it, so close the real one.
|
|
1061
|
+
addCloser('storage', this.storage);
|
|
1062
|
+
addCloser('dataStorage', this.dataStorage);
|
|
1063
|
+
addCloser('mediaStorage', this.mediaStorage);
|
|
1064
|
+
addCloser('eventBus', this.eventBus);
|
|
1065
|
+
const results = await Promise.allSettled(closers.map(c => c.close()));
|
|
1066
|
+
results.forEach((result, index) => {
|
|
1067
|
+
if (result.status === 'rejected') {
|
|
1068
|
+
this.logger.error(`Failed to close ${closers[index].name} during shutdown`, result.reason);
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
this.logger.info('TrokkyCore shutdown complete');
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
//# sourceMappingURL=engine.js.map
|