@hed-hog/core 0.0.399 → 0.0.401
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/ai/ai-agent.sort.d.ts +6 -0
- package/dist/ai/ai-agent.sort.d.ts.map +1 -0
- package/dist/ai/ai-agent.sort.js +21 -0
- package/dist/ai/ai-agent.sort.js.map +1 -0
- package/dist/ai/ai.controller.d.ts +6 -4
- package/dist/ai/ai.controller.d.ts.map +1 -1
- package/dist/ai/ai.service.d.ts +121 -6
- package/dist/ai/ai.service.d.ts.map +1 -1
- package/dist/ai/ai.service.js +355 -160
- package/dist/ai/ai.service.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.js +26 -23
- package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.sort.d.ts +16 -0
- package/dist/ai-instruction/ai-instruction.sort.d.ts.map +1 -0
- package/dist/ai-instruction/ai-instruction.sort.js +32 -0
- package/dist/ai-instruction/ai-instruction.sort.js.map +1 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.d.ts +12 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-prompt-resolver.service.js +26 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.js.map +1 -1
- package/dist/auth/auth.controller.d.ts +24 -8
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +8 -1
- package/dist/auth/auth.module.js.map +1 -1
- package/dist/auth/auth.service.d.ts +72 -25
- package/dist/auth/auth.service.d.ts.map +1 -1
- package/dist/auth/auth.service.js +41 -4
- package/dist/auth/auth.service.js.map +1 -1
- package/dist/auth/guards/auth.guard.d.ts +3 -1
- package/dist/auth/guards/auth.guard.d.ts.map +1 -1
- package/dist/auth/guards/auth.guard.js +12 -3
- package/dist/auth/guards/auth.guard.js.map +1 -1
- package/dist/authorize/authorize.controller.d.ts +29 -5
- package/dist/authorize/authorize.controller.d.ts.map +1 -1
- package/dist/authorize/authorize.controller.js +120 -13
- package/dist/authorize/authorize.controller.js.map +1 -1
- package/dist/authorize/authorize.errors.d.ts +34 -0
- package/dist/authorize/authorize.errors.d.ts.map +1 -0
- package/dist/authorize/authorize.errors.js +37 -0
- package/dist/authorize/authorize.errors.js.map +1 -0
- package/dist/authorize/authorize.module.d.ts.map +1 -1
- package/dist/authorize/authorize.module.js +6 -1
- package/dist/authorize/authorize.module.js.map +1 -1
- package/dist/authorize/authorize.service.d.ts +77 -3
- package/dist/authorize/authorize.service.d.ts.map +1 -1
- package/dist/authorize/authorize.service.js +212 -21
- package/dist/authorize/authorize.service.js.map +1 -1
- package/dist/authorize/dto/authorize-info.dto.d.ts +10 -1
- package/dist/authorize/dto/authorize-info.dto.d.ts.map +1 -1
- package/dist/authorize/dto/authorize-info.dto.js +16 -1
- package/dist/authorize/dto/authorize-info.dto.js.map +1 -1
- package/dist/authorize/dto/consent.dto.d.ts +10 -1
- package/dist/authorize/dto/consent.dto.d.ts.map +1 -1
- package/dist/authorize/dto/consent.dto.js +16 -1
- package/dist/authorize/dto/consent.dto.js.map +1 -1
- package/dist/authorize/dto/token.dto.d.ts +12 -0
- package/dist/authorize/dto/token.dto.d.ts.map +1 -1
- package/dist/authorize/dto/token.dto.js +21 -1
- package/dist/authorize/dto/token.dto.js.map +1 -1
- package/dist/authorize/oauth-exception.filter.d.ts +17 -0
- package/dist/authorize/oauth-exception.filter.d.ts.map +1 -0
- package/dist/authorize/oauth-exception.filter.js +54 -0
- package/dist/authorize/oauth-exception.filter.js.map +1 -0
- package/dist/authorize/oauth-metadata.service.d.ts +39 -0
- package/dist/authorize/oauth-metadata.service.d.ts.map +1 -0
- package/dist/authorize/oauth-metadata.service.js +81 -0
- package/dist/authorize/oauth-metadata.service.js.map +1 -0
- package/dist/authorize/well-known.controller.d.ts +67 -0
- package/dist/authorize/well-known.controller.d.ts.map +1 -0
- package/dist/authorize/well-known.controller.js +126 -0
- package/dist/authorize/well-known.controller.js.map +1 -0
- package/dist/captcha/captcha.service.d.ts +32 -2
- package/dist/captcha/captcha.service.d.ts.map +1 -1
- package/dist/captcha/captcha.service.js +85 -12
- package/dist/captcha/captcha.service.js.map +1 -1
- package/dist/challenge/challenge.service.d.ts +2 -2
- package/dist/core.module.d.ts.map +1 -1
- package/dist/core.module.js +9 -0
- package/dist/core.module.js.map +1 -1
- package/dist/dashboard/dashboard/dashboard.controller.d.ts +9 -9
- package/dist/dashboard/dashboard/dashboard.service.d.ts +9 -9
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +3 -3
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +3 -3
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +3 -3
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +3 -3
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js +2 -4
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js.map +1 -1
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts +8 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts.map +1 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js +18 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js.map +1 -0
- package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.service.js +2 -4
- package/dist/dashboard/dashboard-item/dashboard-item.service.js.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts +9 -0
- package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts.map +1 -0
- package/dist/dashboard/dashboard-item/dashboard-item.sort.js +19 -0
- package/dist/dashboard/dashboard-item/dashboard-item.sort.js.map +1 -0
- package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +3 -3
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +3 -3
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-role/dashboard-role.service.js +2 -4
- package/dist/dashboard/dashboard-role/dashboard-role.service.js.map +1 -1
- package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts +8 -0
- package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts.map +1 -0
- package/dist/dashboard/dashboard-role/dashboard-role.sort.js +16 -0
- package/dist/dashboard/dashboard-role/dashboard-role.sort.js.map +1 -0
- package/dist/document-kit/document-kit.module.d.ts +3 -0
- package/dist/document-kit/document-kit.module.d.ts.map +1 -0
- package/dist/document-kit/document-kit.module.js +24 -0
- package/dist/document-kit/document-kit.module.js.map +1 -0
- package/dist/document-kit/document-kit.registry.d.ts +55 -0
- package/dist/document-kit/document-kit.registry.d.ts.map +1 -0
- package/dist/document-kit/document-kit.registry.js +91 -0
- package/dist/document-kit/document-kit.registry.js.map +1 -0
- package/dist/document-kit/document-kit.service.d.ts +49 -0
- package/dist/document-kit/document-kit.service.d.ts.map +1 -0
- package/dist/document-kit/document-kit.service.js +135 -0
- package/dist/document-kit/document-kit.service.js.map +1 -0
- package/dist/file/file-upload-ticket.service.d.ts +160 -0
- package/dist/file/file-upload-ticket.service.d.ts.map +1 -0
- package/dist/file/file-upload-ticket.service.js +382 -0
- package/dist/file/file-upload-ticket.service.js.map +1 -0
- package/dist/file/file.controller.d.ts +24 -1
- package/dist/file/file.controller.d.ts.map +1 -1
- package/dist/file/file.controller.js +63 -2
- package/dist/file/file.controller.js.map +1 -1
- package/dist/file/file.module.d.ts.map +1 -1
- package/dist/file/file.module.js +14 -2
- package/dist/file/file.module.js.map +1 -1
- package/dist/file/file.service.d.ts +197 -7
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +438 -78
- package/dist/file/file.service.js.map +1 -1
- package/dist/file/filename-encoding.util.d.ts +24 -0
- package/dist/file/filename-encoding.util.d.ts.map +1 -0
- package/dist/file/filename-encoding.util.js +63 -0
- package/dist/file/filename-encoding.util.js.map +1 -0
- package/dist/file/image-optimization.service.d.ts +27 -0
- package/dist/file/image-optimization.service.d.ts.map +1 -1
- package/dist/file/image-optimization.service.js +63 -14
- package/dist/file/image-optimization.service.js.map +1 -1
- package/dist/file/mcp-file-source.schema.d.ts +33 -0
- package/dist/file/mcp-file-source.schema.d.ts.map +1 -0
- package/dist/file/mcp-file-source.schema.js +78 -0
- package/dist/file/mcp-file-source.schema.js.map +1 -0
- package/dist/file/mcp-file-source.service.d.ts +124 -0
- package/dist/file/mcp-file-source.service.d.ts.map +1 -0
- package/dist/file/mcp-file-source.service.js +262 -0
- package/dist/file/mcp-file-source.service.js.map +1 -0
- package/dist/file/mimetype-sniff.util.d.ts +62 -0
- package/dist/file/mimetype-sniff.util.d.ts.map +1 -0
- package/dist/file/mimetype-sniff.util.js +226 -0
- package/dist/file/mimetype-sniff.util.js.map +1 -0
- package/dist/file/remote-fetch.util.d.ts +35 -0
- package/dist/file/remote-fetch.util.d.ts.map +1 -0
- package/dist/file/remote-fetch.util.js +236 -0
- package/dist/file/remote-fetch.util.js.map +1 -0
- package/dist/impersonation/dto/start-impersonation.dto.d.ts +4 -1
- package/dist/impersonation/dto/start-impersonation.dto.d.ts.map +1 -1
- package/dist/impersonation/dto/start-impersonation.dto.js +1 -1
- package/dist/impersonation/dto/start-impersonation.dto.js.map +1 -1
- package/dist/impersonation/impersonation.service.d.ts +8 -3
- package/dist/impersonation/impersonation.service.d.ts.map +1 -1
- package/dist/impersonation/impersonation.service.js +14 -4
- package/dist/impersonation/impersonation.service.js.map +1 -1
- package/dist/incident/incident.controller.d.ts +2 -1
- package/dist/incident/incident.controller.d.ts.map +1 -1
- package/dist/incident/incident.controller.js +10 -6
- package/dist/incident/incident.controller.js.map +1 -1
- package/dist/incident/incident.service.d.ts +2 -0
- package/dist/incident/incident.service.d.ts.map +1 -1
- package/dist/incident/incident.service.js +4 -0
- package/dist/incident/incident.service.js.map +1 -1
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.js +28 -0
- package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
- package/dist/integration-profile/integration-profile.service.d.ts +0 -13
- package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.service.js +5 -40
- package/dist/integration-profile/integration-profile.service.js.map +1 -1
- package/dist/integration-profile/integration-profile.utils.js +5 -5
- package/dist/integration-profile/integration-profile.utils.js.map +1 -1
- package/dist/integration-profile/testers/ai.testers.d.ts.map +1 -1
- package/dist/integration-profile/testers/ai.testers.js +46 -8
- package/dist/integration-profile/testers/ai.testers.js.map +1 -1
- package/dist/integration-profile/testers/index.d.ts.map +1 -1
- package/dist/integration-profile/testers/index.js +2 -0
- package/dist/integration-profile/testers/index.js.map +1 -1
- package/dist/integration-profile/testers/shipping.testers.d.ts +3 -0
- package/dist/integration-profile/testers/shipping.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/shipping.testers.js +71 -0
- package/dist/integration-profile/testers/shipping.testers.js.map +1 -0
- package/dist/locale/locale.controller.d.ts +1 -1
- package/dist/locale/locale.service.d.ts +1 -1
- package/dist/mail/dto/send.dto.d.ts +6 -1
- package/dist/mail/dto/send.dto.d.ts.map +1 -1
- package/dist/mail/dto/send.dto.js.map +1 -1
- package/dist/mail/mail.service.d.ts +9 -0
- package/dist/mail/mail.service.d.ts.map +1 -1
- package/dist/mail/mail.service.js +34 -14
- package/dist/mail/mail.service.js.map +1 -1
- package/dist/mail-sent/mail-sent.controller.d.ts +1 -1
- package/dist/mail-sent/mail-sent.service.d.ts +1 -1
- package/dist/mail-sent/mail-sent.service.d.ts.map +1 -1
- package/dist/mail-sent/mail-sent.service.js +2 -1
- package/dist/mail-sent/mail-sent.service.js.map +1 -1
- package/dist/mail-sent/mail-sent.sort.d.ts +9 -0
- package/dist/mail-sent/mail-sent.sort.d.ts.map +1 -0
- package/dist/mail-sent/mail-sent.sort.js +19 -0
- package/dist/mail-sent/mail-sent.sort.js.map +1 -0
- package/dist/mcp/filters/mcp-challenge.filter.d.ts +20 -0
- package/dist/mcp/filters/mcp-challenge.filter.d.ts.map +1 -0
- package/dist/mcp/filters/mcp-challenge.filter.js +69 -0
- package/dist/mcp/filters/mcp-challenge.filter.js.map +1 -0
- package/dist/mcp/guards/mcp-auth.guard.d.ts +4 -1
- package/dist/mcp/guards/mcp-auth.guard.d.ts.map +1 -1
- package/dist/mcp/guards/mcp-auth.guard.js +19 -5
- package/dist/mcp/guards/mcp-auth.guard.js.map +1 -1
- package/dist/mcp/guards/mcp-permission.guard.d.ts +25 -3
- package/dist/mcp/guards/mcp-permission.guard.d.ts.map +1 -1
- package/dist/mcp/guards/mcp-permission.guard.js +46 -26
- package/dist/mcp/guards/mcp-permission.guard.js.map +1 -1
- package/dist/mcp/mcp-audit.service.d.ts +17 -0
- package/dist/mcp/mcp-audit.service.d.ts.map +1 -1
- package/dist/mcp/mcp-audit.service.js +32 -3
- package/dist/mcp/mcp-audit.service.js.map +1 -1
- package/dist/mcp/mcp-permission.service.d.ts +64 -0
- package/dist/mcp/mcp-permission.service.d.ts.map +1 -0
- package/dist/mcp/mcp-permission.service.js +178 -0
- package/dist/mcp/mcp-permission.service.js.map +1 -0
- package/dist/mcp/mcp-server.service.d.ts +3 -1
- package/dist/mcp/mcp-server.service.d.ts.map +1 -1
- package/dist/mcp/mcp-server.service.js +36 -15
- package/dist/mcp/mcp-server.service.js.map +1 -1
- package/dist/mcp/mcp.controller.d.ts.map +1 -1
- package/dist/mcp/mcp.controller.js +10 -2
- package/dist/mcp/mcp.controller.js.map +1 -1
- package/dist/mcp/mcp.module.d.ts.map +1 -1
- package/dist/mcp/mcp.module.js +7 -1
- package/dist/mcp/mcp.module.js.map +1 -1
- package/dist/mcp/tools/core-access-log.mcp-tools.d.ts +17 -0
- package/dist/mcp/tools/core-access-log.mcp-tools.d.ts.map +1 -0
- package/dist/mcp/tools/core-access-log.mcp-tools.js +74 -0
- package/dist/mcp/tools/core-access-log.mcp-tools.js.map +1 -0
- package/dist/mcp/tools/core-ai.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-ai.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-dashboard-items.mcp-tools.js +1 -1
- package/dist/mcp/tools/core-dashboard-items.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-dashboard.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-dashboard.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-event-webhooks.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-event-webhooks.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-event-webhooks.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-files.mcp-tools.d.ts +17 -5
- package/dist/mcp/tools/core-files.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-files.mcp-tools.js +186 -24
- package/dist/mcp/tools/core-files.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-integration-events.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-integration-events.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-mail-sent.mcp-tools.js +2 -14
- package/dist/mcp/tools/core-mail-sent.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-mail.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-mail.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-menus.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-menus.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-menus.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-notifications.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-notifications.mcp-tools.js +0 -1
- package/dist/mcp/tools/core-notifications.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-roles.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-roles.mcp-tools.js +2 -13
- package/dist/mcp/tools/core-roles.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-routes.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-routes.mcp-tools.js +2 -11
- package/dist/mcp/tools/core-routes.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-screens.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-screens.mcp-tools.js +2 -11
- package/dist/mcp/tools/core-screens.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-sessions.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-sessions.mcp-tools.js +0 -2
- package/dist/mcp/tools/core-sessions.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-settings.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-settings.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-settings.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-users.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-users.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-webhooks.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-webhooks.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-webhooks.mcp-tools.js.map +1 -1
- package/dist/mcp/types/mcp-context.type.d.ts +9 -0
- package/dist/mcp/types/mcp-context.type.d.ts.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.js +8 -0
- package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
- package/dist/meeting/meeting-provider.registry.d.ts +187 -0
- package/dist/meeting/meeting-provider.registry.d.ts.map +1 -1
- package/dist/meeting/meeting-provider.registry.js.map +1 -1
- package/dist/meeting/meeting.constants.d.ts +70 -0
- package/dist/meeting/meeting.constants.d.ts.map +1 -1
- package/dist/meeting/meeting.constants.js +9 -1
- package/dist/meeting/meeting.constants.js.map +1 -1
- package/dist/menu/menu.service.d.ts.map +1 -1
- package/dist/menu/menu.service.js +29 -9
- package/dist/menu/menu.service.js.map +1 -1
- package/dist/message-template/dto/update-message-template.dto.d.ts +18 -0
- package/dist/message-template/dto/update-message-template.dto.d.ts.map +1 -0
- package/dist/message-template/dto/update-message-template.dto.js +38 -0
- package/dist/message-template/dto/update-message-template.dto.js.map +1 -0
- package/dist/message-template/message-template-admin.service.d.ts +70 -0
- package/dist/message-template/message-template-admin.service.d.ts.map +1 -0
- package/dist/message-template/message-template-admin.service.js +226 -0
- package/dist/message-template/message-template-admin.service.js.map +1 -0
- package/dist/message-template/message-template.controller.d.ts +29 -0
- package/dist/message-template/message-template.controller.d.ts.map +1 -0
- package/dist/message-template/message-template.controller.js +101 -0
- package/dist/message-template/message-template.controller.js.map +1 -0
- package/dist/message-template/message-template.module.d.ts +10 -0
- package/dist/message-template/message-template.module.d.ts.map +1 -0
- package/dist/message-template/message-template.module.js +33 -0
- package/dist/message-template/message-template.module.js.map +1 -0
- package/dist/message-template/message-template.registry.d.ts +55 -0
- package/dist/message-template/message-template.registry.d.ts.map +1 -0
- package/dist/message-template/message-template.registry.js +64 -0
- package/dist/message-template/message-template.registry.js.map +1 -0
- package/dist/message-template/message-template.service.d.ts +59 -0
- package/dist/message-template/message-template.service.d.ts.map +1 -0
- package/dist/message-template/message-template.service.js +166 -0
- package/dist/message-template/message-template.service.js.map +1 -0
- package/dist/notification/notification.constants.d.ts +11 -0
- package/dist/notification/notification.constants.d.ts.map +1 -0
- package/dist/notification/notification.constants.js +14 -0
- package/dist/notification/notification.constants.js.map +1 -0
- package/dist/notification/notification.controller.d.ts +20 -20
- package/dist/notification/notification.module.d.ts.map +1 -1
- package/dist/notification/notification.module.js +3 -0
- package/dist/notification/notification.module.js.map +1 -1
- package/dist/notification/notification.service.d.ts +33 -21
- package/dist/notification/notification.service.d.ts.map +1 -1
- package/dist/notification/notification.service.js +36 -2
- package/dist/notification/notification.service.js.map +1 -1
- package/dist/oauth/oauth-token-broker.service.d.ts +50 -1
- package/dist/oauth/oauth-token-broker.service.d.ts.map +1 -1
- package/dist/oauth/oauth-token-broker.service.js +105 -3
- package/dist/oauth/oauth-token-broker.service.js.map +1 -1
- package/dist/oauth/oauth.controller.d.ts +4 -6
- package/dist/oauth/oauth.controller.d.ts.map +1 -1
- package/dist/oauth/oauth.controller.js +0 -1
- package/dist/oauth/oauth.controller.js.map +1 -1
- package/dist/oauth/oauth.errors.d.ts +15 -1
- package/dist/oauth/oauth.errors.d.ts.map +1 -1
- package/dist/oauth/oauth.errors.js +9 -1
- package/dist/oauth/oauth.errors.js.map +1 -1
- package/dist/oauth/oauth.module.d.ts.map +1 -1
- package/dist/oauth/oauth.module.js +6 -1
- package/dist/oauth/oauth.module.js.map +1 -1
- package/dist/oauth/oauth.service.d.ts +25 -5
- package/dist/oauth/oauth.service.d.ts.map +1 -1
- package/dist/oauth/oauth.service.js +63 -27
- package/dist/oauth/oauth.service.js.map +1 -1
- package/dist/oauth/providers/abstract.provider.d.ts +10 -0
- package/dist/oauth/providers/abstract.provider.d.ts.map +1 -1
- package/dist/oauth/providers/abstract.provider.js +39 -12
- package/dist/oauth/providers/abstract.provider.js.map +1 -1
- package/dist/oauth/providers/github.provider.d.ts +1 -1
- package/dist/oauth/providers/github.provider.d.ts.map +1 -1
- package/dist/oauth/providers/github.provider.js +48 -22
- package/dist/oauth/providers/github.provider.js.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.d.ts +6 -0
- package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.js +36 -4
- package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
- package/dist/observability/monitored-cron.d.ts +29 -12
- package/dist/observability/monitored-cron.d.ts.map +1 -1
- package/dist/observability/monitored-cron.js +131 -46
- package/dist/observability/monitored-cron.js.map +1 -1
- package/dist/pairing/pairing.service.d.ts +6 -2
- package/dist/pairing/pairing.service.d.ts.map +1 -1
- package/dist/pdf/document/charts/chart-bar.d.ts +24 -0
- package/dist/pdf/document/charts/chart-bar.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-bar.js +117 -0
- package/dist/pdf/document/charts/chart-bar.js.map +1 -0
- package/dist/pdf/document/charts/chart-donut.d.ts +16 -0
- package/dist/pdf/document/charts/chart-donut.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-donut.js +89 -0
- package/dist/pdf/document/charts/chart-donut.js.map +1 -0
- package/dist/pdf/document/charts/chart-gauge.d.ts +15 -0
- package/dist/pdf/document/charts/chart-gauge.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-gauge.js +60 -0
- package/dist/pdf/document/charts/chart-gauge.js.map +1 -0
- package/dist/pdf/document/charts/chart-line.d.ts +29 -0
- package/dist/pdf/document/charts/chart-line.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-line.js +89 -0
- package/dist/pdf/document/charts/chart-line.js.map +1 -0
- package/dist/pdf/document/charts/chart-primitives.d.ts +64 -0
- package/dist/pdf/document/charts/chart-primitives.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-primitives.js +110 -0
- package/dist/pdf/document/charts/chart-primitives.js.map +1 -0
- package/dist/pdf/document/charts/chart-radar.d.ts +13 -0
- package/dist/pdf/document/charts/chart-radar.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-radar.js +83 -0
- package/dist/pdf/document/charts/chart-radar.js.map +1 -0
- package/dist/pdf/document/charts/chart-scale.d.ts +39 -0
- package/dist/pdf/document/charts/chart-scale.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-scale.js +118 -0
- package/dist/pdf/document/charts/chart-scale.js.map +1 -0
- package/dist/pdf/document/charts/index.d.ts +8 -0
- package/dist/pdf/document/charts/index.d.ts.map +1 -0
- package/dist/pdf/document/charts/index.js +24 -0
- package/dist/pdf/document/charts/index.js.map +1 -0
- package/dist/pdf/document/index.d.ts +8 -0
- package/dist/pdf/document/index.d.ts.map +1 -0
- package/dist/pdf/document/index.js +24 -0
- package/dist/pdf/document/index.js.map +1 -0
- package/dist/pdf/document/pdf-document.chrome.d.ts +20 -0
- package/dist/pdf/document/pdf-document.chrome.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.chrome.js +36 -0
- package/dist/pdf/document/pdf-document.chrome.js.map +1 -0
- package/dist/pdf/document/pdf-document.css.d.ts +20 -0
- package/dist/pdf/document/pdf-document.css.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.css.js +239 -0
- package/dist/pdf/document/pdf-document.css.js.map +1 -0
- package/dist/pdf/document/pdf-document.renderer.d.ts +10 -0
- package/dist/pdf/document/pdf-document.renderer.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.renderer.js +153 -0
- package/dist/pdf/document/pdf-document.renderer.js.map +1 -0
- package/dist/pdf/document/pdf-document.service.d.ts +27 -0
- package/dist/pdf/document/pdf-document.service.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.service.js +81 -0
- package/dist/pdf/document/pdf-document.service.js.map +1 -0
- package/dist/pdf/document/pdf-document.theme.d.ts +41 -0
- package/dist/pdf/document/pdf-document.theme.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.theme.js +105 -0
- package/dist/pdf/document/pdf-document.theme.js.map +1 -0
- package/dist/pdf/document/pdf-document.types.d.ts +108 -0
- package/dist/pdf/document/pdf-document.types.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.types.js +18 -0
- package/dist/pdf/document/pdf-document.types.js.map +1 -0
- package/dist/pdf/pdf.module.d.ts.map +1 -1
- package/dist/pdf/pdf.module.js +3 -2
- package/dist/pdf/pdf.module.js.map +1 -1
- package/dist/pdf/pdf.service.d.ts +69 -1
- package/dist/pdf/pdf.service.d.ts.map +1 -1
- package/dist/pdf/pdf.service.js +164 -63
- package/dist/pdf/pdf.service.js.map +1 -1
- package/dist/pdf/templates/commercial-proposal.template.d.ts +96 -0
- package/dist/pdf/templates/commercial-proposal.template.d.ts.map +1 -0
- package/dist/pdf/templates/commercial-proposal.template.js +276 -0
- package/dist/pdf/templates/commercial-proposal.template.js.map +1 -0
- package/dist/profile/dto/change-password.dto.d.ts.map +1 -1
- package/dist/profile/dto/change-password.dto.js +4 -6
- package/dist/profile/dto/change-password.dto.js.map +1 -1
- package/dist/profile/profile.controller.d.ts +1 -1
- package/dist/profile/profile.service.d.ts +1 -1
- package/dist/profile/profile.service.d.ts.map +1 -1
- package/dist/profile/profile.service.js +9 -3
- package/dist/profile/profile.service.js.map +1 -1
- package/dist/realtime/realtime-tick.coalescer.d.ts +34 -0
- package/dist/realtime/realtime-tick.coalescer.d.ts.map +1 -0
- package/dist/realtime/realtime-tick.coalescer.js +60 -0
- package/dist/realtime/realtime-tick.coalescer.js.map +1 -0
- package/dist/realtime/realtime.service.d.ts +2 -0
- package/dist/realtime/realtime.service.d.ts.map +1 -1
- package/dist/realtime/realtime.service.js +22 -2
- package/dist/realtime/realtime.service.js.map +1 -1
- package/dist/redis/redis-kv.service.d.ts +90 -0
- package/dist/redis/redis-kv.service.d.ts.map +1 -0
- package/dist/redis/redis-kv.service.js +247 -0
- package/dist/redis/redis-kv.service.js.map +1 -0
- package/dist/redis/redis-master.d.ts +29 -0
- package/dist/redis/redis-master.d.ts.map +1 -0
- package/dist/redis/redis-master.js +81 -0
- package/dist/redis/redis-master.js.map +1 -0
- package/dist/redis/redis-pubsub.d.ts +12 -0
- package/dist/redis/redis-pubsub.d.ts.map +1 -1
- package/dist/redis/redis-pubsub.js +25 -2
- package/dist/redis/redis-pubsub.js.map +1 -1
- package/dist/redis/redis.module.d.ts +11 -0
- package/dist/redis/redis.module.d.ts.map +1 -0
- package/dist/redis/redis.module.js +30 -0
- package/dist/redis/redis.module.js.map +1 -0
- package/dist/session/session.controller.d.ts +6 -2
- package/dist/session/session.controller.d.ts.map +1 -1
- package/dist/session/session.service.d.ts +118 -15
- package/dist/session/session.service.d.ts.map +1 -1
- package/dist/session/session.service.js +251 -77
- package/dist/session/session.service.js.map +1 -1
- package/dist/setting/favicon.controller.d.ts +26 -0
- package/dist/setting/favicon.controller.d.ts.map +1 -0
- package/dist/setting/favicon.controller.js +130 -0
- package/dist/setting/favicon.controller.js.map +1 -0
- package/dist/setting/setting.controller.d.ts +5 -0
- package/dist/setting/setting.controller.d.ts.map +1 -1
- package/dist/setting/setting.module.d.ts.map +1 -1
- package/dist/setting/setting.module.js +2 -1
- package/dist/setting/setting.module.js.map +1 -1
- package/dist/setting/setting.service.d.ts +7 -0
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +38 -3
- package/dist/setting/setting.service.js.map +1 -1
- package/dist/task/task.service.d.ts +17 -0
- package/dist/task/task.service.d.ts.map +1 -1
- package/dist/task/task.service.js +48 -13
- package/dist/task/task.service.js.map +1 -1
- package/dist/token/token.service.d.ts +19 -1
- package/dist/token/token.service.d.ts.map +1 -1
- package/dist/token/token.service.js +39 -2
- package/dist/token/token.service.js.map +1 -1
- package/dist/user/user-credential.util.d.ts +10 -0
- package/dist/user/user-credential.util.d.ts.map +1 -1
- package/dist/user/user-credential.util.js +14 -1
- package/dist/user/user-credential.util.js.map +1 -1
- package/dist/user/user.service.d.ts +12 -4
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +2 -11
- package/dist/user/user.service.js.map +1 -1
- package/dist/user/user.sort.d.ts +16 -0
- package/dist/user/user.sort.d.ts.map +1 -0
- package/dist/user/user.sort.js +25 -0
- package/dist/user/user.sort.js.map +1 -0
- package/dist/utils/abbreviate-name.d.ts +13 -0
- package/dist/utils/abbreviate-name.d.ts.map +1 -0
- package/dist/utils/abbreviate-name.js +42 -0
- package/dist/utils/abbreviate-name.js.map +1 -0
- package/dist/utils/date-range-query.dto.d.ts +11 -0
- package/dist/utils/date-range-query.dto.d.ts.map +1 -0
- package/dist/utils/date-range-query.dto.js +63 -0
- package/dist/utils/date-range-query.dto.js.map +1 -0
- package/dist/utils/date-range.d.ts +96 -0
- package/dist/utils/date-range.d.ts.map +1 -0
- package/dist/utils/date-range.js +172 -0
- package/dist/utils/date-range.js.map +1 -0
- package/dist/webhook-integration/webhook-utils.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-utils.js +24 -0
- package/dist/webhook-integration/webhook-utils.js.map +1 -1
- package/dist/whatsapp-sender/whatsapp-recipients.d.ts +49 -0
- package/dist/whatsapp-sender/whatsapp-recipients.d.ts.map +1 -0
- package/dist/whatsapp-sender/whatsapp-recipients.js +66 -0
- package/dist/whatsapp-sender/whatsapp-recipients.js.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +25 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -1
- package/dist/whatsapp-sender/whatsapp-sender.service.js +71 -7
- package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -1
- package/hedhog/data/integration_provider.yaml +9 -0
- package/hedhog/data/integration_type.yaml +12 -0
- package/hedhog/data/locale.yaml +0 -1
- package/hedhog/data/mail.yaml +2 -2
- package/hedhog/data/mail_layout.yaml +6 -3
- package/hedhog/data/menu.yaml +25 -5
- package/hedhog/data/route.yaml +148 -0
- package/hedhog/data/setting_group.yaml +189 -3
- package/hedhog/frontend/app/access-log/page.tsx.ejs +47 -53
- package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +33 -8
- package/hedhog/frontend/app/account/components/mcp-tokens.tsx.ejs +54 -13
- package/hedhog/frontend/app/account/components/mfa-method-card.tsx.ejs +7 -1
- package/hedhog/frontend/app/account/components/recovery-codes-dialog.tsx.ejs +1 -0
- package/hedhog/frontend/app/account/components/tokens.tsx.ejs +47 -17
- package/hedhog/frontend/app/ai_agent/page.tsx.ejs +46 -5
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +101 -30
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +24 -8
- package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +80 -15
- package/hedhog/frontend/app/configurations/[slug]/components/image-optimization-action.tsx.ejs +166 -0
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.test.tsx.ejs +145 -45
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +99 -219
- package/hedhog/frontend/app/configurations/[slug]/page.tsx.ejs +19 -1
- package/hedhog/frontend/app/configurations/layout.tsx.ejs +19 -5
- package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +2 -8
- package/hedhog/frontend/app/dashboard/components/dynamic-widget.tsx.ejs +3 -0
- package/hedhog/frontend/app/dashboard/components/widget-wrapper.tsx.ejs +4 -0
- package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +43 -44
- package/hedhog/frontend/app/dashboard/management/tabs/component-roles-tab.tsx.ejs +41 -3
- package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +42 -2
- package/hedhog/frontend/app/dashboard/management/tabs/dashboard-roles-tab.tsx.ejs +41 -3
- package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +39 -4
- package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +42 -3
- package/hedhog/frontend/app/incidents/page.tsx.ejs +60 -31
- package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +45 -5
- package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +92 -15
- package/hedhog/frontend/app/mail/log/page.tsx.ejs +109 -61
- package/hedhog/frontend/app/mail/template/page.tsx.ejs +125 -23
- package/hedhog/frontend/app/mcp_chat/chat-components.tsx.ejs +13 -15
- package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +116 -110
- package/hedhog/frontend/app/message-templates/_components/message-template-sheet.tsx.ejs +245 -0
- package/hedhog/frontend/app/message-templates/_lib/types.ts.ejs +24 -0
- package/hedhog/frontend/app/message-templates/page.tsx.ejs +182 -0
- package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1 -0
- package/hedhog/frontend/app/pages/page.tsx.ejs +94 -9
- package/hedhog/frontend/app/roles/menus.tsx.ejs +4 -4
- package/hedhog/frontend/app/roles/routes.tsx.ejs +4 -4
- package/hedhog/frontend/app/roles/users.tsx.ejs +4 -4
- package/hedhog/frontend/app/setting-list/page.tsx.ejs +71 -9
- package/hedhog/frontend/app/users/page.tsx.ejs +77 -67
- package/hedhog/frontend/messages/en.json +237 -37
- package/hedhog/frontend/messages/pt.json +237 -37
- package/hedhog/table/cron_lock.yaml +17 -0
- package/hedhog/table/file.yaml +13 -1
- package/hedhog/table/file_upload_chunk.yaml +23 -0
- package/hedhog/table/file_upload_ticket.yaml +67 -0
- package/hedhog/table/mcp_tool_call_log.yaml +30 -22
- package/hedhog/table/message_template.yaml +33 -0
- package/hedhog/table/setting.yaml +8 -0
- package/hedhog/table/user_session.yaml +36 -1
- package/package.json +5 -3
- package/src/ai/ai-agent.sort.ts +21 -0
- package/src/ai/ai-attachment.fragments.spec.ts +56 -3
- package/src/ai/ai.service.responses.spec.ts +429 -0
- package/src/ai/ai.service.spec.ts +173 -1
- package/src/ai/ai.service.ts +473 -220
- package/src/ai-instruction/ai-instruction.service.ts +32 -28
- package/src/ai-instruction/ai-instruction.sort.ts +32 -0
- package/src/ai-instruction/ai-prompt-resolver.service.spec.ts +44 -0
- package/src/ai-instruction/ai-prompt-resolver.service.ts +29 -0
- package/src/auth/auth.module.ts +8 -1
- package/src/auth/auth.service.spec.ts +108 -1
- package/src/auth/auth.service.ts +59 -5
- package/src/auth/guards/auth.guard.ts +9 -1
- package/src/authorize/authorize.controller.ts +126 -11
- package/src/authorize/authorize.errors.ts +55 -0
- package/src/authorize/authorize.module.ts +6 -1
- package/src/authorize/authorize.service.spec.ts +379 -7
- package/src/authorize/authorize.service.ts +309 -23
- package/src/authorize/dto/authorize-info.dto.ts +21 -3
- package/src/authorize/dto/consent.dto.ts +21 -3
- package/src/authorize/dto/token.dto.ts +24 -2
- package/src/authorize/oauth-exception.filter.ts +58 -0
- package/src/authorize/oauth-metadata.service.ts +67 -0
- package/src/authorize/well-known.controller.spec.ts +84 -0
- package/src/authorize/well-known.controller.ts +96 -0
- package/src/captcha/captcha.service.spec.ts +211 -4
- package/src/captcha/captcha.service.ts +127 -10
- package/src/core.module.ts +9 -0
- package/src/dashboard/dashboard-component-role/dashboard-component-role.service.ts +2 -3
- package/src/dashboard/dashboard-component-role/dashboard-component-role.sort.ts +18 -0
- package/src/dashboard/dashboard-item/dashboard-item.service.ts +2 -3
- package/src/dashboard/dashboard-item/dashboard-item.sort.ts +19 -0
- package/src/dashboard/dashboard-role/dashboard-role.service.ts +2 -3
- package/src/dashboard/dashboard-role/dashboard-role.sort.ts +16 -0
- package/src/document-kit/document-kit.module.ts +12 -0
- package/src/document-kit/document-kit.registry.ts +125 -0
- package/src/document-kit/document-kit.service.spec.ts +156 -0
- package/src/document-kit/document-kit.service.ts +173 -0
- package/src/file/file-upload-ticket.service.spec.ts +422 -0
- package/src/file/file-upload-ticket.service.ts +513 -0
- package/src/file/file.controller.ts +65 -0
- package/src/file/file.module.ts +14 -2
- package/src/file/file.service.spec.ts +262 -1
- package/src/file/file.service.ts +505 -87
- package/src/file/filename-encoding.util.spec.ts +54 -0
- package/src/file/filename-encoding.util.ts +67 -0
- package/src/file/image-optimization.service.spec.ts +156 -19
- package/src/file/image-optimization.service.ts +106 -21
- package/src/file/mcp-file-source.schema.ts +86 -0
- package/src/file/mcp-file-source.service.spec.ts +473 -0
- package/src/file/mcp-file-source.service.ts +445 -0
- package/src/file/mimetype-sniff.util.spec.ts +126 -0
- package/src/file/mimetype-sniff.util.ts +265 -0
- package/src/file/remote-fetch.util.spec.ts +117 -0
- package/src/file/remote-fetch.util.ts +330 -0
- package/src/impersonation/dto/start-impersonation.dto.ts +5 -2
- package/src/impersonation/impersonation.service.spec.ts +24 -1
- package/src/impersonation/impersonation.service.ts +14 -4
- package/src/incident/incident.controller.ts +9 -1
- package/src/incident/incident.service.ts +7 -0
- package/src/index.ts +23 -1
- package/src/integration-profile/integration-profile.secrets.ts +28 -0
- package/src/integration-profile/integration-profile.service.ts +7 -64
- package/src/integration-profile/integration-profile.utils.spec.ts +9 -0
- package/src/integration-profile/integration-profile.utils.ts +5 -5
- package/src/integration-profile/testers/ai.testers.ts +70 -5
- package/src/integration-profile/testers/index.ts +2 -0
- package/src/integration-profile/testers/remaining.testers.spec.ts +144 -1
- package/src/integration-profile/testers/shipping.testers.ts +94 -0
- package/src/integration-profile/testers/tester-coverage.spec.ts +10 -0
- package/src/mail/dto/send.dto.ts +6 -1
- package/src/mail/mail-template.spec.ts +58 -1
- package/src/mail/mail.service.spec.ts +112 -0
- package/src/mail/mail.service.ts +42 -4
- package/src/mail-sent/mail-sent.service.ts +3 -0
- package/src/mail-sent/mail-sent.sort.ts +19 -0
- package/src/mcp/filters/mcp-challenge.filter.spec.ts +76 -0
- package/src/mcp/filters/mcp-challenge.filter.ts +70 -0
- package/src/mcp/guards/mcp-auth.guard.spec.ts +51 -2
- package/src/mcp/guards/mcp-auth.guard.ts +24 -1
- package/src/mcp/guards/mcp-permission.guard.spec.ts +109 -15
- package/src/mcp/guards/mcp-permission.guard.ts +76 -51
- package/src/mcp/mcp-audit.service.spec.ts +107 -0
- package/src/mcp/mcp-audit.service.ts +37 -1
- package/src/mcp/mcp-permission.service.spec.ts +197 -0
- package/src/mcp/mcp-permission.service.ts +184 -0
- package/src/mcp/mcp-server.service.spec.ts +84 -2
- package/src/mcp/mcp-server.service.ts +111 -87
- package/src/mcp/mcp.controller.ts +8 -1
- package/src/mcp/mcp.module.ts +7 -1
- package/src/mcp/tools/core-access-log.mcp-tools.ts +66 -0
- package/src/mcp/tools/core-ai.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-dashboard-items.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-dashboard.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-event-webhooks.mcp-tools.ts +1 -2
- package/src/mcp/tools/core-files.mcp-tools.ts +202 -22
- package/src/mcp/tools/core-integration-events.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-mail-sent.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-mail.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-menus.mcp-tools.ts +1 -2
- package/src/mcp/tools/core-notifications.mcp-tools.ts +0 -1
- package/src/mcp/tools/core-roles.mcp-tools.ts +1 -5
- package/src/mcp/tools/core-routes.mcp-tools.ts +1 -3
- package/src/mcp/tools/core-screens.mcp-tools.ts +1 -3
- package/src/mcp/tools/core-sessions.mcp-tools.ts +0 -2
- package/src/mcp/tools/core-settings.mcp-tools.ts +1 -2
- package/src/mcp/tools/core-users.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-webhooks.mcp-tools.ts +1 -2
- package/src/mcp/types/mcp-context.type.ts +15 -6
- package/src/mcp-chat/mcp-chat.service.ts +8 -0
- package/src/meeting/meeting-provider.registry.ts +201 -0
- package/src/meeting/meeting.constants.ts +74 -0
- package/src/menu/menu.service.spec.ts +89 -0
- package/src/menu/menu.service.ts +29 -11
- package/src/message-template/dto/update-message-template.dto.ts +22 -0
- package/src/message-template/message-template-admin.service.spec.ts +163 -0
- package/src/message-template/message-template-admin.service.ts +239 -0
- package/src/message-template/message-template.controller.ts +52 -0
- package/src/message-template/message-template.module.ts +21 -0
- package/src/message-template/message-template.registry.spec.ts +62 -0
- package/src/message-template/message-template.registry.ts +125 -0
- package/src/message-template/message-template.service.spec.ts +149 -0
- package/src/message-template/message-template.service.ts +149 -0
- package/src/notification/notification.constants.ts +10 -0
- package/src/notification/notification.module.ts +3 -0
- package/src/notification/notification.service.spec.ts +75 -1
- package/src/notification/notification.service.ts +39 -1
- package/src/oauth/oauth-token-broker.service.spec.ts +108 -0
- package/src/oauth/oauth-token-broker.service.ts +129 -2
- package/src/oauth/oauth.controller.ts +0 -1
- package/src/oauth/oauth.errors.ts +7 -0
- package/src/oauth/oauth.module.ts +6 -1
- package/src/oauth/oauth.service.spec.ts +58 -7
- package/src/oauth/oauth.service.ts +71 -32
- package/src/oauth/providers/abstract.provider.spec.ts +192 -0
- package/src/oauth/providers/abstract.provider.ts +46 -14
- package/src/oauth/providers/github.provider.ts +57 -34
- package/src/oauth/providers/microsoft-entra-id.provider.spec.ts +133 -0
- package/src/oauth/providers/microsoft-entra-id.provider.ts +37 -3
- package/src/observability/monitored-cron.spec.ts +164 -31
- package/src/observability/monitored-cron.ts +154 -62
- package/src/pdf/document/charts/chart-bar.ts +217 -0
- package/src/pdf/document/charts/chart-donut.ts +163 -0
- package/src/pdf/document/charts/chart-gauge.ts +94 -0
- package/src/pdf/document/charts/chart-line.ts +159 -0
- package/src/pdf/document/charts/chart-primitives.ts +188 -0
- package/src/pdf/document/charts/chart-radar.ts +136 -0
- package/src/pdf/document/charts/chart-scale.spec.ts +93 -0
- package/src/pdf/document/charts/chart-scale.ts +141 -0
- package/src/pdf/document/charts/charts.spec.ts +157 -0
- package/src/pdf/document/charts/index.ts +7 -0
- package/src/pdf/document/index.ts +7 -0
- package/src/pdf/document/pdf-document.chrome.ts +38 -0
- package/src/pdf/document/pdf-document.css.ts +238 -0
- package/src/pdf/document/pdf-document.renderer.spec.ts +129 -0
- package/src/pdf/document/pdf-document.renderer.ts +215 -0
- package/src/pdf/document/pdf-document.service.ts +77 -0
- package/src/pdf/document/pdf-document.theme.ts +146 -0
- package/src/pdf/document/pdf-document.types.ts +97 -0
- package/src/pdf/pdf.module.ts +3 -2
- package/src/pdf/pdf.service.spec.ts +131 -0
- package/src/pdf/pdf.service.ts +245 -82
- package/src/pdf/templates/commercial-proposal.template.spec.ts +177 -0
- package/src/pdf/templates/commercial-proposal.template.ts +400 -0
- package/src/profile/dto/change-password.dto.ts +25 -7
- package/src/profile/profile.service.spec.ts +97 -0
- package/src/profile/profile.service.ts +9 -3
- package/src/realtime/realtime-tick.coalescer.spec.ts +92 -0
- package/src/realtime/realtime-tick.coalescer.ts +60 -0
- package/src/realtime/realtime.service.spec.ts +33 -0
- package/src/realtime/realtime.service.ts +28 -2
- package/src/redis/redis-kv.service.ts +261 -0
- package/src/redis/redis-master.spec.ts +111 -0
- package/src/redis/redis-master.ts +86 -0
- package/src/redis/redis-pubsub.ts +27 -3
- package/src/redis/redis.module.ts +17 -0
- package/src/session/session.service.spec.ts +121 -42
- package/src/session/session.service.ts +279 -82
- package/src/setting/favicon.controller.spec.ts +92 -0
- package/src/setting/favicon.controller.ts +135 -0
- package/src/setting/setting.module.ts +2 -1
- package/src/setting/setting.service.ts +44 -3
- package/src/task/task.service.spec.ts +41 -0
- package/src/task/task.service.ts +53 -13
- package/src/token/token.service.spec.ts +90 -0
- package/src/token/token.service.ts +48 -2
- package/src/user/user-credential.util.ts +14 -5
- package/src/user/user.service.ts +2 -12
- package/src/user/user.sort.ts +25 -0
- package/src/utils/abbreviate-name.spec.ts +50 -0
- package/src/utils/abbreviate-name.ts +44 -0
- package/src/utils/date-range-query.dto.ts +56 -0
- package/src/utils/date-range.spec.ts +175 -0
- package/src/utils/date-range.ts +246 -0
- package/src/webhook-integration/webhook-utils.spec.ts +67 -0
- package/src/webhook-integration/webhook-utils.ts +26 -0
- package/src/whatsapp-sender/whatsapp-recipients.spec.ts +89 -0
- package/src/whatsapp-sender/whatsapp-recipients.ts +83 -0
- package/src/whatsapp-sender/whatsapp-sender.service.spec.ts +185 -0
- package/src/whatsapp-sender/whatsapp-sender.service.ts +90 -7
- package/hedhog/query/device_pairing_request.sql +0 -46
- package/hedhog/query/impersonation_grant.sql +0 -71
- package/hedhog/query/oauth_authorize_pkce.sql +0 -58
- package/hedhog/query/oauth_mobile_state_token.sql +0 -30
- package/hedhog/query/oauth_web_ref_token.sql +0 -25
|
@@ -18,11 +18,25 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
|
18
18
|
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
19
19
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
20
20
|
};
|
|
21
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
22
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
23
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
24
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
25
|
+
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
26
|
+
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
27
|
+
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
|
|
28
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
29
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
30
|
+
function fulfill(value) { resume("next", value); }
|
|
31
|
+
function reject(value) { resume("throw", value); }
|
|
32
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
33
|
+
};
|
|
21
34
|
var _a;
|
|
22
35
|
var FileService_1;
|
|
23
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
37
|
exports.FileService = void 0;
|
|
25
38
|
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
39
|
+
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
|
26
40
|
const client_lambda_1 = require("@aws-sdk/client-lambda");
|
|
27
41
|
const client_sts_1 = require("@aws-sdk/client-sts");
|
|
28
42
|
const api_locale_1 = require("@hed-hog/api-locale");
|
|
@@ -30,6 +44,7 @@ const api_pagination_1 = require("@hed-hog/api-pagination");
|
|
|
30
44
|
const api_prisma_1 = require("@hed-hog/api-prisma");
|
|
31
45
|
const common_1 = require("@nestjs/common");
|
|
32
46
|
const jwt_1 = require("@nestjs/jwt");
|
|
47
|
+
const crypto_1 = require("crypto");
|
|
33
48
|
const fs_1 = require("fs");
|
|
34
49
|
const os_1 = require("os");
|
|
35
50
|
const path_1 = require("path");
|
|
@@ -37,9 +52,13 @@ const promises_1 = require("stream/promises");
|
|
|
37
52
|
const uuid_1 = require("uuid");
|
|
38
53
|
const integration_profile_utils_1 = require("../integration-profile/integration-profile.utils");
|
|
39
54
|
const setting_service_1 = require("../setting/setting.service");
|
|
55
|
+
const filename_encoding_util_1 = require("./filename-encoding.util");
|
|
56
|
+
const mimetype_sniff_util_1 = require("./mimetype-sniff.util");
|
|
40
57
|
const image_optimization_service_1 = require("./image-optimization.service");
|
|
41
58
|
const abstract_provider_1 = require("./provider/abstract.provider");
|
|
42
59
|
const provider_factory_1 = require("./provider/provider.factory");
|
|
60
|
+
/** Códigos de erro do S3/Spaces que indicam indisponibilidade passageira, não arquivo ruim. */
|
|
61
|
+
const STORAGE_UNAVAILABLE_CODES = ['SlowDown', 'ServiceUnavailable', 'InternalError', 'RequestTimeout'];
|
|
43
62
|
/**
|
|
44
63
|
* Resolver o provider custa 3 queries (setting + integration_profile, que ainda decifra o
|
|
45
64
|
* config, + file_provider) e reconstrói o client de storage a cada arquivo. Em upload em
|
|
@@ -56,18 +75,13 @@ let FileService = FileService_1 = class FileService {
|
|
|
56
75
|
}
|
|
57
76
|
return `${file.location}/${file.path}`;
|
|
58
77
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Nome que chegou com o encoding trocado (busboy entrega `originalname` em
|
|
80
|
+
* latin1, e a base ainda recebe nome importado com o mesmo defeito). A lógica
|
|
81
|
+
* mora no util porque a migration de backfill a reproduz em plpgsql.
|
|
82
|
+
*/
|
|
62
83
|
normalizeUploadedFilename(filename) {
|
|
63
|
-
|
|
64
|
-
return filename;
|
|
65
|
-
}
|
|
66
|
-
if (!this.hasMojibake(filename)) {
|
|
67
|
-
return filename;
|
|
68
|
-
}
|
|
69
|
-
const decoded = Buffer.from(filename, 'latin1').toString('utf8');
|
|
70
|
-
return this.hasMojibake(decoded) ? filename : decoded;
|
|
84
|
+
return filename ? (0, filename_encoding_util_1.fixMojibake)(filename) : filename;
|
|
71
85
|
}
|
|
72
86
|
constructor(prismaService, paginationService, settingService, jwtService, imageOptimizationService) {
|
|
73
87
|
this.prismaService = prismaService;
|
|
@@ -79,6 +93,8 @@ let FileService = FileService_1 = class FileService {
|
|
|
79
93
|
this.mimetypes = {};
|
|
80
94
|
this.cachedProvider = null;
|
|
81
95
|
this.providerResolution = null;
|
|
96
|
+
/** Cache curto de papéis, no mesmo espírito do McpPermissionService. */
|
|
97
|
+
this.fileAdminCache = new Map();
|
|
82
98
|
}
|
|
83
99
|
async onModuleInit() {
|
|
84
100
|
try {
|
|
@@ -212,14 +228,30 @@ let FileService = FileService_1 = class FileService {
|
|
|
212
228
|
});
|
|
213
229
|
return file;
|
|
214
230
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
231
|
+
/**
|
|
232
|
+
* Traduz a falha do provider de storage para a resposta HTTP certa.
|
|
233
|
+
*
|
|
234
|
+
* 5xx e throttle do S3/Spaces são indisponibilidade passageira, não defeito:
|
|
235
|
+
* viram 503 com `code: STORAGE_UNAVAILABLE`, que o HttpExceptionFilter da API
|
|
236
|
+
* responde com `Retry-After` e reporta deduplicado. Sem isso, um 503 do Spaces
|
|
237
|
+
* com corpo que não é XML (ex.: `upstream connect error` do balanceador)
|
|
238
|
+
* estourava no parse do SDK como `char 'u' is not expected` e virava 500.
|
|
239
|
+
*
|
|
240
|
+
* O status vem de `$metadata.httpStatusCode`, que o SDK carimba mesmo quando a
|
|
241
|
+
* desserialização do erro falha; `$response.statusCode` cobre o resto.
|
|
242
|
+
*/
|
|
243
|
+
mapStorageError(error, fileId) {
|
|
244
|
+
var _a, _b, _c;
|
|
245
|
+
const status = (_b = (_a = error === null || error === void 0 ? void 0 : error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) !== null && _b !== void 0 ? _b : (_c = error === null || error === void 0 ? void 0 : error.$response) === null || _c === void 0 ? void 0 : _c.statusCode;
|
|
246
|
+
const codes = [error === null || error === void 0 ? void 0 : error.name, error === null || error === void 0 ? void 0 : error.Code];
|
|
247
|
+
if (codes.includes('NoSuchKey') || status === 404) {
|
|
221
248
|
throw new common_1.NotFoundException(`File not found in storage: ${fileId}`);
|
|
222
249
|
}
|
|
250
|
+
const unavailable = (typeof status === 'number' && status >= 500) ||
|
|
251
|
+
codes.some((c) => STORAGE_UNAVAILABLE_CODES.includes(c));
|
|
252
|
+
if (unavailable) {
|
|
253
|
+
throw new common_1.ServiceUnavailableException({ message: 'Storage temporarily unavailable', code: 'STORAGE_UNAVAILABLE' }, { cause: error });
|
|
254
|
+
}
|
|
223
255
|
throw error;
|
|
224
256
|
}
|
|
225
257
|
async openReadStreamById(fileId) {
|
|
@@ -240,12 +272,16 @@ let FileService = FileService_1 = class FileService {
|
|
|
240
272
|
}
|
|
241
273
|
const provider = await this.getProvider();
|
|
242
274
|
const providerPath = this.resolveProviderPath(file);
|
|
275
|
+
// O HEAD só serve para descobrir o tamanho quando a tabela não o tem. Feito
|
|
276
|
+
// sempre, dobrava as requisições ao storage em cada segmento HLS.
|
|
243
277
|
let metadata;
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
278
|
+
if (file.size == null) {
|
|
279
|
+
try {
|
|
280
|
+
metadata = await provider.metaData(providerPath);
|
|
281
|
+
}
|
|
282
|
+
catch (_b) {
|
|
283
|
+
metadata = undefined;
|
|
284
|
+
}
|
|
249
285
|
}
|
|
250
286
|
try {
|
|
251
287
|
const stream = await provider.readStream(providerPath);
|
|
@@ -256,7 +292,7 @@ let FileService = FileService_1 = class FileService {
|
|
|
256
292
|
};
|
|
257
293
|
}
|
|
258
294
|
catch (error) {
|
|
259
|
-
this.
|
|
295
|
+
this.mapStorageError(error, fileId);
|
|
260
296
|
}
|
|
261
297
|
}
|
|
262
298
|
async openReadStreamWithRange(fileId, start, end) {
|
|
@@ -275,7 +311,13 @@ let FileService = FileService_1 = class FileService {
|
|
|
275
311
|
const resolvedStart = start !== null && start !== void 0 ? start : 0;
|
|
276
312
|
const resolvedEnd = end !== undefined ? end : totalSize > 0 ? totalSize - 1 : undefined;
|
|
277
313
|
const hasRange = start !== undefined;
|
|
278
|
-
|
|
314
|
+
let stream;
|
|
315
|
+
try {
|
|
316
|
+
stream = await provider.readStream(providerPath, hasRange ? { start: resolvedStart, end: resolvedEnd } : undefined);
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
this.mapStorageError(error, fileId);
|
|
320
|
+
}
|
|
279
321
|
const contentLength = resolvedEnd !== undefined ? resolvedEnd - resolvedStart + 1 : totalSize;
|
|
280
322
|
return {
|
|
281
323
|
file,
|
|
@@ -315,7 +357,6 @@ let FileService = FileService_1 = class FileService {
|
|
|
315
357
|
}
|
|
316
358
|
}
|
|
317
359
|
async getBuffer(fileId) {
|
|
318
|
-
var _a;
|
|
319
360
|
if (!fileId) {
|
|
320
361
|
throw new common_1.BadRequestException(`No file ID provided`);
|
|
321
362
|
}
|
|
@@ -337,13 +378,7 @@ let FileService = FileService_1 = class FileService {
|
|
|
337
378
|
providerBuffer = await provider.buffer(providerPath);
|
|
338
379
|
}
|
|
339
380
|
catch (error) {
|
|
340
|
-
|
|
341
|
-
(error === null || error === void 0 ? void 0 : error.Code) === 'NoSuchKey' ||
|
|
342
|
-
((_a = error === null || error === void 0 ? void 0 : error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 404;
|
|
343
|
-
if (missingInStorage) {
|
|
344
|
-
throw new common_1.NotFoundException(`File not found in storage: ${fileId}`);
|
|
345
|
-
}
|
|
346
|
-
throw error;
|
|
381
|
+
this.mapStorageError(error, fileId);
|
|
347
382
|
}
|
|
348
383
|
const buffer = Buffer.from(providerBuffer);
|
|
349
384
|
return {
|
|
@@ -397,7 +432,7 @@ let FileService = FileService_1 = class FileService {
|
|
|
397
432
|
// repassa este argumento, então não há como acioná-lo por HTTP.
|
|
398
433
|
// `isPrivate` tira o arquivo das rotas que servem por id sem autenticação.
|
|
399
434
|
options) {
|
|
400
|
-
var _a;
|
|
435
|
+
var _a, _b;
|
|
401
436
|
if (!fileBuffer) {
|
|
402
437
|
throw new common_1.BadRequestException(`No file provided`);
|
|
403
438
|
}
|
|
@@ -414,7 +449,13 @@ let FileService = FileService_1 = class FileService {
|
|
|
414
449
|
}
|
|
415
450
|
const normalizedFilename = this.normalizeUploadedFilename(fileBuffer.originalname);
|
|
416
451
|
const effectiveMimetype = await this.resolveEffectiveMimetype(fileBuffer.mimetype, normalizedFilename, fileBuffer.buffer);
|
|
417
|
-
const optimized =
|
|
452
|
+
const optimized = (options === null || options === void 0 ? void 0 : options.skipImageOptimization)
|
|
453
|
+
? {
|
|
454
|
+
buffer: fileBuffer.buffer,
|
|
455
|
+
mimetype: effectiveMimetype,
|
|
456
|
+
originalname: normalizedFilename,
|
|
457
|
+
}
|
|
458
|
+
: await this.imageOptimizationService.optimizeBuffer(fileBuffer.buffer, effectiveMimetype, normalizedFilename, { maxWidth: resize === null || resize === void 0 ? void 0 : resize.maxWidth, maxHeight: resize === null || resize === void 0 ? void 0 : resize.maxHeight });
|
|
418
459
|
const normalizedFile = Object.assign(Object.assign({}, fileBuffer), { buffer: optimized.buffer, mimetype: optimized.mimetype, originalname: optimized.originalname, size: optimized.buffer.length });
|
|
419
460
|
const url = await provider.upload(destination, normalizedFile);
|
|
420
461
|
const file = await this.prismaService.file.create({
|
|
@@ -426,12 +467,13 @@ let FileService = FileService_1 = class FileService {
|
|
|
426
467
|
mimetype_id: await this.getMimeType(optimized.mimetype),
|
|
427
468
|
size: optimized.buffer.length,
|
|
428
469
|
is_private: (_a = options === null || options === void 0 ? void 0 : options.isPrivate) !== null && _a !== void 0 ? _a : false,
|
|
470
|
+
created_by_user_id: (_b = options === null || options === void 0 ? void 0 : options.createdByUserId) !== null && _b !== void 0 ? _b : null,
|
|
429
471
|
},
|
|
430
472
|
});
|
|
431
473
|
return file;
|
|
432
474
|
}
|
|
433
475
|
async uploadFromPath(destination, filePath, metadata) {
|
|
434
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
476
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
435
477
|
if (!filePath) {
|
|
436
478
|
throw new common_1.BadRequestException(`No file path provided`);
|
|
437
479
|
}
|
|
@@ -446,7 +488,14 @@ let FileService = FileService_1 = class FileService {
|
|
|
446
488
|
const originalname = this.normalizeUploadedFilename((_c = (_b = metadata === null || metadata === void 0 ? void 0 : metadata.originalname) !== null && _b !== void 0 ? _b : metadata === null || metadata === void 0 ? void 0 : metadata.filename) !== null && _c !== void 0 ? _c : (0, path_1.basename)(filePath));
|
|
447
489
|
// Recupera o tipo real quando o caller não informou o mimetype (default antigo era
|
|
448
490
|
// application/octet-stream, que fazia imagens caírem fora da otimização e do serve).
|
|
449
|
-
|
|
491
|
+
// Diferente de `upload`, aqui só existe um caminho no disco — e ler o arquivo inteiro
|
|
492
|
+
// é justamente o que o branch de streaming abaixo evita para SCORM/vídeo de vários GB.
|
|
493
|
+
// Por isso o sniffing recebe só o cabeçalho, e apenas quando o caller não declarou um
|
|
494
|
+
// tipo concreto: sem isso, uma imagem enviada como application/octet-stream sem
|
|
495
|
+
// extensão no nome escapava da otimização e era gravada byte a byte.
|
|
496
|
+
const declaredMimetype = metadata === null || metadata === void 0 ? void 0 : metadata.mimetype;
|
|
497
|
+
const isGenericMimetype = !declaredMimetype || declaredMimetype === 'application/octet-stream';
|
|
498
|
+
const mimetype = await this.resolveEffectiveMimetype(declaredMimetype, originalname, isGenericMimetype ? await this.readFileHeader(filePath) : undefined);
|
|
450
499
|
if (!(metadata === null || metadata === void 0 ? void 0 : metadata.skipMimeValidation) && !(await this.acceptMimetypes(mimetype))) {
|
|
451
500
|
throw new common_1.BadRequestException(`Invalid file type: ${mimetype}`);
|
|
452
501
|
}
|
|
@@ -458,8 +507,9 @@ let FileService = FileService_1 = class FileService {
|
|
|
458
507
|
// streaming direto do disco via provider.uploadFromPath. Isso evita carregar
|
|
459
508
|
// o arquivo inteiro na RAM (fs.readFile estoura o limite de Buffer / causa OOM)
|
|
460
509
|
// e habilita upload multipart no S3. A otimização de imagem só se aplica a
|
|
461
|
-
// image/*, então não há perda nesse caminho.
|
|
462
|
-
|
|
510
|
+
// image/*, então não há perda nesse caminho. `skipImageOptimization` manda a
|
|
511
|
+
// imagem pelo mesmo caminho: o chamador quer os bytes exatamente como estão.
|
|
512
|
+
if (!mimetype.startsWith('image/') || (metadata === null || metadata === void 0 ? void 0 : metadata.skipImageOptimization)) {
|
|
463
513
|
const url = await provider.uploadFromPath(destination, filePath, {
|
|
464
514
|
filename: originalname,
|
|
465
515
|
mimetype,
|
|
@@ -473,19 +523,20 @@ let FileService = FileService_1 = class FileService {
|
|
|
473
523
|
mimetype_id: await this.getMimeType(mimetype),
|
|
474
524
|
size,
|
|
475
525
|
is_private: (_d = metadata === null || metadata === void 0 ? void 0 : metadata.isPrivate) !== null && _d !== void 0 ? _d : false,
|
|
526
|
+
created_by_user_id: (_e = metadata === null || metadata === void 0 ? void 0 : metadata.createdByUserId) !== null && _e !== void 0 ? _e : null,
|
|
476
527
|
},
|
|
477
528
|
});
|
|
478
529
|
}
|
|
479
530
|
// Read buffer to allow image optimization regardless of provider support
|
|
480
531
|
const rawBuffer = await fs_1.promises.readFile(filePath);
|
|
481
532
|
const optimized = await this.imageOptimizationService.optimizeBuffer(rawBuffer, mimetype, originalname, {
|
|
482
|
-
maxWidth: (
|
|
483
|
-
maxHeight: (
|
|
533
|
+
maxWidth: (_f = metadata === null || metadata === void 0 ? void 0 : metadata.resize) === null || _f === void 0 ? void 0 : _f.maxWidth,
|
|
534
|
+
maxHeight: (_g = metadata === null || metadata === void 0 ? void 0 : metadata.resize) === null || _g === void 0 ? void 0 : _g.maxHeight,
|
|
484
535
|
});
|
|
485
536
|
const url = await provider.upload(destination, {
|
|
486
537
|
fieldname: 'file',
|
|
487
538
|
originalname: optimized.originalname,
|
|
488
|
-
encoding: (
|
|
539
|
+
encoding: (_h = metadata === null || metadata === void 0 ? void 0 : metadata.encoding) !== null && _h !== void 0 ? _h : '7bit',
|
|
489
540
|
mimetype: optimized.mimetype,
|
|
490
541
|
size: optimized.buffer.length,
|
|
491
542
|
destination: '',
|
|
@@ -501,19 +552,68 @@ let FileService = FileService_1 = class FileService {
|
|
|
501
552
|
location: destination,
|
|
502
553
|
mimetype_id: await this.getMimeType(optimized.mimetype),
|
|
503
554
|
size: optimized.buffer.length,
|
|
504
|
-
is_private: (
|
|
555
|
+
is_private: (_j = metadata === null || metadata === void 0 ? void 0 : metadata.isPrivate) !== null && _j !== void 0 ? _j : false,
|
|
556
|
+
created_by_user_id: (_k = metadata === null || metadata === void 0 ? void 0 : metadata.createdByUserId) !== null && _k !== void 0 ? _k : null,
|
|
505
557
|
},
|
|
506
558
|
});
|
|
507
559
|
return file;
|
|
508
560
|
}
|
|
561
|
+
/**
|
|
562
|
+
* Lista as imagens armazenadas que valem uma passada por `reoptimizeFile`, para a
|
|
563
|
+
* operação em massa de reprocessamento do acervo.
|
|
564
|
+
*
|
|
565
|
+
* Devolve junto o total e a soma de bytes do filtro inteiro (não só da página), que é
|
|
566
|
+
* o que permite mostrar uma prévia antes de enfileirar dezenas de milhares de jobs.
|
|
567
|
+
* O core não conhece a fila — quem enfileira é a library `queue`, que depende deste
|
|
568
|
+
* pacote e não o contrário.
|
|
569
|
+
*/
|
|
570
|
+
async findOptimizableImages(params) {
|
|
571
|
+
var _a, _b, _c;
|
|
572
|
+
const minSize = Math.max(0, Math.trunc(Number(params === null || params === void 0 ? void 0 : params.minSize) || 0));
|
|
573
|
+
const locations = ((_a = params === null || params === void 0 ? void 0 : params.locations) !== null && _a !== void 0 ? _a : [])
|
|
574
|
+
.map((location) => String(location).trim())
|
|
575
|
+
.filter(Boolean);
|
|
576
|
+
const where = {
|
|
577
|
+
size: { gte: minSize },
|
|
578
|
+
file_mimetype: {
|
|
579
|
+
name: {
|
|
580
|
+
startsWith: 'image/',
|
|
581
|
+
notIn: FileService_1.NON_OPTIMIZABLE_IMAGE_MIMETYPES,
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
};
|
|
585
|
+
if (locations.length) {
|
|
586
|
+
where.location = { in: locations };
|
|
587
|
+
}
|
|
588
|
+
const [aggregate, rows] = await Promise.all([
|
|
589
|
+
this.prismaService.file.aggregate({
|
|
590
|
+
where,
|
|
591
|
+
_count: { _all: true },
|
|
592
|
+
_sum: { size: true },
|
|
593
|
+
}),
|
|
594
|
+
this.prismaService.file.findMany({
|
|
595
|
+
where,
|
|
596
|
+
select: { id: true },
|
|
597
|
+
// Ordem estável para que o enfileiramento paginado não pule nem repita linhas.
|
|
598
|
+
orderBy: { id: 'asc' },
|
|
599
|
+
skip: Math.max(0, Math.trunc(Number(params === null || params === void 0 ? void 0 : params.offset) || 0)),
|
|
600
|
+
take: Math.min(5000, Math.max(1, Math.trunc(Number(params === null || params === void 0 ? void 0 : params.limit) || 1000))),
|
|
601
|
+
}),
|
|
602
|
+
]);
|
|
603
|
+
return {
|
|
604
|
+
ids: rows.map((row) => row.id),
|
|
605
|
+
total: (_b = aggregate._count._all) !== null && _b !== void 0 ? _b : 0,
|
|
606
|
+
totalBytes: Number((_c = aggregate._sum.size) !== null && _c !== void 0 ? _c : 0),
|
|
607
|
+
};
|
|
608
|
+
}
|
|
509
609
|
/**
|
|
510
610
|
* Re-applies the current image-optimization settings to an already-stored file,
|
|
511
611
|
* rewriting it in place: the `file` record keeps the same id, so every row that
|
|
512
612
|
* references it (course_image, course_lesson_video_frame, ...) stays valid without
|
|
513
|
-
* any FK juggling. Only replaces the stored object when the
|
|
514
|
-
*
|
|
515
|
-
* operation idempotent and avoids repeated
|
|
516
|
-
* left untouched.
|
|
613
|
+
* any FK juggling. Only replaces the stored object when the mimetype changed
|
|
614
|
+
* (e.g. PNG → WebP) or the result is smaller by a margin that justifies the rewrite —
|
|
615
|
+
* that margin is what actually makes the operation idempotent and avoids repeated
|
|
616
|
+
* lossy recompression. Non-image files are left untouched.
|
|
517
617
|
*/
|
|
518
618
|
async reoptimizeFile(fileId) {
|
|
519
619
|
var _a;
|
|
@@ -525,8 +625,13 @@ let FileService = FileService_1 = class FileService {
|
|
|
525
625
|
}
|
|
526
626
|
const optimized = await this.imageOptimizationService.optimizeBuffer(buffer, currentMimetype, file.filename);
|
|
527
627
|
const mimetypeChanged = optimized.mimetype !== currentMimetype;
|
|
528
|
-
|
|
529
|
-
|
|
628
|
+
// Mudança de formato é o ganho principal (PNG → WebP) e vale por si; sem ela, só
|
|
629
|
+
// regrava quando a economia passa do limiar. `optimizeBuffer` já garante que o
|
|
630
|
+
// resultado nunca é maior que a entrada neste caminho (sem crop de alvo exato).
|
|
631
|
+
const worthRewriting = oldSize > 0 &&
|
|
632
|
+
(oldSize - optimized.buffer.length) / oldSize >=
|
|
633
|
+
FileService_1.REOPTIMIZE_MIN_GAIN_RATIO;
|
|
634
|
+
if (!mimetypeChanged && !worthRewriting) {
|
|
530
635
|
return {
|
|
531
636
|
changed: false,
|
|
532
637
|
oldSize,
|
|
@@ -602,14 +707,181 @@ let FileService = FileService_1 = class FileService {
|
|
|
602
707
|
}
|
|
603
708
|
return files.map((file) => file.id);
|
|
604
709
|
}
|
|
605
|
-
|
|
710
|
+
/**
|
|
711
|
+
* `ownerUserId` restringe a listagem aos arquivos enviados por aquele usuário.
|
|
712
|
+
*
|
|
713
|
+
* Existe para as tools MCP: sem ele, `core.files.list` é um índice de tudo o que
|
|
714
|
+
* qualquer empresa já subiu, incluindo o que está gravado como `is_private`. O
|
|
715
|
+
* controller REST continua chamando sem o parâmetro, porque ali a rota já é `admin`
|
|
716
|
+
* e a tela de arquivos é justamente a visão global.
|
|
717
|
+
*/
|
|
718
|
+
/**
|
|
719
|
+
* Grava um stream em disco medindo, hasheando e guardando o cabeçalho de uma vez só.
|
|
720
|
+
*
|
|
721
|
+
* O upload assinado recebe o binário cru no corpo do PUT, e nada garante que venha com
|
|
722
|
+
* `Content-Length` — sem o contador abaixo, um corpo aberto encheria o disco do pod. O
|
|
723
|
+
* corte é feito em pleno voo, antes de o excedente chegar ao arquivo.
|
|
724
|
+
*
|
|
725
|
+
* Passa o cabeçalho adiante porque conferir o tipo real é obrigatório nesse caminho, e
|
|
726
|
+
* reler o arquivo depois seria uma segunda passada por nada.
|
|
727
|
+
*/
|
|
728
|
+
async writeStreamToPath(source, targetPath, maxBytes) {
|
|
729
|
+
const hash = (0, crypto_1.createHash)('sha256');
|
|
730
|
+
const headerChunks = [];
|
|
731
|
+
let headerLength = 0;
|
|
732
|
+
let bytes = 0;
|
|
733
|
+
const target = (0, fs_1.createWriteStream)(targetPath);
|
|
734
|
+
await (0, promises_1.pipeline)(source, function (chunks) {
|
|
735
|
+
return __asyncGenerator(this, arguments, function* () {
|
|
736
|
+
var _a, e_1, _b, _c;
|
|
737
|
+
try {
|
|
738
|
+
for (var _d = true, chunks_1 = __asyncValues(chunks), chunks_1_1; chunks_1_1 = yield __await(chunks_1.next()), _a = chunks_1_1.done, !_a; _d = true) {
|
|
739
|
+
_c = chunks_1_1.value;
|
|
740
|
+
_d = false;
|
|
741
|
+
const chunk = _c;
|
|
742
|
+
const buffer = Buffer.from(chunk);
|
|
743
|
+
bytes += buffer.length;
|
|
744
|
+
if (bytes > maxBytes) {
|
|
745
|
+
throw new common_1.BadRequestException(`Upload exceeds the declared size of ${maxBytes} bytes`);
|
|
746
|
+
}
|
|
747
|
+
hash.update(buffer);
|
|
748
|
+
if (headerLength < mimetype_sniff_util_1.MIMETYPE_SNIFF_BYTES) {
|
|
749
|
+
const slice = buffer.subarray(0, mimetype_sniff_util_1.MIMETYPE_SNIFF_BYTES - headerLength);
|
|
750
|
+
headerChunks.push(slice);
|
|
751
|
+
headerLength += slice.length;
|
|
752
|
+
}
|
|
753
|
+
yield yield __await(buffer);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
757
|
+
finally {
|
|
758
|
+
try {
|
|
759
|
+
if (!_d && !_a && (_b = chunks_1.return)) yield __await(_b.call(chunks_1));
|
|
760
|
+
}
|
|
761
|
+
finally { if (e_1) throw e_1.error; }
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
}, target);
|
|
765
|
+
return {
|
|
766
|
+
bytes,
|
|
767
|
+
sha256: hash.digest('hex'),
|
|
768
|
+
header: Buffer.concat(headerChunks),
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Conteúdo de um arquivo já armazenado, em memória.
|
|
773
|
+
*
|
|
774
|
+
* Existe para as tools que consomem os bytes sem persistir nada (importar extrato,
|
|
775
|
+
* extrair dados de uma nota com IA): elas recebem um `fileId` e precisam do arquivo,
|
|
776
|
+
* não de um stream. O teto evita que um `fileId` apontando para um SCORM de vários GB
|
|
777
|
+
* derrube o pod — quem serve arquivo grande usa `openReadStream` e não passa por aqui.
|
|
778
|
+
*/
|
|
779
|
+
async bufferById(fileId, maxBytes) {
|
|
780
|
+
var _a, e_2, _b, _c;
|
|
781
|
+
var _d, _e;
|
|
782
|
+
const { stream } = await this.openReadStreamById(fileId);
|
|
783
|
+
const chunks = [];
|
|
784
|
+
let total = 0;
|
|
785
|
+
try {
|
|
786
|
+
for (var _f = true, _g = __asyncValues(stream), _h; _h = await _g.next(), _a = _h.done, !_a; _f = true) {
|
|
787
|
+
_c = _h.value;
|
|
788
|
+
_f = false;
|
|
789
|
+
const chunk = _c;
|
|
790
|
+
total += chunk.length;
|
|
791
|
+
if (total > maxBytes) {
|
|
792
|
+
(_e = (_d = stream).destroy) === null || _e === void 0 ? void 0 : _e.call(_d);
|
|
793
|
+
throw new common_1.BadRequestException(`File ${fileId} is larger than the ${maxBytes} bytes this operation can load`);
|
|
794
|
+
}
|
|
795
|
+
chunks.push(Buffer.from(chunk));
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
799
|
+
finally {
|
|
800
|
+
try {
|
|
801
|
+
if (!_f && !_a && (_b = _g.return)) await _b.call(_g);
|
|
802
|
+
}
|
|
803
|
+
finally { if (e_2) throw e_2.error; }
|
|
804
|
+
}
|
|
805
|
+
return Buffer.concat(chunks);
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Nome do mimetype de um arquivo.
|
|
809
|
+
*
|
|
810
|
+
* `get()` e `upload()` devolvem a linha crua, sem a relação, e cada chamador que
|
|
811
|
+
* precisava do tipo vinha refazendo o `include` por conta. Como o cache de
|
|
812
|
+
* `getMimeType` é id-por-nome, este é o inverso dele e sai do mesmo mapa quando já
|
|
813
|
+
* tiver sido consultado.
|
|
814
|
+
*/
|
|
815
|
+
async mimetypeNameById(mimetypeId) {
|
|
816
|
+
const cached = Object.entries(this.mimetypes).find(([, id]) => id === mimetypeId);
|
|
817
|
+
if (cached) {
|
|
818
|
+
return cached[0];
|
|
819
|
+
}
|
|
820
|
+
const row = await this.prismaService.file_mimetype.findUnique({
|
|
821
|
+
where: { id: mimetypeId },
|
|
822
|
+
select: { name: true },
|
|
823
|
+
});
|
|
824
|
+
if (row === null || row === void 0 ? void 0 : row.name) {
|
|
825
|
+
this.mimetypes[row.name] = mimetypeId;
|
|
826
|
+
return row.name;
|
|
827
|
+
}
|
|
828
|
+
return 'application/octet-stream';
|
|
829
|
+
}
|
|
830
|
+
async getFiles(paginationParams, ownerUserId) {
|
|
606
831
|
const fields = ['filename', 'path'];
|
|
607
832
|
const OR = this.prismaService.createInsensitiveSearch(fields, paginationParams);
|
|
608
833
|
return this.paginationService.paginate(this.prismaService.file, paginationParams, {
|
|
834
|
+
where: Object.assign({ OR }, (ownerUserId ? { created_by_user_id: ownerUserId } : {})),
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
async isFileAdmin(userId) {
|
|
838
|
+
const cached = this.fileAdminCache.get(userId);
|
|
839
|
+
if (cached && Date.now() - cached.at < FileService_1.FILE_ADMIN_CACHE_TTL_MS) {
|
|
840
|
+
return cached.value;
|
|
841
|
+
}
|
|
842
|
+
const found = await this.prismaService.role_user.findFirst({
|
|
609
843
|
where: {
|
|
610
|
-
|
|
844
|
+
user_id: userId,
|
|
845
|
+
role: { slug: { in: FileService_1.FILE_ADMIN_ROLES } },
|
|
611
846
|
},
|
|
847
|
+
select: { role_id: true },
|
|
848
|
+
});
|
|
849
|
+
const value = Boolean(found);
|
|
850
|
+
this.fileAdminCache.set(userId, { value, at: Date.now() });
|
|
851
|
+
return value;
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Porteiro do `fileId` vindo de fora: só o dono usa um arquivo, e quem administra o
|
|
855
|
+
* acervo usa qualquer um.
|
|
856
|
+
*
|
|
857
|
+
* Sem isto, apontar um `fileId` numa tool seria enumerar — id de arquivo é sequencial,
|
|
858
|
+
* exatamente o motivo pelo qual `is_private` existe. Arquivo anterior a esta coluna
|
|
859
|
+
* (ou gravado por cron/seed/webhook) fica com dono nulo e só o admin alcança: não dá
|
|
860
|
+
* para provar de quem ele é, e adivinhar a favor do chamador seria abrir a porta que
|
|
861
|
+
* este método fecha.
|
|
862
|
+
*/
|
|
863
|
+
async assertFileUsable(fileId, userId) {
|
|
864
|
+
if (!Number.isInteger(fileId) || fileId <= 0) {
|
|
865
|
+
throw new common_1.BadRequestException(`Invalid file id: ${fileId}`);
|
|
866
|
+
}
|
|
867
|
+
const file = await this.prismaService.file.findUnique({
|
|
868
|
+
where: { id: fileId },
|
|
869
|
+
include: { file_mimetype: true },
|
|
612
870
|
});
|
|
871
|
+
// Mesma resposta para inexistente e para alheio seria o ideal contra enumeração, mas
|
|
872
|
+
// `get()` já responde 404 com o id, e divergir aqui só confundiria quem integra.
|
|
873
|
+
if (!file) {
|
|
874
|
+
throw new common_1.NotFoundException(`File not found: ${fileId}`);
|
|
875
|
+
}
|
|
876
|
+
if (file.created_by_user_id === userId) {
|
|
877
|
+
return file;
|
|
878
|
+
}
|
|
879
|
+
if (await this.isFileAdmin(userId)) {
|
|
880
|
+
return file;
|
|
881
|
+
}
|
|
882
|
+
throw new common_1.ForbiddenException(file.created_by_user_id === null
|
|
883
|
+
? `File ${fileId} has no recorded owner and can only be used by an administrator`
|
|
884
|
+
: `File ${fileId} belongs to another user`);
|
|
613
885
|
}
|
|
614
886
|
async get(fileId) {
|
|
615
887
|
const file = await this.prismaService.file.findUnique({
|
|
@@ -743,19 +1015,44 @@ let FileService = FileService_1 = class FileService {
|
|
|
743
1015
|
}
|
|
744
1016
|
return undefined;
|
|
745
1017
|
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Resolve o `file` cujo `resolveProviderPath` (location + path, ou path já combinado) bate com
|
|
1020
|
+
* o `filepath` embutido no token de download — é o inverso de `resolveProviderPath`.
|
|
1021
|
+
*
|
|
1022
|
+
* Bug corrigido (relatado como "Token de download inválido ou expirado" no storage local):
|
|
1023
|
+
* `tempURLById` assina o token com `resolveProviderPath(file)` (ex.:
|
|
1024
|
+
* "class-assignment-tasks/abc123.pdf", já com o prefixo de `location`), mas o upload local/S3
|
|
1025
|
+
* grava só o basename em `file.path` ("abc123.pdf") e o `location` separado em outra coluna.
|
|
1026
|
+
* Um `findFirst({ where: { path: filepath } })` direto nunca batia para esses arquivos — sempre
|
|
1027
|
+
* caía no `catch` abaixo e mostrava a mensagem genérica de token inválido, mesmo com o token
|
|
1028
|
+
* (e o arquivo) perfeitamente válidos. S3 mascarava isso porque `S3Provider.tempURL` devolve uma
|
|
1029
|
+
* URL assinada direto do bucket, sem passar por este método.
|
|
1030
|
+
*/
|
|
1031
|
+
async findFileByResolvedPath(filepath) {
|
|
1032
|
+
const bySameValue = await this.prismaService.file.findFirst({
|
|
1033
|
+
where: { path: filepath },
|
|
1034
|
+
include: { file_mimetype: true },
|
|
1035
|
+
});
|
|
1036
|
+
if (bySameValue)
|
|
1037
|
+
return bySameValue;
|
|
1038
|
+
const slashIndex = filepath.lastIndexOf('/');
|
|
1039
|
+
if (slashIndex === -1)
|
|
1040
|
+
return null;
|
|
1041
|
+
return this.prismaService.file.findFirst({
|
|
1042
|
+
where: {
|
|
1043
|
+
location: filepath.slice(0, slashIndex),
|
|
1044
|
+
path: filepath.slice(slashIndex + 1),
|
|
1045
|
+
},
|
|
1046
|
+
include: { file_mimetype: true },
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
746
1049
|
async download(locale, token) {
|
|
747
1050
|
var _a;
|
|
748
1051
|
try {
|
|
749
1052
|
const { filepath } = this.jwtService.verify(token, {
|
|
750
1053
|
secret: process.env.JWT_SECRET,
|
|
751
1054
|
});
|
|
752
|
-
|
|
753
|
-
const file = await this.prismaService.file.findFirst({
|
|
754
|
-
where: { path: filepath },
|
|
755
|
-
include: {
|
|
756
|
-
file_mimetype: true,
|
|
757
|
-
},
|
|
758
|
-
});
|
|
1055
|
+
const file = await this.findFileByResolvedPath(filepath);
|
|
759
1056
|
if (!file) {
|
|
760
1057
|
throw new common_1.NotFoundException((0, api_locale_1.getLocaleText)('file.download.not_found', locale, `Not found: ${filepath}`));
|
|
761
1058
|
}
|
|
@@ -879,6 +1176,28 @@ let FileService = FileService_1 = class FileService {
|
|
|
879
1176
|
};
|
|
880
1177
|
return (_a = map[ext]) !== null && _a !== void 0 ? _a : null;
|
|
881
1178
|
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Lê só o começo do arquivo, o bastante para o sharp reconhecer o formato pelo
|
|
1181
|
+
* cabeçalho. Existe para o sniffing de `uploadFromPath`, que não pode chamar
|
|
1182
|
+
* `fs.readFile`: o mesmo caminho recebe pacotes SCORM e vídeos de vários GB, e
|
|
1183
|
+
* carregá-los inteiros estoura o limite de Buffer. Devolve `undefined` em qualquer
|
|
1184
|
+
* falha de leitura — quem chama já trata a ausência do buffer.
|
|
1185
|
+
*/
|
|
1186
|
+
async readFileHeader(filePath, bytes = 64 * 1024) {
|
|
1187
|
+
let handle;
|
|
1188
|
+
try {
|
|
1189
|
+
handle = await fs_1.promises.open(filePath, 'r');
|
|
1190
|
+
const buffer = Buffer.alloc(bytes);
|
|
1191
|
+
const { bytesRead } = await handle.read(buffer, 0, bytes, 0);
|
|
1192
|
+
return bytesRead > 0 ? buffer.subarray(0, bytesRead) : undefined;
|
|
1193
|
+
}
|
|
1194
|
+
catch (_a) {
|
|
1195
|
+
return undefined;
|
|
1196
|
+
}
|
|
1197
|
+
finally {
|
|
1198
|
+
await (handle === null || handle === void 0 ? void 0 : handle.close().catch(() => undefined));
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
882
1201
|
/**
|
|
883
1202
|
* Resolves the MIME type to persist for an upload. When the incoming mimetype is
|
|
884
1203
|
* generic (application/octet-stream or empty), recovers the real image type from
|
|
@@ -886,25 +1205,8 @@ let FileService = FileService_1 = class FileService {
|
|
|
886
1205
|
* Concrete non-image types (video, pdf, ...) are returned unchanged.
|
|
887
1206
|
*/
|
|
888
1207
|
async resolveEffectiveMimetype(mimetype, name, buffer) {
|
|
889
|
-
if (mimetype && mimetype.startsWith('image/'))
|
|
890
|
-
// O mimetype que chega do navegador vem da EXTENSÃO do arquivo, não do
|
|
891
|
-
// conteúdo: um PNG renomeado para `.svg` é anunciado como `image/svg+xml`.
|
|
892
|
-
// Gravar isso faz o endpoint de imagem servir bytes PNG sob Content-Type
|
|
893
|
-
// de SVG e, com o `nosniff` que a API envia, o navegador não corrige
|
|
894
|
-
// sozinho — a imagem simplesmente não renderiza, sem erro nenhum.
|
|
895
|
-
// Com os bytes em mãos, quem decide é a assinatura do arquivo.
|
|
896
|
-
if (buffer) {
|
|
897
|
-
const sniffed = await this.imageOptimizationService.detectImageMimetype(buffer);
|
|
898
|
-
// Só sobrepõe quando o sniffing reconheceu o formato: um `null` significa
|
|
899
|
-
// que o sharp não entendeu o buffer, e aí o declarado ainda é o melhor
|
|
900
|
-
// palpite disponível.
|
|
901
|
-
if (sniffed && sniffed !== mimetype) {
|
|
902
|
-
this.logger.warn(`Upload "${name}" foi anunciado como ${mimetype}, mas os bytes são ${sniffed}. Persistindo o tipo real.`);
|
|
903
|
-
return sniffed;
|
|
904
|
-
}
|
|
905
|
-
}
|
|
1208
|
+
if (mimetype && mimetype.startsWith('image/'))
|
|
906
1209
|
return mimetype;
|
|
907
|
-
}
|
|
908
1210
|
// Tipos concretos não-imagem (video, pdf, ...) são mantidos como estão.
|
|
909
1211
|
if (mimetype && mimetype !== 'application/octet-stream')
|
|
910
1212
|
return mimetype;
|
|
@@ -1017,7 +1319,7 @@ let FileService = FileService_1 = class FileService {
|
|
|
1017
1319
|
* which the storage layer does not normally do — cannot serve stale bytes.
|
|
1018
1320
|
*/
|
|
1019
1321
|
async renderImageVariant(provider, providerPath, contentType, id, size, variant) {
|
|
1020
|
-
var _a,
|
|
1322
|
+
var _a, e_3, _b, _c;
|
|
1021
1323
|
var _d;
|
|
1022
1324
|
const format = (_d = variant.format) !== null && _d !== void 0 ? _d : (contentType === 'image/png'
|
|
1023
1325
|
? 'png'
|
|
@@ -1045,12 +1347,12 @@ let FileService = FileService_1 = class FileService {
|
|
|
1045
1347
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
1046
1348
|
}
|
|
1047
1349
|
}
|
|
1048
|
-
catch (
|
|
1350
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
1049
1351
|
finally {
|
|
1050
1352
|
try {
|
|
1051
1353
|
if (!_f && !_a && (_b = stream_1.return)) await _b.call(stream_1);
|
|
1052
1354
|
}
|
|
1053
|
-
finally { if (
|
|
1355
|
+
finally { if (e_3) throw e_3.error; }
|
|
1054
1356
|
}
|
|
1055
1357
|
const original = Buffer.concat(chunks);
|
|
1056
1358
|
const rendered = await this.imageOptimizationService.resizeBuffer(original, contentType, { width: variant.width, format: variant.format, quality: variant.quality });
|
|
@@ -1113,6 +1415,14 @@ let FileService = FileService_1 = class FileService {
|
|
|
1113
1415
|
}
|
|
1114
1416
|
return url;
|
|
1115
1417
|
}
|
|
1418
|
+
/** Par de `tempURLById`, pela mesma razão: `path` cru resolve para NoSuchKey no S3. */
|
|
1419
|
+
async tempOpenURLById(fileId, expires = 3600) {
|
|
1420
|
+
const url = await this.tempURLById(fileId, expires);
|
|
1421
|
+
if (typeof url === 'string') {
|
|
1422
|
+
return url.replace('/file/download/', '/file/open/');
|
|
1423
|
+
}
|
|
1424
|
+
return url;
|
|
1425
|
+
}
|
|
1116
1426
|
async getTemporaryCredentials(params) {
|
|
1117
1427
|
const stsClient = new client_sts_1.STSClient({
|
|
1118
1428
|
region: params.region,
|
|
@@ -1148,6 +1458,30 @@ let FileService = FileService_1 = class FileService {
|
|
|
1148
1458
|
ETag: result.ETag,
|
|
1149
1459
|
};
|
|
1150
1460
|
}
|
|
1461
|
+
/**
|
|
1462
|
+
* URL assinada de um objeto em bucket avulso.
|
|
1463
|
+
*
|
|
1464
|
+
* O `getFileUrl` do provider resolve arquivos do acervo, que vivem no destino
|
|
1465
|
+
* ativo do core. Este metodo serve para os buckets que outras libraries
|
|
1466
|
+
* configuram por conta propria — o Studio grava no perfil de armazenamento
|
|
1467
|
+
* dele, que pode nao ser o mesmo — e por isso recebe as credenciais e o bucket
|
|
1468
|
+
* de fora, como o `headS3Object` ao lado.
|
|
1469
|
+
*/
|
|
1470
|
+
async signS3Object(params) {
|
|
1471
|
+
var _a;
|
|
1472
|
+
const s3 = new client_s3_1.S3Client({
|
|
1473
|
+
region: params.region,
|
|
1474
|
+
credentials: Object.assign({ accessKeyId: params.accessKeyId, secretAccessKey: params.secretAccessKey }, (params.sessionToken ? { sessionToken: params.sessionToken } : {})),
|
|
1475
|
+
});
|
|
1476
|
+
const command = new client_s3_1.GetObjectCommand(Object.assign({ Bucket: params.bucket, Key: params.key }, (params.downloadFileName
|
|
1477
|
+
? {
|
|
1478
|
+
ResponseContentDisposition: `attachment; filename="${params.downloadFileName.replace(/"/g, '')}"`,
|
|
1479
|
+
}
|
|
1480
|
+
: {})));
|
|
1481
|
+
return (0, s3_request_presigner_1.getSignedUrl)(s3, command, {
|
|
1482
|
+
expiresIn: (_a = params.expiresInSeconds) !== null && _a !== void 0 ? _a : 900,
|
|
1483
|
+
});
|
|
1484
|
+
}
|
|
1151
1485
|
async headS3Bucket(params) {
|
|
1152
1486
|
const s3 = new client_s3_1.S3Client({
|
|
1153
1487
|
region: params.region,
|
|
@@ -1399,6 +1733,32 @@ let FileService = FileService_1 = class FileService {
|
|
|
1399
1733
|
}
|
|
1400
1734
|
};
|
|
1401
1735
|
exports.FileService = FileService;
|
|
1736
|
+
/**
|
|
1737
|
+
* Mimetypes de imagem que `optimizeBuffer` devolve intactos por decisão de projeto
|
|
1738
|
+
* (vetor não vira bitmap, GIF animado não vira quadro único). Enfileirá-los para
|
|
1739
|
+
* reotimização seria custo de download e reprocessamento com resultado garantidamente
|
|
1740
|
+
* nulo, então ficam fora da varredura.
|
|
1741
|
+
*/
|
|
1742
|
+
FileService.NON_OPTIMIZABLE_IMAGE_MIMETYPES = [
|
|
1743
|
+
'image/svg+xml',
|
|
1744
|
+
'image/gif',
|
|
1745
|
+
];
|
|
1746
|
+
/**
|
|
1747
|
+
* Ganho mínimo para valer a regravação de um arquivo que já está no formato final.
|
|
1748
|
+
*
|
|
1749
|
+
* Recomprimir WebP sobre WebP sempre devolve alguns bytes a menos, então um limiar de
|
|
1750
|
+
* "estritamente menor" nunca converge: cada passada da varredura trocaria o arquivo
|
|
1751
|
+
* por um ganho irrisório e mais uma geração de perda de qualidade. Medido aqui, três
|
|
1752
|
+
* passadas seguidas rendiam 10926 → 10664 → 10662 bytes — a última custou uma
|
|
1753
|
+
* recompressão inteira para economizar 2 bytes.
|
|
1754
|
+
*/
|
|
1755
|
+
FileService.REOPTIMIZE_MIN_GAIN_RATIO = 0.1;
|
|
1756
|
+
/**
|
|
1757
|
+
* Papéis que enxergam qualquer arquivo. Os mesmos que já governam as rotas de arquivo
|
|
1758
|
+
* em `route.yaml` — quem administra o acervo pela tela também o administra pelo MCP.
|
|
1759
|
+
*/
|
|
1760
|
+
FileService.FILE_ADMIN_ROLES = ['admin', 'admin-access'];
|
|
1761
|
+
FileService.FILE_ADMIN_CACHE_TTL_MS = 30000;
|
|
1402
1762
|
exports.FileService = FileService = FileService_1 = __decorate([
|
|
1403
1763
|
(0, common_1.Injectable)(),
|
|
1404
1764
|
__param(0, (0, common_1.Inject)((0, common_1.forwardRef)(() => api_prisma_1.PrismaService))),
|